1 //===- llvm/unittest/IR/OpenMPIRBuilderTest.cpp - OpenMPIRBuilder tests ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Frontend/OpenMP/OMPConstants.h"
10 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
11 #include "llvm/IR/BasicBlock.h"
12 #include "llvm/IR/DIBuilder.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/InstIterator.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Verifier.h"
18 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
19 #include "gtest/gtest.h"
20 
21 using namespace llvm;
22 using namespace omp;
23 
24 namespace {
25 
26 /// Create an instruction that uses the values in \p Values. We use "printf"
27 /// just because it is often used for this purpose in test code, but it is never
28 /// executed here.
29 static CallInst *createPrintfCall(IRBuilder<> &Builder, StringRef FormatStr,
30                                   ArrayRef<Value *> Values) {
31   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
32 
33   GlobalVariable *GV = Builder.CreateGlobalString(FormatStr, "", 0, M);
34   Constant *Zero = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0);
35   Constant *Indices[] = {Zero, Zero};
36   Constant *FormatStrConst =
37       ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, Indices);
38 
39   Function *PrintfDecl = M->getFunction("printf");
40   if (!PrintfDecl) {
41     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
42     FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true);
43     PrintfDecl = Function::Create(Ty, Linkage, "printf", M);
44   }
45 
46   SmallVector<Value *, 4> Args;
47   Args.push_back(FormatStrConst);
48   Args.append(Values.begin(), Values.end());
49   return Builder.CreateCall(PrintfDecl, Args);
50 }
51 
52 /// Verify that blocks in \p RefOrder are corresponds to the depth-first visit
53 /// order the control flow of \p F.
54 ///
55 /// This is an easy way to verify the branching structure of the CFG without
56 /// checking every branch instruction individually. For the CFG of a
57 /// CanonicalLoopInfo, the Cond BB's terminating branch's first edge is entering
58 /// the body, i.e. the DFS order corresponds to the execution order with one
59 /// loop iteration.
60 static testing::AssertionResult
61 verifyDFSOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) {
62   ArrayRef<BasicBlock *>::iterator It = RefOrder.begin();
63   ArrayRef<BasicBlock *>::iterator E = RefOrder.end();
64 
65   df_iterator_default_set<BasicBlock *, 16> Visited;
66   auto DFS = llvm::depth_first_ext(&F->getEntryBlock(), Visited);
67 
68   BasicBlock *Prev = nullptr;
69   for (BasicBlock *BB : DFS) {
70     if (It != E && BB == *It) {
71       Prev = *It;
72       ++It;
73     }
74   }
75 
76   if (It == E)
77     return testing::AssertionSuccess();
78   if (!Prev)
79     return testing::AssertionFailure()
80            << "Did not find " << (*It)->getName() << " in control flow";
81   return testing::AssertionFailure()
82          << "Expected " << Prev->getName() << " before " << (*It)->getName()
83          << " in control flow";
84 }
85 
86 /// Verify that blocks in \p RefOrder are in the same relative order in the
87 /// linked lists of blocks in \p F. The linked list may contain additional
88 /// blocks in-between.
89 ///
90 /// While the order in the linked list is not relevant for semantics, keeping
91 /// the order roughly in execution order makes its printout easier to read.
92 static testing::AssertionResult
93 verifyListOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) {
94   ArrayRef<BasicBlock *>::iterator It = RefOrder.begin();
95   ArrayRef<BasicBlock *>::iterator E = RefOrder.end();
96 
97   BasicBlock *Prev = nullptr;
98   for (BasicBlock &BB : *F) {
99     if (It != E && &BB == *It) {
100       Prev = *It;
101       ++It;
102     }
103   }
104 
105   if (It == E)
106     return testing::AssertionSuccess();
107   if (!Prev)
108     return testing::AssertionFailure() << "Did not find " << (*It)->getName()
109                                        << " in function " << F->getName();
110   return testing::AssertionFailure()
111          << "Expected " << Prev->getName() << " before " << (*It)->getName()
112          << " in function " << F->getName();
113 }
114 
115 class OpenMPIRBuilderTest : public testing::Test {
116 protected:
117   void SetUp() override {
118     M.reset(new Module("MyModule", Ctx));
119     FunctionType *FTy =
120         FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
121                           /*isVarArg=*/false);
122     F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
123     BB = BasicBlock::Create(Ctx, "", F);
124 
125     DIBuilder DIB(*M);
126     auto File = DIB.createFile("test.dbg", "/src", llvm::None,
127                                Optional<StringRef>("/src/test.dbg"));
128     auto CU =
129         DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0);
130     auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
131     auto SP = DIB.createFunction(
132         CU, "foo", "", File, 1, Type, 1, DINode::FlagZero,
133         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
134     F->setSubprogram(SP);
135     auto Scope = DIB.createLexicalBlockFile(SP, File, 0);
136     DIB.finalize();
137     DL = DILocation::get(Ctx, 3, 7, Scope);
138   }
139 
140   void TearDown() override {
141     BB = nullptr;
142     M.reset();
143   }
144 
145   LLVMContext Ctx;
146   std::unique_ptr<Module> M;
147   Function *F;
148   BasicBlock *BB;
149   DebugLoc DL;
150 };
151 
152 class OpenMPIRBuilderTestWithParams
153     : public OpenMPIRBuilderTest,
154       public ::testing::WithParamInterface<omp::OMPScheduleType> {};
155 
156 // Returns the value stored in the given allocation. Returns null if the given
157 // value is not a result of an allocation, if no value is stored or if there is
158 // more than one store.
159 static Value *findStoredValue(Value *AllocaValue) {
160   Instruction *Alloca = dyn_cast<AllocaInst>(AllocaValue);
161   if (!Alloca)
162     return nullptr;
163   StoreInst *Store = nullptr;
164   for (Use &U : Alloca->uses()) {
165     if (auto *CandidateStore = dyn_cast<StoreInst>(U.getUser())) {
166       EXPECT_EQ(Store, nullptr);
167       Store = CandidateStore;
168     }
169   }
170   if (!Store)
171     return nullptr;
172   return Store->getValueOperand();
173 }
174 
175 TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
176   OpenMPIRBuilder OMPBuilder(*M);
177   OMPBuilder.initialize();
178 
179   IRBuilder<> Builder(BB);
180 
181   OMPBuilder.createBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
182   EXPECT_TRUE(M->global_empty());
183   EXPECT_EQ(M->size(), 1U);
184   EXPECT_EQ(F->size(), 1U);
185   EXPECT_EQ(BB->size(), 0U);
186 
187   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
188   OMPBuilder.createBarrier(Loc, OMPD_for);
189   EXPECT_FALSE(M->global_empty());
190   EXPECT_EQ(M->size(), 3U);
191   EXPECT_EQ(F->size(), 1U);
192   EXPECT_EQ(BB->size(), 2U);
193 
194   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
195   EXPECT_NE(GTID, nullptr);
196   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
197   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
198   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
199   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
200 
201   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
202   EXPECT_NE(Barrier, nullptr);
203   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
204   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
205   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
206   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
207 
208   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
209 
210   Builder.CreateUnreachable();
211   EXPECT_FALSE(verifyModule(*M, &errs()));
212 }
213 
214 TEST_F(OpenMPIRBuilderTest, CreateCancel) {
215   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
216   OpenMPIRBuilder OMPBuilder(*M);
217   OMPBuilder.initialize();
218 
219   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
220   new UnreachableInst(Ctx, CBB);
221   auto FiniCB = [&](InsertPointTy IP) {
222     ASSERT_NE(IP.getBlock(), nullptr);
223     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
224     BranchInst::Create(CBB, IP.getBlock());
225   };
226   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
227 
228   IRBuilder<> Builder(BB);
229 
230   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
231   auto NewIP = OMPBuilder.createCancel(Loc, nullptr, OMPD_parallel);
232   Builder.restoreIP(NewIP);
233   EXPECT_FALSE(M->global_empty());
234   EXPECT_EQ(M->size(), 3U);
235   EXPECT_EQ(F->size(), 4U);
236   EXPECT_EQ(BB->size(), 4U);
237 
238   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
239   EXPECT_NE(GTID, nullptr);
240   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
241   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
242   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
243   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
244 
245   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
246   EXPECT_NE(Cancel, nullptr);
247   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
248   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
249   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
250   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
251   EXPECT_EQ(Cancel->getNumUses(), 1U);
252   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
253   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
254   EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
255   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
256   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
257             1U);
258   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
259             CBB);
260 
261   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
262 
263   OMPBuilder.popFinalizationCB();
264 
265   Builder.CreateUnreachable();
266   EXPECT_FALSE(verifyModule(*M, &errs()));
267 }
268 
269 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
270   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
271   OpenMPIRBuilder OMPBuilder(*M);
272   OMPBuilder.initialize();
273 
274   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
275   new UnreachableInst(Ctx, CBB);
276   auto FiniCB = [&](InsertPointTy IP) {
277     ASSERT_NE(IP.getBlock(), nullptr);
278     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
279     BranchInst::Create(CBB, IP.getBlock());
280   };
281   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
282 
283   IRBuilder<> Builder(BB);
284 
285   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
286   auto NewIP = OMPBuilder.createCancel(Loc, Builder.getTrue(), OMPD_parallel);
287   Builder.restoreIP(NewIP);
288   EXPECT_FALSE(M->global_empty());
289   EXPECT_EQ(M->size(), 3U);
290   EXPECT_EQ(F->size(), 7U);
291   EXPECT_EQ(BB->size(), 1U);
292   ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
293   ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
294   BB = BB->getTerminator()->getSuccessor(0);
295   EXPECT_EQ(BB->size(), 4U);
296 
297 
298   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
299   EXPECT_NE(GTID, nullptr);
300   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
301   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
302   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
303   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
304 
305   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
306   EXPECT_NE(Cancel, nullptr);
307   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
308   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
309   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
310   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
311   EXPECT_EQ(Cancel->getNumUses(), 1U);
312   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
313   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
314   EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
315   EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock());
316   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
317   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
318             1U);
319   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
320             CBB);
321 
322   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
323 
324   OMPBuilder.popFinalizationCB();
325 
326   Builder.CreateUnreachable();
327   EXPECT_FALSE(verifyModule(*M, &errs()));
328 }
329 
330 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
331   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
332   OpenMPIRBuilder OMPBuilder(*M);
333   OMPBuilder.initialize();
334 
335   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
336   new UnreachableInst(Ctx, CBB);
337   auto FiniCB = [&](InsertPointTy IP) {
338     ASSERT_NE(IP.getBlock(), nullptr);
339     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
340     BranchInst::Create(CBB, IP.getBlock());
341   };
342   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
343 
344   IRBuilder<> Builder(BB);
345 
346   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
347   auto NewIP = OMPBuilder.createBarrier(Loc, OMPD_for);
348   Builder.restoreIP(NewIP);
349   EXPECT_FALSE(M->global_empty());
350   EXPECT_EQ(M->size(), 3U);
351   EXPECT_EQ(F->size(), 4U);
352   EXPECT_EQ(BB->size(), 4U);
353 
354   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
355   EXPECT_NE(GTID, nullptr);
356   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
357   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
358   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
359   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
360 
361   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
362   EXPECT_NE(Barrier, nullptr);
363   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
364   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
365   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
366   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
367   EXPECT_EQ(Barrier->getNumUses(), 1U);
368   Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
369   EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
370   EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
371   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
372   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
373             1U);
374   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
375             CBB);
376 
377   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
378 
379   OMPBuilder.popFinalizationCB();
380 
381   Builder.CreateUnreachable();
382   EXPECT_FALSE(verifyModule(*M, &errs()));
383 }
384 
385 TEST_F(OpenMPIRBuilderTest, DbgLoc) {
386   OpenMPIRBuilder OMPBuilder(*M);
387   OMPBuilder.initialize();
388   F->setName("func");
389 
390   IRBuilder<> Builder(BB);
391 
392   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
393   OMPBuilder.createBarrier(Loc, OMPD_for);
394   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
395   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
396   EXPECT_EQ(GTID->getDebugLoc(), DL);
397   EXPECT_EQ(Barrier->getDebugLoc(), DL);
398   EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
399   if (!isa<GlobalVariable>(Barrier->getOperand(0)))
400     return;
401   GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
402   EXPECT_TRUE(Ident->hasInitializer());
403   if (!Ident->hasInitializer())
404     return;
405   Constant *Initializer = Ident->getInitializer();
406   EXPECT_TRUE(
407       isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
408   GlobalVariable *SrcStrGlob =
409       cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
410   if (!SrcStrGlob)
411     return;
412   EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
413   ConstantDataArray *SrcSrc =
414       dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
415   if (!SrcSrc)
416     return;
417   EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;");
418 }
419 
420 TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
421   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
422   OpenMPIRBuilder OMPBuilder(*M);
423   OMPBuilder.initialize();
424   F->setName("func");
425   IRBuilder<> Builder(BB);
426 
427   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
428 
429   AllocaInst *PrivAI = nullptr;
430 
431   unsigned NumBodiesGenerated = 0;
432   unsigned NumPrivatizedVars = 0;
433   unsigned NumFinalizationPoints = 0;
434 
435   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
436                        BasicBlock &ContinuationIP) {
437     ++NumBodiesGenerated;
438 
439     Builder.restoreIP(AllocaIP);
440     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
441     Builder.CreateStore(F->arg_begin(), PrivAI);
442 
443     Builder.restoreIP(CodeGenIP);
444     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
445                                          "local.use");
446     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
447     Instruction *ThenTerm, *ElseTerm;
448     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
449                                   &ThenTerm, &ElseTerm);
450 
451     Builder.SetInsertPoint(ThenTerm);
452     Builder.CreateBr(&ContinuationIP);
453     ThenTerm->eraseFromParent();
454   };
455 
456   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
457                     Value &Orig, Value &Inner,
458                     Value *&ReplacementValue) -> InsertPointTy {
459     ++NumPrivatizedVars;
460 
461     if (!isa<AllocaInst>(Orig)) {
462       EXPECT_EQ(&Orig, F->arg_begin());
463       ReplacementValue = &Inner;
464       return CodeGenIP;
465     }
466 
467     // Since the original value is an allocation, it has a pointer type and
468     // therefore no additional wrapping should happen.
469     EXPECT_EQ(&Orig, &Inner);
470 
471     // Trivial copy (=firstprivate).
472     Builder.restoreIP(AllocaIP);
473     Type *VTy = Inner.getType()->getPointerElementType();
474     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
475     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
476     Builder.restoreIP(CodeGenIP);
477     Builder.CreateStore(V, ReplacementValue);
478     return CodeGenIP;
479   };
480 
481   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
482 
483   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
484                                     F->getEntryBlock().getFirstInsertionPt());
485   IRBuilder<>::InsertPoint AfterIP =
486       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
487                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
488   EXPECT_EQ(NumBodiesGenerated, 1U);
489   EXPECT_EQ(NumPrivatizedVars, 1U);
490   EXPECT_EQ(NumFinalizationPoints, 1U);
491 
492   Builder.restoreIP(AfterIP);
493   Builder.CreateRetVoid();
494 
495   OMPBuilder.finalize();
496 
497   EXPECT_NE(PrivAI, nullptr);
498   Function *OutlinedFn = PrivAI->getFunction();
499   EXPECT_NE(F, OutlinedFn);
500   EXPECT_FALSE(verifyModule(*M, &errs()));
501   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
502   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
503   EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
504   EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
505 
506   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
507   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
508 
509   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
510   EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
511   User *Usr = OutlinedFn->user_back();
512   ASSERT_TRUE(isa<ConstantExpr>(Usr));
513   CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
514   ASSERT_NE(ForkCI, nullptr);
515 
516   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
517   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
518   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
519   EXPECT_EQ(ForkCI->getArgOperand(1),
520             ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
521   EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
522   EXPECT_EQ(findStoredValue(ForkCI->getArgOperand(3)), F->arg_begin());
523 }
524 
525 TEST_F(OpenMPIRBuilderTest, ParallelNested) {
526   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
527   OpenMPIRBuilder OMPBuilder(*M);
528   OMPBuilder.initialize();
529   F->setName("func");
530   IRBuilder<> Builder(BB);
531 
532   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
533 
534   unsigned NumInnerBodiesGenerated = 0;
535   unsigned NumOuterBodiesGenerated = 0;
536   unsigned NumFinalizationPoints = 0;
537 
538   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
539                             BasicBlock &ContinuationIP) {
540     ++NumInnerBodiesGenerated;
541   };
542 
543   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
544                     Value &Orig, Value &Inner,
545                     Value *&ReplacementValue) -> InsertPointTy {
546     // Trivial copy (=firstprivate).
547     Builder.restoreIP(AllocaIP);
548     Type *VTy = Inner.getType()->getPointerElementType();
549     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
550     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
551     Builder.restoreIP(CodeGenIP);
552     Builder.CreateStore(V, ReplacementValue);
553     return CodeGenIP;
554   };
555 
556   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
557 
558   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
559                             BasicBlock &ContinuationIP) {
560     ++NumOuterBodiesGenerated;
561     Builder.restoreIP(CodeGenIP);
562     BasicBlock *CGBB = CodeGenIP.getBlock();
563     BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint());
564     CGBB->getTerminator()->eraseFromParent();
565     ;
566 
567     IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel(
568         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
569         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
570 
571     Builder.restoreIP(AfterIP);
572     Builder.CreateBr(NewBB);
573   };
574 
575   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
576                                     F->getEntryBlock().getFirstInsertionPt());
577   IRBuilder<>::InsertPoint AfterIP =
578       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
579                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
580 
581   EXPECT_EQ(NumInnerBodiesGenerated, 1U);
582   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
583   EXPECT_EQ(NumFinalizationPoints, 2U);
584 
585   Builder.restoreIP(AfterIP);
586   Builder.CreateRetVoid();
587 
588   OMPBuilder.finalize();
589 
590   EXPECT_EQ(M->size(), 5U);
591   for (Function &OutlinedFn : *M) {
592     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
593       continue;
594     EXPECT_FALSE(verifyModule(*M, &errs()));
595     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
596     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
597     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
598     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
599 
600     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
601     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
602 
603     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
604     User *Usr = OutlinedFn.user_back();
605     ASSERT_TRUE(isa<ConstantExpr>(Usr));
606     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
607     ASSERT_NE(ForkCI, nullptr);
608 
609     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
610     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
611     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
612     EXPECT_EQ(ForkCI->getArgOperand(1),
613               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
614     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
615   }
616 }
617 
618 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) {
619   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
620   OpenMPIRBuilder OMPBuilder(*M);
621   OMPBuilder.initialize();
622   F->setName("func");
623   IRBuilder<> Builder(BB);
624 
625   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
626 
627   unsigned NumInnerBodiesGenerated = 0;
628   unsigned NumOuterBodiesGenerated = 0;
629   unsigned NumFinalizationPoints = 0;
630 
631   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
632                             BasicBlock &ContinuationIP) {
633     ++NumInnerBodiesGenerated;
634   };
635 
636   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
637                     Value &Orig, Value &Inner,
638                     Value *&ReplacementValue) -> InsertPointTy {
639     // Trivial copy (=firstprivate).
640     Builder.restoreIP(AllocaIP);
641     Type *VTy = Inner.getType()->getPointerElementType();
642     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
643     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
644     Builder.restoreIP(CodeGenIP);
645     Builder.CreateStore(V, ReplacementValue);
646     return CodeGenIP;
647   };
648 
649   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
650 
651   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
652                             BasicBlock &ContinuationIP) {
653     ++NumOuterBodiesGenerated;
654     Builder.restoreIP(CodeGenIP);
655     BasicBlock *CGBB = CodeGenIP.getBlock();
656     BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint());
657     BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt());
658     CGBB->getTerminator()->eraseFromParent();
659     ;
660     NewBB1->getTerminator()->eraseFromParent();
661     ;
662 
663     IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel(
664         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
665         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
666 
667     Builder.restoreIP(AfterIP1);
668     Builder.CreateBr(NewBB1);
669 
670     IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel(
671         InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB,
672         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
673 
674     Builder.restoreIP(AfterIP2);
675     Builder.CreateBr(NewBB2);
676   };
677 
678   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
679                                     F->getEntryBlock().getFirstInsertionPt());
680   IRBuilder<>::InsertPoint AfterIP =
681       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
682                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
683 
684   EXPECT_EQ(NumInnerBodiesGenerated, 2U);
685   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
686   EXPECT_EQ(NumFinalizationPoints, 3U);
687 
688   Builder.restoreIP(AfterIP);
689   Builder.CreateRetVoid();
690 
691   OMPBuilder.finalize();
692 
693   EXPECT_EQ(M->size(), 6U);
694   for (Function &OutlinedFn : *M) {
695     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
696       continue;
697     EXPECT_FALSE(verifyModule(*M, &errs()));
698     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
699     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
700     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
701     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
702 
703     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
704     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
705 
706     unsigned NumAllocas = 0;
707     for (Instruction &I : instructions(OutlinedFn))
708       NumAllocas += isa<AllocaInst>(I);
709     EXPECT_EQ(NumAllocas, 1U);
710 
711     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
712     User *Usr = OutlinedFn.user_back();
713     ASSERT_TRUE(isa<ConstantExpr>(Usr));
714     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
715     ASSERT_NE(ForkCI, nullptr);
716 
717     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
718     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
719     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
720     EXPECT_EQ(ForkCI->getArgOperand(1),
721               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
722     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
723   }
724 }
725 
726 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
727   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
728   OpenMPIRBuilder OMPBuilder(*M);
729   OMPBuilder.initialize();
730   F->setName("func");
731   IRBuilder<> Builder(BB);
732 
733   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
734 
735   AllocaInst *PrivAI = nullptr;
736 
737   unsigned NumBodiesGenerated = 0;
738   unsigned NumPrivatizedVars = 0;
739   unsigned NumFinalizationPoints = 0;
740 
741   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
742                        BasicBlock &ContinuationIP) {
743     ++NumBodiesGenerated;
744 
745     Builder.restoreIP(AllocaIP);
746     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
747     Builder.CreateStore(F->arg_begin(), PrivAI);
748 
749     Builder.restoreIP(CodeGenIP);
750     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
751                                          "local.use");
752     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
753     Instruction *ThenTerm, *ElseTerm;
754     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
755                                   &ThenTerm, &ElseTerm);
756 
757     Builder.SetInsertPoint(ThenTerm);
758     Builder.CreateBr(&ContinuationIP);
759     ThenTerm->eraseFromParent();
760   };
761 
762   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
763                     Value &Orig, Value &Inner,
764                     Value *&ReplacementValue) -> InsertPointTy {
765     ++NumPrivatizedVars;
766 
767     if (!isa<AllocaInst>(Orig)) {
768       EXPECT_EQ(&Orig, F->arg_begin());
769       ReplacementValue = &Inner;
770       return CodeGenIP;
771     }
772 
773     // Since the original value is an allocation, it has a pointer type and
774     // therefore no additional wrapping should happen.
775     EXPECT_EQ(&Orig, &Inner);
776 
777     // Trivial copy (=firstprivate).
778     Builder.restoreIP(AllocaIP);
779     Type *VTy = Inner.getType()->getPointerElementType();
780     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
781     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
782     Builder.restoreIP(CodeGenIP);
783     Builder.CreateStore(V, ReplacementValue);
784     return CodeGenIP;
785   };
786 
787   auto FiniCB = [&](InsertPointTy CodeGenIP) {
788     ++NumFinalizationPoints;
789     // No destructors.
790   };
791 
792   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
793                                     F->getEntryBlock().getFirstInsertionPt());
794   IRBuilder<>::InsertPoint AfterIP =
795       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
796                                 Builder.CreateIsNotNull(F->arg_begin()),
797                                 nullptr, OMP_PROC_BIND_default, false);
798 
799   EXPECT_EQ(NumBodiesGenerated, 1U);
800   EXPECT_EQ(NumPrivatizedVars, 1U);
801   EXPECT_EQ(NumFinalizationPoints, 1U);
802 
803   Builder.restoreIP(AfterIP);
804   Builder.CreateRetVoid();
805   OMPBuilder.finalize();
806 
807   EXPECT_NE(PrivAI, nullptr);
808   Function *OutlinedFn = PrivAI->getFunction();
809   EXPECT_NE(F, OutlinedFn);
810   EXPECT_FALSE(verifyModule(*M, &errs()));
811 
812   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
813   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
814 
815   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
816   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
817 
818   CallInst *DirectCI = nullptr;
819   CallInst *ForkCI = nullptr;
820   for (User *Usr : OutlinedFn->users()) {
821     if (isa<CallInst>(Usr)) {
822       ASSERT_EQ(DirectCI, nullptr);
823       DirectCI = cast<CallInst>(Usr);
824     } else {
825       ASSERT_TRUE(isa<ConstantExpr>(Usr));
826       ASSERT_EQ(Usr->getNumUses(), 1U);
827       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
828       ForkCI = cast<CallInst>(Usr->user_back());
829     }
830   }
831 
832   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
833   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
834   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
835   EXPECT_EQ(ForkCI->getArgOperand(1),
836             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
837   Value *StoredForkArg = findStoredValue(ForkCI->getArgOperand(3));
838   EXPECT_EQ(StoredForkArg, F->arg_begin());
839 
840   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
841   EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
842   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
843   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
844   Value *StoredDirectArg = findStoredValue(DirectCI->getArgOperand(2));
845   EXPECT_EQ(StoredDirectArg, F->arg_begin());
846 }
847 
848 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
849   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
850   OpenMPIRBuilder OMPBuilder(*M);
851   OMPBuilder.initialize();
852   F->setName("func");
853   IRBuilder<> Builder(BB);
854 
855   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
856 
857   unsigned NumBodiesGenerated = 0;
858   unsigned NumPrivatizedVars = 0;
859   unsigned NumFinalizationPoints = 0;
860 
861   CallInst *CheckedBarrier = nullptr;
862   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
863                        BasicBlock &ContinuationIP) {
864     ++NumBodiesGenerated;
865 
866     Builder.restoreIP(CodeGenIP);
867 
868     // Create three barriers, two cancel barriers but only one checked.
869     Function *CBFn, *BFn;
870 
871     Builder.restoreIP(
872         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel));
873 
874     CBFn = M->getFunction("__kmpc_cancel_barrier");
875     BFn = M->getFunction("__kmpc_barrier");
876     ASSERT_NE(CBFn, nullptr);
877     ASSERT_EQ(BFn, nullptr);
878     ASSERT_EQ(CBFn->getNumUses(), 1U);
879     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
880     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
881     CheckedBarrier = cast<CallInst>(CBFn->user_back());
882 
883     Builder.restoreIP(
884         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true));
885     CBFn = M->getFunction("__kmpc_cancel_barrier");
886     BFn = M->getFunction("__kmpc_barrier");
887     ASSERT_NE(CBFn, nullptr);
888     ASSERT_NE(BFn, nullptr);
889     ASSERT_EQ(CBFn->getNumUses(), 1U);
890     ASSERT_EQ(BFn->getNumUses(), 1U);
891     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
892     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
893 
894     Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel,
895                                                false, false));
896     ASSERT_EQ(CBFn->getNumUses(), 2U);
897     ASSERT_EQ(BFn->getNumUses(), 1U);
898     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
899     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
900     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
901   };
902 
903   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &,
904                     Value *&) -> InsertPointTy {
905     ++NumPrivatizedVars;
906     llvm_unreachable("No privatization callback call expected!");
907   };
908 
909   FunctionType *FakeDestructorTy =
910       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
911                         /*isVarArg=*/false);
912   auto *FakeDestructor = Function::Create(
913       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
914 
915   auto FiniCB = [&](InsertPointTy IP) {
916     ++NumFinalizationPoints;
917     Builder.restoreIP(IP);
918     Builder.CreateCall(FakeDestructor,
919                        {Builder.getInt32(NumFinalizationPoints)});
920   };
921 
922   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
923                                     F->getEntryBlock().getFirstInsertionPt());
924   IRBuilder<>::InsertPoint AfterIP =
925       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
926                                 Builder.CreateIsNotNull(F->arg_begin()),
927                                 nullptr, OMP_PROC_BIND_default, true);
928 
929   EXPECT_EQ(NumBodiesGenerated, 1U);
930   EXPECT_EQ(NumPrivatizedVars, 0U);
931   EXPECT_EQ(NumFinalizationPoints, 2U);
932   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
933 
934   Builder.restoreIP(AfterIP);
935   Builder.CreateRetVoid();
936   OMPBuilder.finalize();
937 
938   EXPECT_FALSE(verifyModule(*M, &errs()));
939 
940   BasicBlock *ExitBB = nullptr;
941   for (const User *Usr : FakeDestructor->users()) {
942     const CallInst *CI = dyn_cast<CallInst>(Usr);
943     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
944     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
945     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
946     if (ExitBB)
947       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
948     else
949       ExitBB = CI->getNextNode()->getSuccessor(0);
950     ASSERT_EQ(ExitBB->size(), 1U);
951     if (!isa<ReturnInst>(ExitBB->front())) {
952       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
953       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
954       ASSERT_TRUE(isa<ReturnInst>(
955           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
956     }
957   }
958 }
959 
960 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) {
961   OpenMPIRBuilder OMPBuilder(*M);
962   OMPBuilder.initialize();
963   F->setName("func");
964   IRBuilder<> Builder(BB);
965   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
966   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
967 
968   Type *I32Ty = Type::getInt32Ty(M->getContext());
969   Type *I32PtrTy = Type::getInt32PtrTy(M->getContext());
970   Type *StructTy = StructType::get(I32Ty, I32PtrTy);
971   Type *StructPtrTy = StructTy->getPointerTo();
972   Type *VoidTy = Type::getVoidTy(M->getContext());
973   FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty);
974   FunctionCallee TakeI32Func =
975       M->getOrInsertFunction("take_i32", VoidTy, I32Ty);
976   FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy);
977   FunctionCallee TakeI32PtrFunc =
978       M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy);
979   FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy);
980   FunctionCallee TakeStructFunc =
981       M->getOrInsertFunction("take_struct", VoidTy, StructTy);
982   FunctionCallee RetStructPtrFunc =
983       M->getOrInsertFunction("ret_structptr", StructPtrTy);
984   FunctionCallee TakeStructPtrFunc =
985       M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy);
986   Value *I32Val = Builder.CreateCall(RetI32Func);
987   Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc);
988   Value *StructVal = Builder.CreateCall(RetStructFunc);
989   Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc);
990 
991   Instruction *Internal;
992   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
993                        BasicBlock &ContinuationBB) {
994     IRBuilder<>::InsertPointGuard Guard(Builder);
995     Builder.restoreIP(CodeGenIP);
996     Internal = Builder.CreateCall(TakeI32Func, I32Val);
997     Builder.CreateCall(TakeI32PtrFunc, I32PtrVal);
998     Builder.CreateCall(TakeStructFunc, StructVal);
999     Builder.CreateCall(TakeStructPtrFunc, StructPtrVal);
1000   };
1001   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &,
1002                     Value &Inner, Value *&ReplacementValue) {
1003     ReplacementValue = &Inner;
1004     return CodeGenIP;
1005   };
1006   auto FiniCB = [](InsertPointTy) {};
1007 
1008   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
1009                                     F->getEntryBlock().getFirstInsertionPt());
1010   IRBuilder<>::InsertPoint AfterIP =
1011       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1012                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
1013   Builder.restoreIP(AfterIP);
1014   Builder.CreateRetVoid();
1015 
1016   OMPBuilder.finalize();
1017 
1018   EXPECT_FALSE(verifyModule(*M, &errs()));
1019   Function *OutlinedFn = Internal->getFunction();
1020 
1021   Type *Arg2Type = OutlinedFn->getArg(2)->getType();
1022   EXPECT_TRUE(Arg2Type->isPointerTy());
1023   EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty);
1024 
1025   // Arguments that need to be passed through pointers and reloaded will get
1026   // used earlier in the functions and therefore will appear first in the
1027   // argument list after outlining.
1028   Type *Arg3Type = OutlinedFn->getArg(3)->getType();
1029   EXPECT_TRUE(Arg3Type->isPointerTy());
1030   EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy);
1031 
1032   Type *Arg4Type = OutlinedFn->getArg(4)->getType();
1033   EXPECT_EQ(Arg4Type, I32PtrTy);
1034 
1035   Type *Arg5Type = OutlinedFn->getArg(5)->getType();
1036   EXPECT_EQ(Arg5Type, StructPtrTy);
1037 }
1038 
1039 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) {
1040   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1041   OpenMPIRBuilder OMPBuilder(*M);
1042   OMPBuilder.initialize();
1043   IRBuilder<> Builder(BB);
1044   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1045   Value *TripCount = F->getArg(0);
1046 
1047   unsigned NumBodiesGenerated = 0;
1048   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
1049     NumBodiesGenerated += 1;
1050 
1051     Builder.restoreIP(CodeGenIP);
1052 
1053     Value *Cmp = Builder.CreateICmpEQ(LC, TripCount);
1054     Instruction *ThenTerm, *ElseTerm;
1055     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
1056                                   &ThenTerm, &ElseTerm);
1057   };
1058 
1059   CanonicalLoopInfo *Loop =
1060       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
1061 
1062   Builder.restoreIP(Loop->getAfterIP());
1063   ReturnInst *RetInst = Builder.CreateRetVoid();
1064   OMPBuilder.finalize();
1065 
1066   Loop->assertOK();
1067   EXPECT_FALSE(verifyModule(*M, &errs()));
1068 
1069   EXPECT_EQ(NumBodiesGenerated, 1U);
1070 
1071   // Verify control flow structure (in addition to Loop->assertOK()).
1072   EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock());
1073   EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock());
1074 
1075   Instruction *IndVar = Loop->getIndVar();
1076   EXPECT_TRUE(isa<PHINode>(IndVar));
1077   EXPECT_EQ(IndVar->getType(), TripCount->getType());
1078   EXPECT_EQ(IndVar->getParent(), Loop->getHeader());
1079 
1080   EXPECT_EQ(Loop->getTripCount(), TripCount);
1081 
1082   BasicBlock *Body = Loop->getBody();
1083   Instruction *CmpInst = &Body->getInstList().front();
1084   EXPECT_TRUE(isa<ICmpInst>(CmpInst));
1085   EXPECT_EQ(CmpInst->getOperand(0), IndVar);
1086 
1087   BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor();
1088   EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) {
1089     return SuccBB->getSingleSuccessor() == LatchPred;
1090   }));
1091 
1092   EXPECT_EQ(&Loop->getAfter()->front(), RetInst);
1093 }
1094 
1095 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) {
1096   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1097   OpenMPIRBuilder OMPBuilder(*M);
1098   OMPBuilder.initialize();
1099   IRBuilder<> Builder(BB);
1100 
1101   // Check the trip count is computed correctly. We generate the canonical loop
1102   // but rely on the IRBuilder's constant folder to compute the final result
1103   // since all inputs are constant. To verify overflow situations, limit the
1104   // trip count / loop counter widths to 16 bits.
1105   auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1106                            bool IsSigned, bool InclusiveStop) -> int64_t {
1107     OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1108     Type *LCTy = Type::getInt16Ty(Ctx);
1109     Value *StartVal = ConstantInt::get(LCTy, Start);
1110     Value *StopVal = ConstantInt::get(LCTy, Stop);
1111     Value *StepVal = ConstantInt::get(LCTy, Step);
1112     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1113     CanonicalLoopInfo *Loop =
1114         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1115                                        StepVal, IsSigned, InclusiveStop);
1116     Loop->assertOK();
1117     Builder.restoreIP(Loop->getAfterIP());
1118     Value *TripCount = Loop->getTripCount();
1119     return cast<ConstantInt>(TripCount)->getValue().getZExtValue();
1120   };
1121 
1122   EXPECT_EQ(EvalTripCount(0, 0, 1, false, false), 0);
1123   EXPECT_EQ(EvalTripCount(0, 1, 2, false, false), 1);
1124   EXPECT_EQ(EvalTripCount(0, 42, 1, false, false), 42);
1125   EXPECT_EQ(EvalTripCount(0, 42, 2, false, false), 21);
1126   EXPECT_EQ(EvalTripCount(21, 42, 1, false, false), 21);
1127   EXPECT_EQ(EvalTripCount(0, 5, 5, false, false), 1);
1128   EXPECT_EQ(EvalTripCount(0, 9, 5, false, false), 2);
1129   EXPECT_EQ(EvalTripCount(0, 11, 5, false, false), 3);
1130   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF);
1131   EXPECT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0);
1132   EXPECT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1);
1133   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100);
1134   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1);
1135 
1136   EXPECT_EQ(EvalTripCount(0, 6, 5, false, false), 2);
1137   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2);
1138   EXPECT_EQ(EvalTripCount(0, 0, 1, false, true), 1);
1139   EXPECT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1);
1140   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF);
1141   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000);
1142 
1143   EXPECT_EQ(EvalTripCount(0, 0, -1, true, false), 0);
1144   EXPECT_EQ(EvalTripCount(0, 1, -1, true, true), 0);
1145   EXPECT_EQ(EvalTripCount(20, 5, -5, true, false), 3);
1146   EXPECT_EQ(EvalTripCount(20, 5, -5, true, true), 4);
1147   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, false), 1);
1148   EXPECT_EQ(EvalTripCount(-4, -3, 2, true, false), 1);
1149   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, true), 2);
1150 
1151   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000);
1152   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001);
1153   EXPECT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF);
1154   EXPECT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF);
1155   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2);
1156   EXPECT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF);
1157   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000);
1158   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800);
1159   EXPECT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF);
1160   EXPECT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1);
1161   EXPECT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2);
1162 
1163   // Finalize the function and verify it.
1164   Builder.CreateRetVoid();
1165   OMPBuilder.finalize();
1166   EXPECT_FALSE(verifyModule(*M, &errs()));
1167 }
1168 
1169 TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) {
1170   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1171   OpenMPIRBuilder OMPBuilder(*M);
1172   OMPBuilder.initialize();
1173   F->setName("func");
1174 
1175   IRBuilder<> Builder(BB);
1176 
1177   Type *LCTy = F->getArg(0)->getType();
1178   Constant *One = ConstantInt::get(LCTy, 1);
1179   Constant *Two = ConstantInt::get(LCTy, 2);
1180   Value *OuterTripCount =
1181       Builder.CreateAdd(F->getArg(0), Two, "tripcount.outer");
1182   Value *InnerTripCount =
1183       Builder.CreateAdd(F->getArg(0), One, "tripcount.inner");
1184 
1185   // Fix an insertion point for ComputeIP.
1186   BasicBlock *LoopNextEnter =
1187       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1188                          Builder.GetInsertBlock()->getNextNode());
1189   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1190   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1191 
1192   Builder.SetInsertPoint(LoopNextEnter);
1193   OpenMPIRBuilder::LocationDescription OuterLoc(Builder.saveIP(), DL);
1194 
1195   CanonicalLoopInfo *InnerLoop = nullptr;
1196   CallInst *InbetweenLead = nullptr;
1197   CallInst *InbetweenTrail = nullptr;
1198   CallInst *Call = nullptr;
1199   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, Value *OuterLC) {
1200     Builder.restoreIP(OuterCodeGenIP);
1201     InbetweenLead =
1202         createPrintfCall(Builder, "In-between lead i=%d\\n", {OuterLC});
1203 
1204     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1205                                   Value *InnerLC) {
1206       Builder.restoreIP(InnerCodeGenIP);
1207       Call = createPrintfCall(Builder, "body i=%d j=%d\\n", {OuterLC, InnerLC});
1208     };
1209     InnerLoop = OMPBuilder.createCanonicalLoop(
1210         Builder.saveIP(), InnerLoopBodyGenCB, InnerTripCount, "inner");
1211 
1212     Builder.restoreIP(InnerLoop->getAfterIP());
1213     InbetweenTrail =
1214         createPrintfCall(Builder, "In-between trail i=%d\\n", {OuterLC});
1215   };
1216   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1217       OuterLoc, OuterLoopBodyGenCB, OuterTripCount, "outer");
1218 
1219   // Finish the function.
1220   Builder.restoreIP(OuterLoop->getAfterIP());
1221   Builder.CreateRetVoid();
1222 
1223   CanonicalLoopInfo *Collapsed =
1224       OMPBuilder.collapseLoops(DL, {OuterLoop, InnerLoop}, ComputeIP);
1225 
1226   OMPBuilder.finalize();
1227   EXPECT_FALSE(verifyModule(*M, &errs()));
1228 
1229   // Verify control flow and BB order.
1230   BasicBlock *RefOrder[] = {
1231       Collapsed->getPreheader(),   Collapsed->getHeader(),
1232       Collapsed->getCond(),        Collapsed->getBody(),
1233       InbetweenLead->getParent(),  Call->getParent(),
1234       InbetweenTrail->getParent(), Collapsed->getLatch(),
1235       Collapsed->getExit(),        Collapsed->getAfter(),
1236   };
1237   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1238   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1239 
1240   // Verify the total trip count.
1241   auto *TripCount = cast<MulOperator>(Collapsed->getTripCount());
1242   EXPECT_EQ(TripCount->getOperand(0), OuterTripCount);
1243   EXPECT_EQ(TripCount->getOperand(1), InnerTripCount);
1244 
1245   // Verify the changed indvar.
1246   auto *OuterIV = cast<BinaryOperator>(Call->getOperand(1));
1247   EXPECT_EQ(OuterIV->getOpcode(), Instruction::UDiv);
1248   EXPECT_EQ(OuterIV->getParent(), Collapsed->getBody());
1249   EXPECT_EQ(OuterIV->getOperand(1), InnerTripCount);
1250   EXPECT_EQ(OuterIV->getOperand(0), Collapsed->getIndVar());
1251 
1252   auto *InnerIV = cast<BinaryOperator>(Call->getOperand(2));
1253   EXPECT_EQ(InnerIV->getOpcode(), Instruction::URem);
1254   EXPECT_EQ(InnerIV->getParent(), Collapsed->getBody());
1255   EXPECT_EQ(InnerIV->getOperand(0), Collapsed->getIndVar());
1256   EXPECT_EQ(InnerIV->getOperand(1), InnerTripCount);
1257 
1258   EXPECT_EQ(InbetweenLead->getOperand(1), OuterIV);
1259   EXPECT_EQ(InbetweenTrail->getOperand(1), OuterIV);
1260 }
1261 
1262 TEST_F(OpenMPIRBuilderTest, TileSingleLoop) {
1263   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1264   OpenMPIRBuilder OMPBuilder(*M);
1265   OMPBuilder.initialize();
1266   F->setName("func");
1267 
1268   IRBuilder<> Builder(BB);
1269   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1270   Value *TripCount = F->getArg(0);
1271 
1272   BasicBlock *BodyCode = nullptr;
1273   Instruction *Call = nullptr;
1274   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
1275     Builder.restoreIP(CodeGenIP);
1276     BodyCode = Builder.GetInsertBlock();
1277 
1278     // Add something that consumes the induction variable to the body.
1279     Call = createPrintfCall(Builder, "%d\\n", {LC});
1280   };
1281   CanonicalLoopInfo *Loop =
1282       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
1283 
1284   // Finalize the function.
1285   Builder.restoreIP(Loop->getAfterIP());
1286   Builder.CreateRetVoid();
1287 
1288   Instruction *OrigIndVar = Loop->getIndVar();
1289   EXPECT_EQ(Call->getOperand(1), OrigIndVar);
1290 
1291   // Tile the loop.
1292   Constant *TileSize = ConstantInt::get(Loop->getIndVarType(), APInt(32, 7));
1293   std::vector<CanonicalLoopInfo *> GenLoops =
1294       OMPBuilder.tileLoops(DL, {Loop}, {TileSize});
1295 
1296   OMPBuilder.finalize();
1297   EXPECT_FALSE(verifyModule(*M, &errs()));
1298 
1299   EXPECT_EQ(GenLoops.size(), 2u);
1300   CanonicalLoopInfo *Floor = GenLoops[0];
1301   CanonicalLoopInfo *Tile = GenLoops[1];
1302 
1303   BasicBlock *RefOrder[] = {
1304       Floor->getPreheader(), Floor->getHeader(),   Floor->getCond(),
1305       Floor->getBody(),      Tile->getPreheader(), Tile->getHeader(),
1306       Tile->getCond(),       Tile->getBody(),      BodyCode,
1307       Tile->getLatch(),      Tile->getExit(),      Tile->getAfter(),
1308       Floor->getLatch(),     Floor->getExit(),     Floor->getAfter(),
1309   };
1310   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1311   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1312 
1313   // Check the induction variable.
1314   EXPECT_EQ(Call->getParent(), BodyCode);
1315   auto *Shift = cast<AddOperator>(Call->getOperand(1));
1316   EXPECT_EQ(cast<Instruction>(Shift)->getParent(), Tile->getBody());
1317   EXPECT_EQ(Shift->getOperand(1), Tile->getIndVar());
1318   auto *Scale = cast<MulOperator>(Shift->getOperand(0));
1319   EXPECT_EQ(cast<Instruction>(Scale)->getParent(), Tile->getBody());
1320   EXPECT_EQ(Scale->getOperand(0), TileSize);
1321   EXPECT_EQ(Scale->getOperand(1), Floor->getIndVar());
1322 }
1323 
1324 TEST_F(OpenMPIRBuilderTest, TileNestedLoops) {
1325   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1326   OpenMPIRBuilder OMPBuilder(*M);
1327   OMPBuilder.initialize();
1328   F->setName("func");
1329 
1330   IRBuilder<> Builder(BB);
1331   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1332   Value *TripCount = F->getArg(0);
1333   Type *LCTy = TripCount->getType();
1334 
1335   BasicBlock *BodyCode = nullptr;
1336   CanonicalLoopInfo *InnerLoop = nullptr;
1337   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1338                                 llvm::Value *OuterLC) {
1339     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1340                                   llvm::Value *InnerLC) {
1341       Builder.restoreIP(InnerCodeGenIP);
1342       BodyCode = Builder.GetInsertBlock();
1343 
1344       // Add something that consumes the induction variables to the body.
1345       createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1346     };
1347     InnerLoop = OMPBuilder.createCanonicalLoop(
1348         OuterCodeGenIP, InnerLoopBodyGenCB, TripCount, "inner");
1349   };
1350   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1351       Loc, OuterLoopBodyGenCB, TripCount, "outer");
1352 
1353   // Finalize the function.
1354   Builder.restoreIP(OuterLoop->getAfterIP());
1355   Builder.CreateRetVoid();
1356 
1357   // Tile to loop nest.
1358   Constant *OuterTileSize = ConstantInt::get(LCTy, APInt(32, 11));
1359   Constant *InnerTileSize = ConstantInt::get(LCTy, APInt(32, 7));
1360   std::vector<CanonicalLoopInfo *> GenLoops = OMPBuilder.tileLoops(
1361       DL, {OuterLoop, InnerLoop}, {OuterTileSize, InnerTileSize});
1362 
1363   OMPBuilder.finalize();
1364   EXPECT_FALSE(verifyModule(*M, &errs()));
1365 
1366   EXPECT_EQ(GenLoops.size(), 4u);
1367   CanonicalLoopInfo *Floor1 = GenLoops[0];
1368   CanonicalLoopInfo *Floor2 = GenLoops[1];
1369   CanonicalLoopInfo *Tile1 = GenLoops[2];
1370   CanonicalLoopInfo *Tile2 = GenLoops[3];
1371 
1372   BasicBlock *RefOrder[] = {
1373       Floor1->getPreheader(),
1374       Floor1->getHeader(),
1375       Floor1->getCond(),
1376       Floor1->getBody(),
1377       Floor2->getPreheader(),
1378       Floor2->getHeader(),
1379       Floor2->getCond(),
1380       Floor2->getBody(),
1381       Tile1->getPreheader(),
1382       Tile1->getHeader(),
1383       Tile1->getCond(),
1384       Tile1->getBody(),
1385       Tile2->getPreheader(),
1386       Tile2->getHeader(),
1387       Tile2->getCond(),
1388       Tile2->getBody(),
1389       BodyCode,
1390       Tile2->getLatch(),
1391       Tile2->getExit(),
1392       Tile2->getAfter(),
1393       Tile1->getLatch(),
1394       Tile1->getExit(),
1395       Tile1->getAfter(),
1396       Floor2->getLatch(),
1397       Floor2->getExit(),
1398       Floor2->getAfter(),
1399       Floor1->getLatch(),
1400       Floor1->getExit(),
1401       Floor1->getAfter(),
1402   };
1403   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1404   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1405 }
1406 
1407 TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) {
1408   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1409   OpenMPIRBuilder OMPBuilder(*M);
1410   OMPBuilder.initialize();
1411   F->setName("func");
1412 
1413   IRBuilder<> Builder(BB);
1414   Value *TripCount = F->getArg(0);
1415   Type *LCTy = TripCount->getType();
1416 
1417   Value *OuterStartVal = ConstantInt::get(LCTy, 2);
1418   Value *OuterStopVal = TripCount;
1419   Value *OuterStep = ConstantInt::get(LCTy, 5);
1420   Value *InnerStartVal = ConstantInt::get(LCTy, 13);
1421   Value *InnerStopVal = TripCount;
1422   Value *InnerStep = ConstantInt::get(LCTy, 3);
1423 
1424   // Fix an insertion point for ComputeIP.
1425   BasicBlock *LoopNextEnter =
1426       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1427                          Builder.GetInsertBlock()->getNextNode());
1428   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1429   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1430 
1431   InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()};
1432   OpenMPIRBuilder::LocationDescription Loc({LoopIP, DL});
1433 
1434   BasicBlock *BodyCode = nullptr;
1435   CanonicalLoopInfo *InnerLoop = nullptr;
1436   CallInst *Call = nullptr;
1437   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1438                                 llvm::Value *OuterLC) {
1439     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1440                                   llvm::Value *InnerLC) {
1441       Builder.restoreIP(InnerCodeGenIP);
1442       BodyCode = Builder.GetInsertBlock();
1443 
1444       // Add something that consumes the induction variable to the body.
1445       Call = createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1446     };
1447     InnerLoop = OMPBuilder.createCanonicalLoop(
1448         OuterCodeGenIP, InnerLoopBodyGenCB, InnerStartVal, InnerStopVal,
1449         InnerStep, false, false, ComputeIP, "inner");
1450   };
1451   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1452       Loc, OuterLoopBodyGenCB, OuterStartVal, OuterStopVal, OuterStep, false,
1453       false, ComputeIP, "outer");
1454 
1455   // Finalize the function
1456   Builder.restoreIP(OuterLoop->getAfterIP());
1457   Builder.CreateRetVoid();
1458 
1459   // Tile the loop nest.
1460   Constant *TileSize0 = ConstantInt::get(LCTy, APInt(32, 11));
1461   Constant *TileSize1 = ConstantInt::get(LCTy, APInt(32, 7));
1462   std::vector<CanonicalLoopInfo *> GenLoops =
1463       OMPBuilder.tileLoops(DL, {OuterLoop, InnerLoop}, {TileSize0, TileSize1});
1464 
1465   OMPBuilder.finalize();
1466   EXPECT_FALSE(verifyModule(*M, &errs()));
1467 
1468   EXPECT_EQ(GenLoops.size(), 4u);
1469   CanonicalLoopInfo *Floor0 = GenLoops[0];
1470   CanonicalLoopInfo *Floor1 = GenLoops[1];
1471   CanonicalLoopInfo *Tile0 = GenLoops[2];
1472   CanonicalLoopInfo *Tile1 = GenLoops[3];
1473 
1474   BasicBlock *RefOrder[] = {
1475       Floor0->getPreheader(),
1476       Floor0->getHeader(),
1477       Floor0->getCond(),
1478       Floor0->getBody(),
1479       Floor1->getPreheader(),
1480       Floor1->getHeader(),
1481       Floor1->getCond(),
1482       Floor1->getBody(),
1483       Tile0->getPreheader(),
1484       Tile0->getHeader(),
1485       Tile0->getCond(),
1486       Tile0->getBody(),
1487       Tile1->getPreheader(),
1488       Tile1->getHeader(),
1489       Tile1->getCond(),
1490       Tile1->getBody(),
1491       BodyCode,
1492       Tile1->getLatch(),
1493       Tile1->getExit(),
1494       Tile1->getAfter(),
1495       Tile0->getLatch(),
1496       Tile0->getExit(),
1497       Tile0->getAfter(),
1498       Floor1->getLatch(),
1499       Floor1->getExit(),
1500       Floor1->getAfter(),
1501       Floor0->getLatch(),
1502       Floor0->getExit(),
1503       Floor0->getAfter(),
1504   };
1505   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1506   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1507 
1508   EXPECT_EQ(Call->getParent(), BodyCode);
1509 
1510   auto *RangeShift0 = cast<AddOperator>(Call->getOperand(1));
1511   EXPECT_EQ(RangeShift0->getOperand(1), OuterStartVal);
1512   auto *RangeScale0 = cast<MulOperator>(RangeShift0->getOperand(0));
1513   EXPECT_EQ(RangeScale0->getOperand(1), OuterStep);
1514   auto *TileShift0 = cast<AddOperator>(RangeScale0->getOperand(0));
1515   EXPECT_EQ(cast<Instruction>(TileShift0)->getParent(), Tile1->getBody());
1516   EXPECT_EQ(TileShift0->getOperand(1), Tile0->getIndVar());
1517   auto *TileScale0 = cast<MulOperator>(TileShift0->getOperand(0));
1518   EXPECT_EQ(cast<Instruction>(TileScale0)->getParent(), Tile1->getBody());
1519   EXPECT_EQ(TileScale0->getOperand(0), TileSize0);
1520   EXPECT_EQ(TileScale0->getOperand(1), Floor0->getIndVar());
1521 
1522   auto *RangeShift1 = cast<AddOperator>(Call->getOperand(2));
1523   EXPECT_EQ(cast<Instruction>(RangeShift1)->getParent(), BodyCode);
1524   EXPECT_EQ(RangeShift1->getOperand(1), InnerStartVal);
1525   auto *RangeScale1 = cast<MulOperator>(RangeShift1->getOperand(0));
1526   EXPECT_EQ(cast<Instruction>(RangeScale1)->getParent(), BodyCode);
1527   EXPECT_EQ(RangeScale1->getOperand(1), InnerStep);
1528   auto *TileShift1 = cast<AddOperator>(RangeScale1->getOperand(0));
1529   EXPECT_EQ(cast<Instruction>(TileShift1)->getParent(), Tile1->getBody());
1530   EXPECT_EQ(TileShift1->getOperand(1), Tile1->getIndVar());
1531   auto *TileScale1 = cast<MulOperator>(TileShift1->getOperand(0));
1532   EXPECT_EQ(cast<Instruction>(TileScale1)->getParent(), Tile1->getBody());
1533   EXPECT_EQ(TileScale1->getOperand(0), TileSize1);
1534   EXPECT_EQ(TileScale1->getOperand(1), Floor1->getIndVar());
1535 }
1536 
1537 TEST_F(OpenMPIRBuilderTest, TileSingleLoopCounts) {
1538   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1539   OpenMPIRBuilder OMPBuilder(*M);
1540   OMPBuilder.initialize();
1541   IRBuilder<> Builder(BB);
1542 
1543   // Create a loop, tile it, and extract its trip count. All input values are
1544   // constant and IRBuilder evaluates all-constant arithmetic inplace, such that
1545   // the floor trip count itself will be a ConstantInt. Unfortunately we cannot
1546   // do the same for the tile loop.
1547   auto GetFloorCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1548                            bool IsSigned, bool InclusiveStop,
1549                            int64_t TileSize) -> uint64_t {
1550     OpenMPIRBuilder::LocationDescription Loc(Builder.saveIP(), DL);
1551     Type *LCTy = Type::getInt16Ty(Ctx);
1552     Value *StartVal = ConstantInt::get(LCTy, Start);
1553     Value *StopVal = ConstantInt::get(LCTy, Stop);
1554     Value *StepVal = ConstantInt::get(LCTy, Step);
1555 
1556     // Generate a loop.
1557     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1558     CanonicalLoopInfo *Loop =
1559         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1560                                        StepVal, IsSigned, InclusiveStop);
1561 
1562     // Tile the loop.
1563     Value *TileSizeVal = ConstantInt::get(LCTy, TileSize);
1564     std::vector<CanonicalLoopInfo *> GenLoops =
1565         OMPBuilder.tileLoops(Loc.DL, {Loop}, {TileSizeVal});
1566 
1567     // Set the insertion pointer to after loop, where the next loop will be
1568     // emitted.
1569     Builder.restoreIP(Loop->getAfterIP());
1570 
1571     // Extract the trip count.
1572     CanonicalLoopInfo *FloorLoop = GenLoops[0];
1573     Value *FloorTripCount = FloorLoop->getTripCount();
1574     return cast<ConstantInt>(FloorTripCount)->getValue().getZExtValue();
1575   };
1576 
1577   // Empty iteration domain.
1578   EXPECT_EQ(GetFloorCount(0, 0, 1, false, false, 7), 0u);
1579   EXPECT_EQ(GetFloorCount(0, -1, 1, false, true, 7), 0u);
1580   EXPECT_EQ(GetFloorCount(-1, -1, -1, true, false, 7), 0u);
1581   EXPECT_EQ(GetFloorCount(-1, 0, -1, true, true, 7), 0u);
1582   EXPECT_EQ(GetFloorCount(-1, -1, 3, true, false, 7), 0u);
1583 
1584   // Only complete tiles.
1585   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1586   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1587   EXPECT_EQ(GetFloorCount(1, 15, 1, false, false, 7), 2u);
1588   EXPECT_EQ(GetFloorCount(0, -14, -1, true, false, 7), 2u);
1589   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, true, 7), 2u);
1590   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 2, 3, false, false, 7), 2u);
1591 
1592   // Only a partial tile.
1593   EXPECT_EQ(GetFloorCount(0, 1, 1, false, false, 7), 1u);
1594   EXPECT_EQ(GetFloorCount(0, 6, 1, false, false, 7), 1u);
1595   EXPECT_EQ(GetFloorCount(-1, 1, 3, true, false, 7), 1u);
1596   EXPECT_EQ(GetFloorCount(-1, -2, -1, true, false, 7), 1u);
1597   EXPECT_EQ(GetFloorCount(0, 2, 3, false, false, 7), 1u);
1598 
1599   // Complete and partial tiles.
1600   EXPECT_EQ(GetFloorCount(0, 13, 1, false, false, 7), 2u);
1601   EXPECT_EQ(GetFloorCount(0, 15, 1, false, false, 7), 3u);
1602   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, false, 7), 2u);
1603   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 5 - 1, 3, false, false, 7), 5u);
1604   EXPECT_EQ(GetFloorCount(-1, -3 * 7 * 5, -3, true, false, 7), 5u);
1605 
1606   // Close to 16-bit integer range.
1607   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 1), 0xFFFFu);
1608   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 7), 0xFFFFu / 7 + 1);
1609   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, true, 7), 0xFFFFu / 7 + 1);
1610   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 7), 0xFFFFu / 7 + 1);
1611   EXPECT_EQ(GetFloorCount(-0x7FFF, 0x7FFF, 1, true, true, 7), 0xFFFFu / 7 + 1);
1612   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, false, 0xFFFF), 1u);
1613   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 0xFFFF), 1u);
1614 
1615   // Finalize the function.
1616   Builder.CreateRetVoid();
1617   OMPBuilder.finalize();
1618 
1619   EXPECT_FALSE(verifyModule(*M, &errs()));
1620 }
1621 
1622 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) {
1623   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1624   OpenMPIRBuilder OMPBuilder(*M);
1625   OMPBuilder.initialize();
1626   IRBuilder<> Builder(BB);
1627   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1628 
1629   Type *LCTy = Type::getInt32Ty(Ctx);
1630   Value *StartVal = ConstantInt::get(LCTy, 10);
1631   Value *StopVal = ConstantInt::get(LCTy, 52);
1632   Value *StepVal = ConstantInt::get(LCTy, 2);
1633   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1634 
1635   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1636       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1637       /*IsSigned=*/false, /*InclusiveStop=*/false);
1638 
1639   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1640   InsertPointTy AllocaIP = Builder.saveIP();
1641 
1642   CLI = OMPBuilder.createStaticWorkshareLoop(Loc, CLI, AllocaIP,
1643                                              /*NeedsBarrier=*/true);
1644   auto AllocaIter = BB->begin();
1645   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1646   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1647   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1648   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1649   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1650   EXPECT_NE(PLastIter, nullptr);
1651   EXPECT_NE(PLowerBound, nullptr);
1652   EXPECT_NE(PUpperBound, nullptr);
1653   EXPECT_NE(PStride, nullptr);
1654 
1655   auto PreheaderIter = CLI->getPreheader()->begin();
1656   ASSERT_GE(
1657       std::distance(CLI->getPreheader()->begin(), CLI->getPreheader()->end()),
1658       7);
1659   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1660   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1661   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1662   ASSERT_NE(LowerBoundStore, nullptr);
1663   ASSERT_NE(UpperBoundStore, nullptr);
1664   ASSERT_NE(StrideStore, nullptr);
1665 
1666   auto *OrigLowerBound =
1667       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1668   auto *OrigUpperBound =
1669       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1670   auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1671   ASSERT_NE(OrigLowerBound, nullptr);
1672   ASSERT_NE(OrigUpperBound, nullptr);
1673   ASSERT_NE(OrigStride, nullptr);
1674   EXPECT_EQ(OrigLowerBound->getValue(), 0);
1675   EXPECT_EQ(OrigUpperBound->getValue(), 20);
1676   EXPECT_EQ(OrigStride->getValue(), 1);
1677 
1678   // Check that the loop IV is updated to account for the lower bound returned
1679   // by the OpenMP runtime call.
1680   BinaryOperator *Add = dyn_cast<BinaryOperator>(&CLI->getBody()->front());
1681   EXPECT_EQ(Add->getOperand(0), CLI->getIndVar());
1682   auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1));
1683   ASSERT_NE(LoadedLowerBound, nullptr);
1684   EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound);
1685 
1686   // Check that the trip count is updated to account for the lower and upper
1687   // bounds return by the OpenMP runtime call.
1688   auto *AddOne = dyn_cast<Instruction>(CLI->getTripCount());
1689   ASSERT_NE(AddOne, nullptr);
1690   ASSERT_TRUE(AddOne->isBinaryOp());
1691   auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1));
1692   ASSERT_NE(One, nullptr);
1693   EXPECT_EQ(One->getValue(), 1);
1694   auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0));
1695   ASSERT_NE(Difference, nullptr);
1696   ASSERT_TRUE(Difference->isBinaryOp());
1697   EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound);
1698   auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0));
1699   ASSERT_NE(LoadedUpperBound, nullptr);
1700   EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound);
1701 
1702   // The original loop iterator should only be used in the condition, in the
1703   // increment and in the statement that adds the lower bound to it.
1704   Value *IV = CLI->getIndVar();
1705   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1706 
1707   // The exit block should contain the "fini" call and the barrier call,
1708   // plus the call to obtain the thread ID.
1709   BasicBlock *ExitBlock = CLI->getExit();
1710   size_t NumCallsInExitBlock =
1711       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1712   EXPECT_EQ(NumCallsInExitBlock, 3u);
1713 }
1714 
1715 TEST_P(OpenMPIRBuilderTestWithParams, DynamicWorkShareLoop) {
1716   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1717   OpenMPIRBuilder OMPBuilder(*M);
1718   OMPBuilder.initialize();
1719   IRBuilder<> Builder(BB);
1720   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1721 
1722   omp::OMPScheduleType SchedType = GetParam();
1723   uint32_t ChunkSize = 1;
1724   switch (SchedType) {
1725   case omp::OMPScheduleType::DynamicChunked:
1726   case omp::OMPScheduleType::GuidedChunked:
1727     ChunkSize = 7;
1728     break;
1729   case omp::OMPScheduleType::Auto:
1730   case omp::OMPScheduleType::Runtime:
1731     ChunkSize = 1;
1732     break;
1733   default:
1734     assert(0 && "unknown type for this test");
1735     break;
1736   }
1737 
1738   Type *LCTy = Type::getInt32Ty(Ctx);
1739   Value *StartVal = ConstantInt::get(LCTy, 10);
1740   Value *StopVal = ConstantInt::get(LCTy, 52);
1741   Value *StepVal = ConstantInt::get(LCTy, 2);
1742   Value *ChunkVal = ConstantInt::get(LCTy, ChunkSize);
1743   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1744 
1745   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1746       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1747       /*IsSigned=*/false, /*InclusiveStop=*/false);
1748 
1749   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1750   InsertPointTy AllocaIP = Builder.saveIP();
1751 
1752   // Collect all the info from CLI, as it isn't usable after the call to
1753   // createDynamicWorkshareLoop.
1754   InsertPointTy AfterIP = CLI->getAfterIP();
1755   BasicBlock *Preheader = CLI->getPreheader();
1756   BasicBlock *ExitBlock = CLI->getExit();
1757   Value *IV = CLI->getIndVar();
1758 
1759   InsertPointTy EndIP =
1760       OMPBuilder.createDynamicWorkshareLoop(Loc, CLI, AllocaIP, SchedType,
1761                                             /*NeedsBarrier=*/true, ChunkVal);
1762   // The returned value should be the "after" point.
1763   ASSERT_EQ(EndIP.getBlock(), AfterIP.getBlock());
1764   ASSERT_EQ(EndIP.getPoint(), AfterIP.getPoint());
1765 
1766   auto AllocaIter = BB->begin();
1767   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1768   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1769   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1770   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1771   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1772   EXPECT_NE(PLastIter, nullptr);
1773   EXPECT_NE(PLowerBound, nullptr);
1774   EXPECT_NE(PUpperBound, nullptr);
1775   EXPECT_NE(PStride, nullptr);
1776 
1777   auto PreheaderIter = Preheader->begin();
1778   ASSERT_GE(std::distance(Preheader->begin(), Preheader->end()), 6);
1779   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1780   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1781   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1782   ASSERT_NE(LowerBoundStore, nullptr);
1783   ASSERT_NE(UpperBoundStore, nullptr);
1784   ASSERT_NE(StrideStore, nullptr);
1785 
1786   CallInst *ThreadIdCall = dyn_cast<CallInst>(&*(PreheaderIter++));
1787   ASSERT_NE(ThreadIdCall, nullptr);
1788   EXPECT_EQ(ThreadIdCall->getCalledFunction()->getName(),
1789             "__kmpc_global_thread_num");
1790 
1791   CallInst *InitCall = dyn_cast<CallInst>(&*PreheaderIter);
1792 
1793   ASSERT_NE(InitCall, nullptr);
1794   EXPECT_EQ(InitCall->getCalledFunction()->getName(),
1795             "__kmpc_dispatch_init_4u");
1796   EXPECT_EQ(InitCall->getNumArgOperands(), 7U);
1797   EXPECT_EQ(InitCall->getArgOperand(6),
1798             ConstantInt::get(Type::getInt32Ty(Ctx), ChunkSize));
1799 
1800   ConstantInt *OrigLowerBound =
1801       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1802   ConstantInt *OrigUpperBound =
1803       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1804   ConstantInt *OrigStride =
1805       dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1806   ASSERT_NE(OrigLowerBound, nullptr);
1807   ASSERT_NE(OrigUpperBound, nullptr);
1808   ASSERT_NE(OrigStride, nullptr);
1809   EXPECT_EQ(OrigLowerBound->getValue(), 1);
1810   EXPECT_EQ(OrigUpperBound->getValue(), 21);
1811   EXPECT_EQ(OrigStride->getValue(), 1);
1812 
1813   // The original loop iterator should only be used in the condition, in the
1814   // increment and in the statement that adds the lower bound to it.
1815   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1816 
1817   // The exit block should contain the barrier call, plus the call to obtain
1818   // the thread ID.
1819   size_t NumCallsInExitBlock =
1820       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1821   EXPECT_EQ(NumCallsInExitBlock, 2u);
1822 
1823   // Add a termination to our block and check that it is internally consistent.
1824   Builder.restoreIP(EndIP);
1825   Builder.CreateRetVoid();
1826   OMPBuilder.finalize();
1827   EXPECT_FALSE(verifyModule(*M, &errs()));
1828 }
1829 
1830 INSTANTIATE_TEST_CASE_P(OpenMPWSLoopSchedulingTypes,
1831                         OpenMPIRBuilderTestWithParams,
1832                         ::testing::Values(omp::OMPScheduleType::DynamicChunked,
1833                                           omp::OMPScheduleType::GuidedChunked,
1834                                           omp::OMPScheduleType::Auto,
1835                                           omp::OMPScheduleType::Runtime));
1836 
1837 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
1838   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1839   OpenMPIRBuilder OMPBuilder(*M);
1840   OMPBuilder.initialize();
1841   F->setName("func");
1842   IRBuilder<> Builder(BB);
1843 
1844   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1845 
1846   AllocaInst *PrivAI = nullptr;
1847 
1848   BasicBlock *EntryBB = nullptr;
1849   BasicBlock *ExitBB = nullptr;
1850   BasicBlock *ThenBB = nullptr;
1851 
1852   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1853                        BasicBlock &FiniBB) {
1854     if (AllocaIP.isSet())
1855       Builder.restoreIP(AllocaIP);
1856     else
1857       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1858     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1859     Builder.CreateStore(F->arg_begin(), PrivAI);
1860 
1861     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1862     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1863     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1864 
1865     Builder.restoreIP(CodeGenIP);
1866 
1867     // collect some info for checks later
1868     ExitBB = FiniBB.getUniqueSuccessor();
1869     ThenBB = Builder.GetInsertBlock();
1870     EntryBB = ThenBB->getUniquePredecessor();
1871 
1872     // simple instructions for body
1873     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
1874                                          "local.use");
1875     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1876   };
1877 
1878   auto FiniCB = [&](InsertPointTy IP) {
1879     BasicBlock *IPBB = IP.getBlock();
1880     EXPECT_NE(IPBB->end(), IP.getPoint());
1881   };
1882 
1883   Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
1884   Value *EntryBBTI = EntryBB->getTerminator();
1885   EXPECT_NE(EntryBBTI, nullptr);
1886   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1887   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1888   EXPECT_TRUE(EntryBr->isConditional());
1889   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1890   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1891   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1892 
1893   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1894   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1895 
1896   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
1897   EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
1898   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
1899   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
1900 
1901   CallInst *MasterEndCI = nullptr;
1902   for (auto &FI : *ThenBB) {
1903     Instruction *cur = &FI;
1904     if (isa<CallInst>(cur)) {
1905       MasterEndCI = cast<CallInst>(cur);
1906       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
1907         break;
1908       MasterEndCI = nullptr;
1909     }
1910   }
1911   EXPECT_NE(MasterEndCI, nullptr);
1912   EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
1913   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
1914   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
1915 }
1916 
1917 TEST_F(OpenMPIRBuilderTest, MaskedDirective) {
1918   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1919   OpenMPIRBuilder OMPBuilder(*M);
1920   OMPBuilder.initialize();
1921   F->setName("func");
1922   IRBuilder<> Builder(BB);
1923 
1924   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1925 
1926   AllocaInst *PrivAI = nullptr;
1927 
1928   BasicBlock *EntryBB = nullptr;
1929   BasicBlock *ExitBB = nullptr;
1930   BasicBlock *ThenBB = nullptr;
1931 
1932   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1933                        BasicBlock &FiniBB) {
1934     if (AllocaIP.isSet())
1935       Builder.restoreIP(AllocaIP);
1936     else
1937       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1938     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1939     Builder.CreateStore(F->arg_begin(), PrivAI);
1940 
1941     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1942     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1943     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1944 
1945     Builder.restoreIP(CodeGenIP);
1946 
1947     // collect some info for checks later
1948     ExitBB = FiniBB.getUniqueSuccessor();
1949     ThenBB = Builder.GetInsertBlock();
1950     EntryBB = ThenBB->getUniquePredecessor();
1951 
1952     // simple instructions for body
1953     Value *PrivLoad =
1954         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
1955     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1956   };
1957 
1958   auto FiniCB = [&](InsertPointTy IP) {
1959     BasicBlock *IPBB = IP.getBlock();
1960     EXPECT_NE(IPBB->end(), IP.getPoint());
1961   };
1962 
1963   Constant *Filter = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0);
1964   Builder.restoreIP(
1965       OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, Filter));
1966   Value *EntryBBTI = EntryBB->getTerminator();
1967   EXPECT_NE(EntryBBTI, nullptr);
1968   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1969   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1970   EXPECT_TRUE(EntryBr->isConditional());
1971   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1972   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1973   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1974 
1975   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1976   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1977 
1978   CallInst *MaskedEntryCI = cast<CallInst>(CondInst->getOperand(0));
1979   EXPECT_EQ(MaskedEntryCI->getNumArgOperands(), 3U);
1980   EXPECT_EQ(MaskedEntryCI->getCalledFunction()->getName(), "__kmpc_masked");
1981   EXPECT_TRUE(isa<GlobalVariable>(MaskedEntryCI->getArgOperand(0)));
1982 
1983   CallInst *MaskedEndCI = nullptr;
1984   for (auto &FI : *ThenBB) {
1985     Instruction *cur = &FI;
1986     if (isa<CallInst>(cur)) {
1987       MaskedEndCI = cast<CallInst>(cur);
1988       if (MaskedEndCI->getCalledFunction()->getName() == "__kmpc_end_masked")
1989         break;
1990       MaskedEndCI = nullptr;
1991     }
1992   }
1993   EXPECT_NE(MaskedEndCI, nullptr);
1994   EXPECT_EQ(MaskedEndCI->getNumArgOperands(), 2U);
1995   EXPECT_TRUE(isa<GlobalVariable>(MaskedEndCI->getArgOperand(0)));
1996   EXPECT_EQ(MaskedEndCI->getArgOperand(1), MaskedEntryCI->getArgOperand(1));
1997 }
1998 
1999 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
2000   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2001   OpenMPIRBuilder OMPBuilder(*M);
2002   OMPBuilder.initialize();
2003   F->setName("func");
2004   IRBuilder<> Builder(BB);
2005 
2006   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2007 
2008   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2009 
2010   BasicBlock *EntryBB = nullptr;
2011 
2012   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2013                        BasicBlock &FiniBB) {
2014     // collect some info for checks later
2015     EntryBB = FiniBB.getUniquePredecessor();
2016 
2017     // actual start for bodyCB
2018     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2019     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2020     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2021     EXPECT_EQ(EntryBB, CodeGenIPBB);
2022 
2023     // body begin
2024     Builder.restoreIP(CodeGenIP);
2025     Builder.CreateStore(F->arg_begin(), PrivAI);
2026     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
2027                                          "local.use");
2028     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2029   };
2030 
2031   auto FiniCB = [&](InsertPointTy IP) {
2032     BasicBlock *IPBB = IP.getBlock();
2033     EXPECT_NE(IPBB->end(), IP.getPoint());
2034   };
2035 
2036   Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
2037                                               "testCRT", nullptr));
2038 
2039   Value *EntryBBTI = EntryBB->getTerminator();
2040   EXPECT_EQ(EntryBBTI, nullptr);
2041 
2042   CallInst *CriticalEntryCI = nullptr;
2043   for (auto &EI : *EntryBB) {
2044     Instruction *cur = &EI;
2045     if (isa<CallInst>(cur)) {
2046       CriticalEntryCI = cast<CallInst>(cur);
2047       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
2048         break;
2049       CriticalEntryCI = nullptr;
2050     }
2051   }
2052   EXPECT_NE(CriticalEntryCI, nullptr);
2053   EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
2054   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
2055   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
2056 
2057   CallInst *CriticalEndCI = nullptr;
2058   for (auto &FI : *EntryBB) {
2059     Instruction *cur = &FI;
2060     if (isa<CallInst>(cur)) {
2061       CriticalEndCI = cast<CallInst>(cur);
2062       if (CriticalEndCI->getCalledFunction()->getName() ==
2063           "__kmpc_end_critical")
2064         break;
2065       CriticalEndCI = nullptr;
2066     }
2067   }
2068   EXPECT_NE(CriticalEndCI, nullptr);
2069   EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
2070   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
2071   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
2072   PointerType *CriticalNamePtrTy =
2073       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
2074   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
2075   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
2076 }
2077 
2078 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
2079   OpenMPIRBuilder OMPBuilder(*M);
2080   OMPBuilder.initialize();
2081   F->setName("func");
2082   IRBuilder<> Builder(BB);
2083 
2084   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2085 
2086   IntegerType* Int32 = Type::getInt32Ty(M->getContext());
2087   AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
2088 	AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
2089 
2090   BasicBlock *EntryBB = BB;
2091 
2092   OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress,
2093                                       PrivAddress, Int32, /*BranchtoEnd*/ true);
2094 
2095   BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
2096 
2097   EXPECT_NE(EntryBr, nullptr);
2098   EXPECT_TRUE(EntryBr->isConditional());
2099 
2100   BasicBlock* NotMasterBB = EntryBr->getSuccessor(0);
2101   BasicBlock* CopyinEnd = EntryBr->getSuccessor(1);
2102   CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
2103 
2104   EXPECT_NE(CMP, nullptr);
2105   EXPECT_NE(NotMasterBB, nullptr);
2106   EXPECT_NE(CopyinEnd, nullptr);
2107 
2108   BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
2109   EXPECT_NE(NotMasterBr, nullptr);
2110   EXPECT_FALSE(NotMasterBr->isConditional());
2111   EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
2112 }
2113 
2114 TEST_F(OpenMPIRBuilderTest, SingleDirective) {
2115   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2116   OpenMPIRBuilder OMPBuilder(*M);
2117   OMPBuilder.initialize();
2118   F->setName("func");
2119   IRBuilder<> Builder(BB);
2120 
2121   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2122 
2123   AllocaInst *PrivAI = nullptr;
2124 
2125   BasicBlock *EntryBB = nullptr;
2126   BasicBlock *ExitBB = nullptr;
2127   BasicBlock *ThenBB = nullptr;
2128 
2129   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2130                        BasicBlock &FiniBB) {
2131     if (AllocaIP.isSet())
2132       Builder.restoreIP(AllocaIP);
2133     else
2134       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
2135     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2136     Builder.CreateStore(F->arg_begin(), PrivAI);
2137 
2138     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2139     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2140     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2141 
2142     Builder.restoreIP(CodeGenIP);
2143 
2144     // collect some info for checks later
2145     ExitBB = FiniBB.getUniqueSuccessor();
2146     ThenBB = Builder.GetInsertBlock();
2147     EntryBB = ThenBB->getUniquePredecessor();
2148 
2149     // simple instructions for body
2150     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
2151                                          "local.use");
2152     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2153   };
2154 
2155   auto FiniCB = [&](InsertPointTy IP) {
2156     BasicBlock *IPBB = IP.getBlock();
2157     EXPECT_NE(IPBB->end(), IP.getPoint());
2158   };
2159 
2160   Builder.restoreIP(
2161       OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
2162   Value *EntryBBTI = EntryBB->getTerminator();
2163   EXPECT_NE(EntryBBTI, nullptr);
2164   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2165   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2166   EXPECT_TRUE(EntryBr->isConditional());
2167   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2168   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2169   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2170 
2171   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2172   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2173 
2174   CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
2175   EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
2176   EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
2177   EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
2178 
2179   CallInst *SingleEndCI = nullptr;
2180   for (auto &FI : *ThenBB) {
2181     Instruction *cur = &FI;
2182     if (isa<CallInst>(cur)) {
2183       SingleEndCI = cast<CallInst>(cur);
2184       if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
2185         break;
2186       SingleEndCI = nullptr;
2187     }
2188   }
2189   EXPECT_NE(SingleEndCI, nullptr);
2190   EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
2191   EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
2192   EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
2193 }
2194 
2195 TEST_F(OpenMPIRBuilderTest, CreateSections) {
2196   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2197   using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2198   OpenMPIRBuilder OMPBuilder(*M);
2199   OMPBuilder.initialize();
2200   F->setName("func");
2201   IRBuilder<> Builder(BB);
2202 
2203   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2204   llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
2205   llvm::SmallVector<BasicBlock *, 4> CaseBBs;
2206 
2207   BasicBlock *SwitchBB = nullptr;
2208   BasicBlock *ForExitBB = nullptr;
2209   BasicBlock *ForIncBB = nullptr;
2210   AllocaInst *PrivAI = nullptr;
2211   SwitchInst *Switch = nullptr;
2212 
2213   unsigned NumBodiesGenerated = 0;
2214   unsigned NumFiniCBCalls = 0;
2215   PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2216 
2217   auto FiniCB = [&](InsertPointTy IP) {
2218     ++NumFiniCBCalls;
2219     BasicBlock *IPBB = IP.getBlock();
2220     EXPECT_NE(IPBB->end(), IP.getPoint());
2221   };
2222 
2223   auto SectionCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2224                        BasicBlock &FiniBB) {
2225     ++NumBodiesGenerated;
2226     CaseBBs.push_back(CodeGenIP.getBlock());
2227     SwitchBB = CodeGenIP.getBlock()->getSinglePredecessor();
2228     Builder.restoreIP(CodeGenIP);
2229     Builder.CreateStore(F->arg_begin(), PrivAI);
2230     Value *PrivLoad =
2231         Builder.CreateLoad(F->arg_begin()->getType(), PrivAI, "local.alloca");
2232     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2233     Builder.CreateBr(&FiniBB);
2234     ForIncBB =
2235         CodeGenIP.getBlock()->getSinglePredecessor()->getSingleSuccessor();
2236   };
2237   auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2238                    llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2239     // TODO: Privatization not implemented yet
2240     return CodeGenIP;
2241   };
2242 
2243   SectionCBVector.push_back(SectionCB);
2244   SectionCBVector.push_back(SectionCB);
2245 
2246   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
2247                                     F->getEntryBlock().getFirstInsertionPt());
2248   Builder.restoreIP(OMPBuilder.createSections(Loc, AllocaIP, SectionCBVector,
2249                                               PrivCB, FiniCB, false, false));
2250   Builder.CreateRetVoid(); // Required at the end of the function
2251 
2252   // Switch BB's predecessor is loop condition BB, whose successor at index 1 is
2253   // loop's exit BB
2254   ForExitBB =
2255       SwitchBB->getSinglePredecessor()->getTerminator()->getSuccessor(1);
2256   EXPECT_NE(ForExitBB, nullptr);
2257 
2258   EXPECT_NE(PrivAI, nullptr);
2259   Function *OutlinedFn = PrivAI->getFunction();
2260   EXPECT_EQ(F, OutlinedFn);
2261   EXPECT_FALSE(verifyModule(*M, &errs()));
2262   EXPECT_EQ(OutlinedFn->arg_size(), 1U);
2263   EXPECT_EQ(OutlinedFn->getBasicBlockList().size(), size_t(11));
2264 
2265   BasicBlock *LoopPreheaderBB =
2266       OutlinedFn->getEntryBlock().getSingleSuccessor();
2267   // loop variables are 5 - lower bound, upper bound, stride, islastiter, and
2268   // iterator/counter
2269   bool FoundForInit = false;
2270   for (Instruction &Inst : *LoopPreheaderBB) {
2271     if (isa<CallInst>(Inst)) {
2272       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2273           "__kmpc_for_static_init_4u") {
2274         FoundForInit = true;
2275       }
2276     }
2277   }
2278   EXPECT_EQ(FoundForInit, true);
2279 
2280   bool FoundForExit = false;
2281   bool FoundBarrier = false;
2282   for (Instruction &Inst : *ForExitBB) {
2283     if (isa<CallInst>(Inst)) {
2284       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2285           "__kmpc_for_static_fini") {
2286         FoundForExit = true;
2287       }
2288       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2289           "__kmpc_barrier") {
2290         FoundBarrier = true;
2291       }
2292       if (FoundForExit && FoundBarrier)
2293         break;
2294     }
2295   }
2296   EXPECT_EQ(FoundForExit, true);
2297   EXPECT_EQ(FoundBarrier, true);
2298 
2299   EXPECT_NE(SwitchBB, nullptr);
2300   EXPECT_NE(SwitchBB->getTerminator(), nullptr);
2301   EXPECT_EQ(isa<SwitchInst>(SwitchBB->getTerminator()), true);
2302   Switch = cast<SwitchInst>(SwitchBB->getTerminator());
2303   EXPECT_EQ(Switch->getNumCases(), 2U);
2304   EXPECT_NE(ForIncBB, nullptr);
2305   EXPECT_EQ(Switch->getSuccessor(0), ForIncBB);
2306 
2307   EXPECT_EQ(CaseBBs.size(), 2U);
2308   for (auto *&CaseBB : CaseBBs) {
2309     EXPECT_EQ(CaseBB->getParent(), OutlinedFn);
2310     EXPECT_EQ(CaseBB->getSingleSuccessor(), ForExitBB);
2311   }
2312 
2313   ASSERT_EQ(NumBodiesGenerated, 2U);
2314   ASSERT_EQ(NumFiniCBCalls, 1U);
2315 }
2316 
2317 TEST_F(OpenMPIRBuilderTest, CreateOffloadMaptypes) {
2318   OpenMPIRBuilder OMPBuilder(*M);
2319   OMPBuilder.initialize();
2320 
2321   IRBuilder<> Builder(BB);
2322 
2323   SmallVector<uint64_t> Mappings = {0, 1};
2324   GlobalVariable *OffloadMaptypesGlobal =
2325       OMPBuilder.createOffloadMaptypes(Mappings, "offload_maptypes");
2326   EXPECT_FALSE(M->global_empty());
2327   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_maptypes");
2328   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
2329   EXPECT_TRUE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
2330   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
2331   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
2332   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
2333   EXPECT_TRUE(isa<ConstantDataArray>(Initializer));
2334   ConstantDataArray *MappingInit = dyn_cast<ConstantDataArray>(Initializer);
2335   EXPECT_EQ(MappingInit->getNumElements(), Mappings.size());
2336   EXPECT_TRUE(MappingInit->getType()->getElementType()->isIntegerTy(64));
2337   Constant *CA = ConstantDataArray::get(Builder.getContext(), Mappings);
2338   EXPECT_EQ(MappingInit, CA);
2339 }
2340 
2341 TEST_F(OpenMPIRBuilderTest, CreateOffloadMapnames) {
2342   OpenMPIRBuilder OMPBuilder(*M);
2343   OMPBuilder.initialize();
2344 
2345   IRBuilder<> Builder(BB);
2346 
2347   Constant *Cst1 = OMPBuilder.getOrCreateSrcLocStr("array1", "file1", 2, 5);
2348   Constant *Cst2 = OMPBuilder.getOrCreateSrcLocStr("array2", "file1", 3, 5);
2349   SmallVector<llvm::Constant *> Names = {Cst1, Cst2};
2350 
2351   GlobalVariable *OffloadMaptypesGlobal =
2352       OMPBuilder.createOffloadMapnames(Names, "offload_mapnames");
2353   EXPECT_FALSE(M->global_empty());
2354   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_mapnames");
2355   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
2356   EXPECT_FALSE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
2357   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
2358   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
2359   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
2360   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(0)->stripPointerCasts()));
2361   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(1)->stripPointerCasts()));
2362 
2363   GlobalVariable *Name1Gbl =
2364       cast<GlobalVariable>(Initializer->getOperand(0)->stripPointerCasts());
2365   EXPECT_TRUE(isa<ConstantDataArray>(Name1Gbl->getInitializer()));
2366   ConstantDataArray *Name1GblCA =
2367       dyn_cast<ConstantDataArray>(Name1Gbl->getInitializer());
2368   EXPECT_EQ(Name1GblCA->getAsCString(), ";file1;array1;2;5;;");
2369 
2370   GlobalVariable *Name2Gbl =
2371       cast<GlobalVariable>(Initializer->getOperand(1)->stripPointerCasts());
2372   EXPECT_TRUE(isa<ConstantDataArray>(Name2Gbl->getInitializer()));
2373   ConstantDataArray *Name2GblCA =
2374       dyn_cast<ConstantDataArray>(Name2Gbl->getInitializer());
2375   EXPECT_EQ(Name2GblCA->getAsCString(), ";file1;array2;3;5;;");
2376 
2377   EXPECT_TRUE(Initializer->getType()->getArrayElementType()->isPointerTy());
2378   EXPECT_EQ(Initializer->getType()->getArrayNumElements(), Names.size());
2379 }
2380 
2381 } // namespace
2382