1*609089f2SHongbin Zheng //===------ LoopGenerators.cpp -  IR helper to create loops ---------------===//
2*609089f2SHongbin Zheng //
3*609089f2SHongbin Zheng //                     The LLVM Compiler Infrastructure
4*609089f2SHongbin Zheng //
5*609089f2SHongbin Zheng // This file is distributed under the University of Illinois Open Source
6*609089f2SHongbin Zheng // License. See LICENSE.TXT for details.
7*609089f2SHongbin Zheng //
8*609089f2SHongbin Zheng //===----------------------------------------------------------------------===//
9*609089f2SHongbin Zheng //
10*609089f2SHongbin Zheng // This file contains functions to create scalar and OpenMP parallel loops
11*609089f2SHongbin Zheng // as LLVM-IR.
12*609089f2SHongbin Zheng //
13*609089f2SHongbin Zheng //===----------------------------------------------------------------------===//
14*609089f2SHongbin Zheng 
15*609089f2SHongbin Zheng #include "polly/LoopGenerators.h"
16*609089f2SHongbin Zheng #include "polly/ScopDetection.h"
17*609089f2SHongbin Zheng 
18*609089f2SHongbin Zheng #include "llvm/Module.h"
19*609089f2SHongbin Zheng #include "llvm/Analysis/Dominators.h"
20*609089f2SHongbin Zheng #include "llvm/Target/TargetData.h"
21*609089f2SHongbin Zheng #include "llvm/Transforms/Utils/BasicBlockUtils.h"
22*609089f2SHongbin Zheng 
23*609089f2SHongbin Zheng using namespace llvm;
24*609089f2SHongbin Zheng 
25*609089f2SHongbin Zheng Value *createLoop(Value *LB, Value *UB, Value *Stride,
26*609089f2SHongbin Zheng                   IRBuilder<> *Builder, Pass *P, BasicBlock **AfterBlock) {
27*609089f2SHongbin Zheng   DominatorTree &DT = P->getAnalysis<DominatorTree>();
28*609089f2SHongbin Zheng   Function *F = Builder->GetInsertBlock()->getParent();
29*609089f2SHongbin Zheng   LLVMContext &Context = F->getContext();
30*609089f2SHongbin Zheng 
31*609089f2SHongbin Zheng   BasicBlock *PreheaderBB = Builder->GetInsertBlock();
32*609089f2SHongbin Zheng   BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
33*609089f2SHongbin Zheng   BasicBlock *BodyBB = BasicBlock::Create(Context, "polly.loop_body", F);
34*609089f2SHongbin Zheng   BasicBlock *AfterBB = SplitBlock(PreheaderBB, Builder->GetInsertPoint()++, P);
35*609089f2SHongbin Zheng   AfterBB->setName("polly.loop_after");
36*609089f2SHongbin Zheng 
37*609089f2SHongbin Zheng   PreheaderBB->getTerminator()->setSuccessor(0, HeaderBB);
38*609089f2SHongbin Zheng   DT.addNewBlock(HeaderBB, PreheaderBB);
39*609089f2SHongbin Zheng 
40*609089f2SHongbin Zheng   Builder->SetInsertPoint(HeaderBB);
41*609089f2SHongbin Zheng 
42*609089f2SHongbin Zheng   // Use the type of upper and lower bound.
43*609089f2SHongbin Zheng   assert(LB->getType() == UB->getType()
44*609089f2SHongbin Zheng          && "Different types for upper and lower bound.");
45*609089f2SHongbin Zheng 
46*609089f2SHongbin Zheng   IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType());
47*609089f2SHongbin Zheng   assert(LoopIVType && "UB is not integer?");
48*609089f2SHongbin Zheng 
49*609089f2SHongbin Zheng   // IV
50*609089f2SHongbin Zheng   PHINode *IV = Builder->CreatePHI(LoopIVType, 2, "polly.loopiv");
51*609089f2SHongbin Zheng   IV->addIncoming(LB, PreheaderBB);
52*609089f2SHongbin Zheng 
53*609089f2SHongbin Zheng   Stride = Builder->CreateZExtOrBitCast(Stride, LoopIVType);
54*609089f2SHongbin Zheng   Value *IncrementedIV = Builder->CreateAdd(IV, Stride, "polly.next_loopiv");
55*609089f2SHongbin Zheng 
56*609089f2SHongbin Zheng   // Exit condition.
57*609089f2SHongbin Zheng   Value *CMP;
58*609089f2SHongbin Zheng   CMP = Builder->CreateICmpSLE(IV, UB);
59*609089f2SHongbin Zheng 
60*609089f2SHongbin Zheng   Builder->CreateCondBr(CMP, BodyBB, AfterBB);
61*609089f2SHongbin Zheng   DT.addNewBlock(BodyBB, HeaderBB);
62*609089f2SHongbin Zheng 
63*609089f2SHongbin Zheng   Builder->SetInsertPoint(BodyBB);
64*609089f2SHongbin Zheng   Builder->CreateBr(HeaderBB);
65*609089f2SHongbin Zheng   IV->addIncoming(IncrementedIV, BodyBB);
66*609089f2SHongbin Zheng   DT.changeImmediateDominator(AfterBB, HeaderBB);
67*609089f2SHongbin Zheng 
68*609089f2SHongbin Zheng   Builder->SetInsertPoint(BodyBB->begin());
69*609089f2SHongbin Zheng   *AfterBlock = AfterBB;
70*609089f2SHongbin Zheng 
71*609089f2SHongbin Zheng   return IV;
72*609089f2SHongbin Zheng }
73*609089f2SHongbin Zheng 
74*609089f2SHongbin Zheng void OMPGenerator::createCallParallelLoopStart(Value *SubFunction,
75*609089f2SHongbin Zheng                                                Value *SubfunctionParam,
76*609089f2SHongbin Zheng                                                Value *NumberOfThreads,
77*609089f2SHongbin Zheng                                                Value *LowerBound,
78*609089f2SHongbin Zheng                                                Value *UpperBound,
79*609089f2SHongbin Zheng                                                Value *Stride) {
80*609089f2SHongbin Zheng   Module *M = getModule();
81*609089f2SHongbin Zheng   const char *Name = "GOMP_parallel_loop_runtime_start";
82*609089f2SHongbin Zheng   Function *F = M->getFunction(Name);
83*609089f2SHongbin Zheng 
84*609089f2SHongbin Zheng   // If F is not available, declare it.
85*609089f2SHongbin Zheng   if (!F) {
86*609089f2SHongbin Zheng     Type *LongTy = getIntPtrTy();
87*609089f2SHongbin Zheng     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
88*609089f2SHongbin Zheng 
89*609089f2SHongbin Zheng     Type *Params[] = {
90*609089f2SHongbin Zheng       PointerType::getUnqual(FunctionType::get(Builder.getVoidTy(),
91*609089f2SHongbin Zheng                                                Builder.getInt8PtrTy(),
92*609089f2SHongbin Zheng                                                false)),
93*609089f2SHongbin Zheng       Builder.getInt8PtrTy(),
94*609089f2SHongbin Zheng       Builder.getInt32Ty(),
95*609089f2SHongbin Zheng       LongTy,
96*609089f2SHongbin Zheng       LongTy,
97*609089f2SHongbin Zheng       LongTy,
98*609089f2SHongbin Zheng     };
99*609089f2SHongbin Zheng 
100*609089f2SHongbin Zheng     FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
101*609089f2SHongbin Zheng     F = Function::Create(Ty, Linkage, Name, M);
102*609089f2SHongbin Zheng   }
103*609089f2SHongbin Zheng 
104*609089f2SHongbin Zheng   Value *Args[] = {
105*609089f2SHongbin Zheng     SubFunction,
106*609089f2SHongbin Zheng     SubfunctionParam,
107*609089f2SHongbin Zheng     NumberOfThreads,
108*609089f2SHongbin Zheng     LowerBound,
109*609089f2SHongbin Zheng     UpperBound,
110*609089f2SHongbin Zheng     Stride,
111*609089f2SHongbin Zheng   };
112*609089f2SHongbin Zheng 
113*609089f2SHongbin Zheng   Builder.CreateCall(F, Args);
114*609089f2SHongbin Zheng }
115*609089f2SHongbin Zheng 
116*609089f2SHongbin Zheng Value *OMPGenerator::createCallLoopNext(Value *LowerBoundPtr,
117*609089f2SHongbin Zheng                                         Value *UpperBoundPtr) {
118*609089f2SHongbin Zheng   Module *M = getModule();
119*609089f2SHongbin Zheng   const char *Name = "GOMP_loop_runtime_next";
120*609089f2SHongbin Zheng   Function *F = M->getFunction(Name);
121*609089f2SHongbin Zheng 
122*609089f2SHongbin Zheng   // If F is not available, declare it.
123*609089f2SHongbin Zheng   if (!F) {
124*609089f2SHongbin Zheng     Type *LongPtrTy = PointerType::getUnqual(getIntPtrTy());
125*609089f2SHongbin Zheng     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
126*609089f2SHongbin Zheng 
127*609089f2SHongbin Zheng     Type *Params[] = {
128*609089f2SHongbin Zheng       LongPtrTy,
129*609089f2SHongbin Zheng       LongPtrTy,
130*609089f2SHongbin Zheng     };
131*609089f2SHongbin Zheng 
132*609089f2SHongbin Zheng     FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
133*609089f2SHongbin Zheng     F = Function::Create(Ty, Linkage, Name, M);
134*609089f2SHongbin Zheng   }
135*609089f2SHongbin Zheng 
136*609089f2SHongbin Zheng   Value *Args[] = {
137*609089f2SHongbin Zheng     LowerBoundPtr,
138*609089f2SHongbin Zheng     UpperBoundPtr,
139*609089f2SHongbin Zheng   };
140*609089f2SHongbin Zheng 
141*609089f2SHongbin Zheng   Value *Return = Builder.CreateCall(F, Args);
142*609089f2SHongbin Zheng   Return = Builder.CreateICmpNE(Return, Builder.CreateZExt(Builder.getFalse(),
143*609089f2SHongbin Zheng                                                            Return->getType()));
144*609089f2SHongbin Zheng   return Return;
145*609089f2SHongbin Zheng }
146*609089f2SHongbin Zheng 
147*609089f2SHongbin Zheng void OMPGenerator::createCallParallelEnd() {
148*609089f2SHongbin Zheng   const char *Name = "GOMP_parallel_end";
149*609089f2SHongbin Zheng   Module *M = getModule();
150*609089f2SHongbin Zheng   Function *F = M->getFunction(Name);
151*609089f2SHongbin Zheng 
152*609089f2SHongbin Zheng   // If F is not available, declare it.
153*609089f2SHongbin Zheng   if (!F) {
154*609089f2SHongbin Zheng     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
155*609089f2SHongbin Zheng 
156*609089f2SHongbin Zheng     FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
157*609089f2SHongbin Zheng     F = Function::Create(Ty, Linkage, Name, M);
158*609089f2SHongbin Zheng   }
159*609089f2SHongbin Zheng 
160*609089f2SHongbin Zheng   Builder.CreateCall(F);
161*609089f2SHongbin Zheng }
162*609089f2SHongbin Zheng 
163*609089f2SHongbin Zheng void OMPGenerator::createCallLoopEndNowait() {
164*609089f2SHongbin Zheng   const char *Name = "GOMP_loop_end_nowait";
165*609089f2SHongbin Zheng   Module *M = getModule();
166*609089f2SHongbin Zheng   Function *F = M->getFunction(Name);
167*609089f2SHongbin Zheng 
168*609089f2SHongbin Zheng   // If F is not available, declare it.
169*609089f2SHongbin Zheng   if (!F) {
170*609089f2SHongbin Zheng     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
171*609089f2SHongbin Zheng 
172*609089f2SHongbin Zheng     FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
173*609089f2SHongbin Zheng     F = Function::Create(Ty, Linkage, Name, M);
174*609089f2SHongbin Zheng   }
175*609089f2SHongbin Zheng 
176*609089f2SHongbin Zheng   Builder.CreateCall(F);
177*609089f2SHongbin Zheng }
178*609089f2SHongbin Zheng 
179*609089f2SHongbin Zheng IntegerType *OMPGenerator::getIntPtrTy() {
180*609089f2SHongbin Zheng   return P->getAnalysis<TargetData>().getIntPtrType(Builder.getContext());
181*609089f2SHongbin Zheng }
182*609089f2SHongbin Zheng 
183*609089f2SHongbin Zheng Module *OMPGenerator::getModule() {
184*609089f2SHongbin Zheng   return Builder.GetInsertBlock()->getParent()->getParent();
185*609089f2SHongbin Zheng }
186*609089f2SHongbin Zheng 
187*609089f2SHongbin Zheng Function *OMPGenerator::createSubfunctionDefinition() {
188*609089f2SHongbin Zheng   Module *M = getModule();
189*609089f2SHongbin Zheng   Function *F = Builder.GetInsertBlock()->getParent();
190*609089f2SHongbin Zheng   std::vector<Type*> Arguments(1, Builder.getInt8PtrTy());
191*609089f2SHongbin Zheng   FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
192*609089f2SHongbin Zheng   Function *FN = Function::Create(FT, Function::InternalLinkage,
193*609089f2SHongbin Zheng                                   F->getName() + ".omp_subfn", M);
194*609089f2SHongbin Zheng   // Do not run any polly pass on the new function.
195*609089f2SHongbin Zheng   P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
196*609089f2SHongbin Zheng 
197*609089f2SHongbin Zheng   Function::arg_iterator AI = FN->arg_begin();
198*609089f2SHongbin Zheng   AI->setName("omp.userContext");
199*609089f2SHongbin Zheng 
200*609089f2SHongbin Zheng   return FN;
201*609089f2SHongbin Zheng }
202*609089f2SHongbin Zheng 
203*609089f2SHongbin Zheng Value *OMPGenerator::loadValuesIntoStruct(SetVector<Value*> &Values) {
204*609089f2SHongbin Zheng   std::vector<Type*> Members;
205*609089f2SHongbin Zheng 
206*609089f2SHongbin Zheng   for (unsigned i = 0; i < Values.size(); i++)
207*609089f2SHongbin Zheng     Members.push_back(Values[i]->getType());
208*609089f2SHongbin Zheng 
209*609089f2SHongbin Zheng   StructType *Ty = StructType::get(Builder.getContext(), Members);
210*609089f2SHongbin Zheng   Value *Struct = Builder.CreateAlloca(Ty, 0, "omp.userContext");
211*609089f2SHongbin Zheng 
212*609089f2SHongbin Zheng   for (unsigned i = 0; i < Values.size(); i++) {
213*609089f2SHongbin Zheng     Value *Address = Builder.CreateStructGEP(Struct, i);
214*609089f2SHongbin Zheng     Builder.CreateStore(Values[i], Address);
215*609089f2SHongbin Zheng   }
216*609089f2SHongbin Zheng 
217*609089f2SHongbin Zheng   return Struct;
218*609089f2SHongbin Zheng }
219*609089f2SHongbin Zheng 
220*609089f2SHongbin Zheng void OMPGenerator::extractValuesFromStruct(SetVector<Value*> OldValues,
221*609089f2SHongbin Zheng                                            Value *Struct,
222*609089f2SHongbin Zheng                                            ValueToValueMapTy &Map) {
223*609089f2SHongbin Zheng   for (unsigned i = 0; i < OldValues.size(); i++) {
224*609089f2SHongbin Zheng     Value *Address = Builder.CreateStructGEP(Struct, i);
225*609089f2SHongbin Zheng     Value *NewValue = Builder.CreateLoad(Address);
226*609089f2SHongbin Zheng     Map.insert(std::make_pair<Value*, Value*>(OldValues[i], NewValue));
227*609089f2SHongbin Zheng   }
228*609089f2SHongbin Zheng }
229*609089f2SHongbin Zheng 
230*609089f2SHongbin Zheng Value *OMPGenerator::createSubfunction(Value *Stride, Value *StructData,
231*609089f2SHongbin Zheng                                        SetVector<Value*> Data,
232*609089f2SHongbin Zheng                                        ValueToValueMapTy &Map,
233*609089f2SHongbin Zheng                                        Function **SubFunction) {
234*609089f2SHongbin Zheng   Function *FN = createSubfunctionDefinition();
235*609089f2SHongbin Zheng 
236*609089f2SHongbin Zheng   BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *LoadIVBoundsBB,
237*609089f2SHongbin Zheng              *AfterBB;
238*609089f2SHongbin Zheng   Value *LowerBoundPtr, *UpperBoundPtr, *UserContext, *Ret1, *HasNextSchedule,
239*609089f2SHongbin Zheng         *LowerBound, *UpperBound, *IV;
240*609089f2SHongbin Zheng   Type *IntPtrTy = getIntPtrTy();
241*609089f2SHongbin Zheng   LLVMContext &Context = FN->getContext();
242*609089f2SHongbin Zheng 
243*609089f2SHongbin Zheng   // Store the previous basic block.
244*609089f2SHongbin Zheng   PrevBB = Builder.GetInsertBlock();
245*609089f2SHongbin Zheng 
246*609089f2SHongbin Zheng   // Create basic blocks.
247*609089f2SHongbin Zheng   HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
248*609089f2SHongbin Zheng   ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
249*609089f2SHongbin Zheng   CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
250*609089f2SHongbin Zheng   LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds", FN);
251*609089f2SHongbin Zheng 
252*609089f2SHongbin Zheng   DominatorTree &DT = P->getAnalysis<DominatorTree>();
253*609089f2SHongbin Zheng   DT.addNewBlock(HeaderBB, PrevBB);
254*609089f2SHongbin Zheng   DT.addNewBlock(ExitBB, HeaderBB);
255*609089f2SHongbin Zheng   DT.addNewBlock(CheckNextBB, HeaderBB);
256*609089f2SHongbin Zheng   DT.addNewBlock(LoadIVBoundsBB, HeaderBB);
257*609089f2SHongbin Zheng 
258*609089f2SHongbin Zheng   // Fill up basic block HeaderBB.
259*609089f2SHongbin Zheng   Builder.SetInsertPoint(HeaderBB);
260*609089f2SHongbin Zheng   LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr");
261*609089f2SHongbin Zheng   UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr");
262*609089f2SHongbin Zheng   UserContext = Builder.CreateBitCast(FN->arg_begin(), StructData->getType(),
263*609089f2SHongbin Zheng                                       "omp.userContext");
264*609089f2SHongbin Zheng 
265*609089f2SHongbin Zheng   extractValuesFromStruct(Data, UserContext, Map);
266*609089f2SHongbin Zheng   Builder.CreateBr(CheckNextBB);
267*609089f2SHongbin Zheng 
268*609089f2SHongbin Zheng   // Add code to check if another set of iterations will be executed.
269*609089f2SHongbin Zheng   Builder.SetInsertPoint(CheckNextBB);
270*609089f2SHongbin Zheng   Ret1 = createCallLoopNext(LowerBoundPtr, UpperBoundPtr);
271*609089f2SHongbin Zheng   HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
272*609089f2SHongbin Zheng                                         "omp.hasNextScheduleBlock");
273*609089f2SHongbin Zheng   Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB);
274*609089f2SHongbin Zheng 
275*609089f2SHongbin Zheng   // Add code to to load the iv bounds for this set of iterations.
276*609089f2SHongbin Zheng   Builder.SetInsertPoint(LoadIVBoundsBB);
277*609089f2SHongbin Zheng   LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound");
278*609089f2SHongbin Zheng   UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound");
279*609089f2SHongbin Zheng 
280*609089f2SHongbin Zheng   // Subtract one as the upper bound provided by openmp is a < comparison
281*609089f2SHongbin Zheng   // whereas the codegenForSequential function creates a <= comparison.
282*609089f2SHongbin Zheng   UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1),
283*609089f2SHongbin Zheng                                  "omp.upperBoundAdjusted");
284*609089f2SHongbin Zheng 
285*609089f2SHongbin Zheng   Builder.CreateBr(CheckNextBB);
286*609089f2SHongbin Zheng   Builder.SetInsertPoint(--Builder.GetInsertPoint());
287*609089f2SHongbin Zheng   IV = createLoop(LowerBound, UpperBound, Stride, &Builder, P, &AfterBB);
288*609089f2SHongbin Zheng 
289*609089f2SHongbin Zheng   BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
290*609089f2SHongbin Zheng   Builder.SetInsertPoint(AfterBB->begin());
291*609089f2SHongbin Zheng 
292*609089f2SHongbin Zheng   // Add code to terminate this openmp subfunction.
293*609089f2SHongbin Zheng   Builder.SetInsertPoint(ExitBB);
294*609089f2SHongbin Zheng   createCallLoopEndNowait();
295*609089f2SHongbin Zheng   Builder.CreateRetVoid();
296*609089f2SHongbin Zheng 
297*609089f2SHongbin Zheng   Builder.SetInsertPoint(LoopBody);
298*609089f2SHongbin Zheng   *SubFunction = FN;
299*609089f2SHongbin Zheng 
300*609089f2SHongbin Zheng   return IV;
301*609089f2SHongbin Zheng }
302*609089f2SHongbin Zheng 
303*609089f2SHongbin Zheng Value *OMPGenerator::createParallelLoop(Value *LowerBound, Value *UpperBound,
304*609089f2SHongbin Zheng                                         Value *Stride,
305*609089f2SHongbin Zheng                                         SetVector<Value*> &Values,
306*609089f2SHongbin Zheng                                         ValueToValueMapTy &Map,
307*609089f2SHongbin Zheng                                         BasicBlock::iterator *LoopBody) {
308*609089f2SHongbin Zheng   Value *Struct, *IV, *SubfunctionParam, *NumberOfThreads;
309*609089f2SHongbin Zheng   Function *SubFunction;
310*609089f2SHongbin Zheng 
311*609089f2SHongbin Zheng   Struct = loadValuesIntoStruct(Values);
312*609089f2SHongbin Zheng 
313*609089f2SHongbin Zheng   BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
314*609089f2SHongbin Zheng   IV = createSubfunction(Stride, Struct, Values, Map, &SubFunction);
315*609089f2SHongbin Zheng   *LoopBody = Builder.GetInsertPoint();
316*609089f2SHongbin Zheng   Builder.SetInsertPoint(PrevInsertPoint);
317*609089f2SHongbin Zheng 
318*609089f2SHongbin Zheng   // Create call for GOMP_parallel_loop_runtime_start.
319*609089f2SHongbin Zheng   SubfunctionParam = Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(),
320*609089f2SHongbin Zheng                                            "omp_data");
321*609089f2SHongbin Zheng 
322*609089f2SHongbin Zheng   NumberOfThreads = Builder.getInt32(0);
323*609089f2SHongbin Zheng 
324*609089f2SHongbin Zheng   // Add one as the upper bound provided by openmp is a < comparison
325*609089f2SHongbin Zheng   // whereas the codegenForSequential function creates a <= comparison.
326*609089f2SHongbin Zheng   UpperBound = Builder.CreateAdd(UpperBound,
327*609089f2SHongbin Zheng                                  ConstantInt::get(getIntPtrTy(), 1));
328*609089f2SHongbin Zheng 
329*609089f2SHongbin Zheng   createCallParallelLoopStart(SubFunction, SubfunctionParam, NumberOfThreads,
330*609089f2SHongbin Zheng                               LowerBound, UpperBound, Stride);
331*609089f2SHongbin Zheng   Builder.CreateCall(SubFunction, SubfunctionParam);
332*609089f2SHongbin Zheng   createCallParallelEnd();
333*609089f2SHongbin Zheng 
334*609089f2SHongbin Zheng   return IV;
335*609089f2SHongbin Zheng }
336