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/Passes/PassBuilder.h"
19 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
20 #include "gtest/gtest.h"
21 
22 using namespace llvm;
23 using namespace omp;
24 
25 namespace {
26 
27 /// Create an instruction that uses the values in \p Values. We use "printf"
28 /// just because it is often used for this purpose in test code, but it is never
29 /// executed here.
30 static CallInst *createPrintfCall(IRBuilder<> &Builder, StringRef FormatStr,
31                                   ArrayRef<Value *> Values) {
32   Module *M = Builder.GetInsertBlock()->getParent()->getParent();
33 
34   GlobalVariable *GV = Builder.CreateGlobalString(FormatStr, "", 0, M);
35   Constant *Zero = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0);
36   Constant *Indices[] = {Zero, Zero};
37   Constant *FormatStrConst =
38       ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, Indices);
39 
40   Function *PrintfDecl = M->getFunction("printf");
41   if (!PrintfDecl) {
42     GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
43     FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), true);
44     PrintfDecl = Function::Create(Ty, Linkage, "printf", M);
45   }
46 
47   SmallVector<Value *, 4> Args;
48   Args.push_back(FormatStrConst);
49   Args.append(Values.begin(), Values.end());
50   return Builder.CreateCall(PrintfDecl, Args);
51 }
52 
53 /// Verify that blocks in \p RefOrder are corresponds to the depth-first visit
54 /// order the control flow of \p F.
55 ///
56 /// This is an easy way to verify the branching structure of the CFG without
57 /// checking every branch instruction individually. For the CFG of a
58 /// CanonicalLoopInfo, the Cond BB's terminating branch's first edge is entering
59 /// the body, i.e. the DFS order corresponds to the execution order with one
60 /// loop iteration.
61 static testing::AssertionResult
62 verifyDFSOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) {
63   ArrayRef<BasicBlock *>::iterator It = RefOrder.begin();
64   ArrayRef<BasicBlock *>::iterator E = RefOrder.end();
65 
66   df_iterator_default_set<BasicBlock *, 16> Visited;
67   auto DFS = llvm::depth_first_ext(&F->getEntryBlock(), Visited);
68 
69   BasicBlock *Prev = nullptr;
70   for (BasicBlock *BB : DFS) {
71     if (It != E && BB == *It) {
72       Prev = *It;
73       ++It;
74     }
75   }
76 
77   if (It == E)
78     return testing::AssertionSuccess();
79   if (!Prev)
80     return testing::AssertionFailure()
81            << "Did not find " << (*It)->getName() << " in control flow";
82   return testing::AssertionFailure()
83          << "Expected " << Prev->getName() << " before " << (*It)->getName()
84          << " in control flow";
85 }
86 
87 /// Verify that blocks in \p RefOrder are in the same relative order in the
88 /// linked lists of blocks in \p F. The linked list may contain additional
89 /// blocks in-between.
90 ///
91 /// While the order in the linked list is not relevant for semantics, keeping
92 /// the order roughly in execution order makes its printout easier to read.
93 static testing::AssertionResult
94 verifyListOrder(Function *F, ArrayRef<BasicBlock *> RefOrder) {
95   ArrayRef<BasicBlock *>::iterator It = RefOrder.begin();
96   ArrayRef<BasicBlock *>::iterator E = RefOrder.end();
97 
98   BasicBlock *Prev = nullptr;
99   for (BasicBlock &BB : *F) {
100     if (It != E && &BB == *It) {
101       Prev = *It;
102       ++It;
103     }
104   }
105 
106   if (It == E)
107     return testing::AssertionSuccess();
108   if (!Prev)
109     return testing::AssertionFailure() << "Did not find " << (*It)->getName()
110                                        << " in function " << F->getName();
111   return testing::AssertionFailure()
112          << "Expected " << Prev->getName() << " before " << (*It)->getName()
113          << " in function " << F->getName();
114 }
115 
116 class OpenMPIRBuilderTest : public testing::Test {
117 protected:
118   void SetUp() override {
119     M.reset(new Module("MyModule", Ctx));
120     FunctionType *FTy =
121         FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
122                           /*isVarArg=*/false);
123     F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
124     BB = BasicBlock::Create(Ctx, "", F);
125 
126     DIBuilder DIB(*M);
127     auto File = DIB.createFile("test.dbg", "/src", llvm::None,
128                                Optional<StringRef>("/src/test.dbg"));
129     auto CU =
130         DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0);
131     auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
132     auto SP = DIB.createFunction(
133         CU, "foo", "", File, 1, Type, 1, DINode::FlagZero,
134         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
135     F->setSubprogram(SP);
136     auto Scope = DIB.createLexicalBlockFile(SP, File, 0);
137     DIB.finalize();
138     DL = DILocation::get(Ctx, 3, 7, Scope);
139   }
140 
141   void TearDown() override {
142     BB = nullptr;
143     M.reset();
144   }
145 
146   /// Create a function with a simple loop that calls printf using the logical
147   /// loop counter for use with tests that need a CanonicalLoopInfo object.
148   CanonicalLoopInfo *buildSingleLoopFunction(DebugLoc DL,
149                                              OpenMPIRBuilder &OMPBuilder,
150                                              Instruction **Call = nullptr,
151                                              BasicBlock **BodyCode = nullptr) {
152     OMPBuilder.initialize();
153     F->setName("func");
154 
155     IRBuilder<> Builder(BB);
156     OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
157     Value *TripCount = F->getArg(0);
158 
159     auto LoopBodyGenCB = [&](OpenMPIRBuilder::InsertPointTy CodeGenIP,
160                              llvm::Value *LC) {
161       Builder.restoreIP(CodeGenIP);
162       if (BodyCode)
163         *BodyCode = Builder.GetInsertBlock();
164 
165       // Add something that consumes the induction variable to the body.
166       CallInst *CallInst = createPrintfCall(Builder, "%d\\n", {LC});
167       if (Call)
168         *Call = CallInst;
169     };
170     CanonicalLoopInfo *Loop =
171         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
172 
173     // Finalize the function.
174     Builder.restoreIP(Loop->getAfterIP());
175     Builder.CreateRetVoid();
176 
177     return Loop;
178   }
179 
180   LLVMContext Ctx;
181   std::unique_ptr<Module> M;
182   Function *F;
183   BasicBlock *BB;
184   DebugLoc DL;
185 };
186 
187 class OpenMPIRBuilderTestWithParams
188     : public OpenMPIRBuilderTest,
189       public ::testing::WithParamInterface<omp::OMPScheduleType> {};
190 
191 // Returns the value stored in the given allocation. Returns null if the given
192 // value is not a result of an InstTy instruction, if no value is stored or if
193 // there is more than one store.
194 template <typename InstTy> static Value *findStoredValue(Value *AllocaValue) {
195   Instruction *Inst = dyn_cast<InstTy>(AllocaValue);
196   if (!Inst)
197     return nullptr;
198   StoreInst *Store = nullptr;
199   for (Use &U : Inst->uses()) {
200     if (auto *CandidateStore = dyn_cast<StoreInst>(U.getUser())) {
201       EXPECT_EQ(Store, nullptr);
202       Store = CandidateStore;
203     }
204   }
205   if (!Store)
206     return nullptr;
207   return Store->getValueOperand();
208 }
209 
210 TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
211   OpenMPIRBuilder OMPBuilder(*M);
212   OMPBuilder.initialize();
213 
214   IRBuilder<> Builder(BB);
215 
216   OMPBuilder.createBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
217   EXPECT_TRUE(M->global_empty());
218   EXPECT_EQ(M->size(), 1U);
219   EXPECT_EQ(F->size(), 1U);
220   EXPECT_EQ(BB->size(), 0U);
221 
222   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
223   OMPBuilder.createBarrier(Loc, OMPD_for);
224   EXPECT_FALSE(M->global_empty());
225   EXPECT_EQ(M->size(), 3U);
226   EXPECT_EQ(F->size(), 1U);
227   EXPECT_EQ(BB->size(), 2U);
228 
229   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
230   EXPECT_NE(GTID, nullptr);
231   EXPECT_EQ(GTID->arg_size(), 1U);
232   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
233   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
234   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
235 
236   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
237   EXPECT_NE(Barrier, nullptr);
238   EXPECT_EQ(Barrier->arg_size(), 2U);
239   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
240   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
241   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
242 
243   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
244 
245   Builder.CreateUnreachable();
246   EXPECT_FALSE(verifyModule(*M, &errs()));
247 }
248 
249 TEST_F(OpenMPIRBuilderTest, CreateCancel) {
250   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
251   OpenMPIRBuilder OMPBuilder(*M);
252   OMPBuilder.initialize();
253 
254   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
255   new UnreachableInst(Ctx, CBB);
256   auto FiniCB = [&](InsertPointTy IP) {
257     ASSERT_NE(IP.getBlock(), nullptr);
258     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
259     BranchInst::Create(CBB, IP.getBlock());
260   };
261   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
262 
263   IRBuilder<> Builder(BB);
264 
265   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
266   auto NewIP = OMPBuilder.createCancel(Loc, nullptr, OMPD_parallel);
267   Builder.restoreIP(NewIP);
268   EXPECT_FALSE(M->global_empty());
269   EXPECT_EQ(M->size(), 4U);
270   EXPECT_EQ(F->size(), 4U);
271   EXPECT_EQ(BB->size(), 4U);
272 
273   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
274   EXPECT_NE(GTID, nullptr);
275   EXPECT_EQ(GTID->arg_size(), 1U);
276   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
277   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
278   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
279 
280   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
281   EXPECT_NE(Cancel, nullptr);
282   EXPECT_EQ(Cancel->arg_size(), 3U);
283   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
284   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
285   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
286   EXPECT_EQ(Cancel->getNumUses(), 1U);
287   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
288   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
289   EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
290   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 3U);
291   CallInst *GTID1 = dyn_cast<CallInst>(&CancelBBTI->getSuccessor(1)->front());
292   EXPECT_NE(GTID1, nullptr);
293   EXPECT_EQ(GTID1->arg_size(), 1U);
294   EXPECT_EQ(GTID1->getCalledFunction()->getName(), "__kmpc_global_thread_num");
295   EXPECT_FALSE(GTID1->getCalledFunction()->doesNotAccessMemory());
296   EXPECT_FALSE(GTID1->getCalledFunction()->doesNotFreeMemory());
297   CallInst *Barrier = dyn_cast<CallInst>(GTID1->getNextNode());
298   EXPECT_NE(Barrier, nullptr);
299   EXPECT_EQ(Barrier->arg_size(), 2U);
300   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
301   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
302   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
303   EXPECT_EQ(Barrier->getNumUses(), 0U);
304   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
305             1U);
306   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), CBB);
307 
308   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
309 
310   OMPBuilder.popFinalizationCB();
311 
312   Builder.CreateUnreachable();
313   EXPECT_FALSE(verifyModule(*M, &errs()));
314 }
315 
316 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
317   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
318   OpenMPIRBuilder OMPBuilder(*M);
319   OMPBuilder.initialize();
320 
321   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
322   new UnreachableInst(Ctx, CBB);
323   auto FiniCB = [&](InsertPointTy IP) {
324     ASSERT_NE(IP.getBlock(), nullptr);
325     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
326     BranchInst::Create(CBB, IP.getBlock());
327   };
328   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
329 
330   IRBuilder<> Builder(BB);
331 
332   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
333   auto NewIP = OMPBuilder.createCancel(Loc, Builder.getTrue(), OMPD_parallel);
334   Builder.restoreIP(NewIP);
335   EXPECT_FALSE(M->global_empty());
336   EXPECT_EQ(M->size(), 4U);
337   EXPECT_EQ(F->size(), 7U);
338   EXPECT_EQ(BB->size(), 1U);
339   ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
340   ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
341   BB = BB->getTerminator()->getSuccessor(0);
342   EXPECT_EQ(BB->size(), 4U);
343 
344   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
345   EXPECT_NE(GTID, nullptr);
346   EXPECT_EQ(GTID->arg_size(), 1U);
347   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
348   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
349   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
350 
351   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
352   EXPECT_NE(Cancel, nullptr);
353   EXPECT_EQ(Cancel->arg_size(), 3U);
354   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
355   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
356   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
357   EXPECT_EQ(Cancel->getNumUses(), 1U);
358   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
359   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
360   EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
361   EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(),
362             NewIP.getBlock());
363   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 3U);
364   CallInst *GTID1 = dyn_cast<CallInst>(&CancelBBTI->getSuccessor(1)->front());
365   EXPECT_NE(GTID1, nullptr);
366   EXPECT_EQ(GTID1->arg_size(), 1U);
367   EXPECT_EQ(GTID1->getCalledFunction()->getName(), "__kmpc_global_thread_num");
368   EXPECT_FALSE(GTID1->getCalledFunction()->doesNotAccessMemory());
369   EXPECT_FALSE(GTID1->getCalledFunction()->doesNotFreeMemory());
370   CallInst *Barrier = dyn_cast<CallInst>(GTID1->getNextNode());
371   EXPECT_NE(Barrier, nullptr);
372   EXPECT_EQ(Barrier->arg_size(), 2U);
373   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
374   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
375   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
376   EXPECT_EQ(Barrier->getNumUses(), 0U);
377   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
378             1U);
379   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0), CBB);
380 
381   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
382 
383   OMPBuilder.popFinalizationCB();
384 
385   Builder.CreateUnreachable();
386   EXPECT_FALSE(verifyModule(*M, &errs()));
387 }
388 
389 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
390   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
391   OpenMPIRBuilder OMPBuilder(*M);
392   OMPBuilder.initialize();
393 
394   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
395   new UnreachableInst(Ctx, CBB);
396   auto FiniCB = [&](InsertPointTy IP) {
397     ASSERT_NE(IP.getBlock(), nullptr);
398     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
399     BranchInst::Create(CBB, IP.getBlock());
400   };
401   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
402 
403   IRBuilder<> Builder(BB);
404 
405   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
406   auto NewIP = OMPBuilder.createBarrier(Loc, OMPD_for);
407   Builder.restoreIP(NewIP);
408   EXPECT_FALSE(M->global_empty());
409   EXPECT_EQ(M->size(), 3U);
410   EXPECT_EQ(F->size(), 4U);
411   EXPECT_EQ(BB->size(), 4U);
412 
413   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
414   EXPECT_NE(GTID, nullptr);
415   EXPECT_EQ(GTID->arg_size(), 1U);
416   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
417   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
418   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
419 
420   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
421   EXPECT_NE(Barrier, nullptr);
422   EXPECT_EQ(Barrier->arg_size(), 2U);
423   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
424   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
425   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
426   EXPECT_EQ(Barrier->getNumUses(), 1U);
427   Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
428   EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
429   EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
430   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
431   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
432             1U);
433   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
434             CBB);
435 
436   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
437 
438   OMPBuilder.popFinalizationCB();
439 
440   Builder.CreateUnreachable();
441   EXPECT_FALSE(verifyModule(*M, &errs()));
442 }
443 
444 TEST_F(OpenMPIRBuilderTest, DbgLoc) {
445   OpenMPIRBuilder OMPBuilder(*M);
446   OMPBuilder.initialize();
447   F->setName("func");
448 
449   IRBuilder<> Builder(BB);
450 
451   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
452   OMPBuilder.createBarrier(Loc, OMPD_for);
453   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
454   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
455   EXPECT_EQ(GTID->getDebugLoc(), DL);
456   EXPECT_EQ(Barrier->getDebugLoc(), DL);
457   EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
458   if (!isa<GlobalVariable>(Barrier->getOperand(0)))
459     return;
460   GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
461   EXPECT_TRUE(Ident->hasInitializer());
462   if (!Ident->hasInitializer())
463     return;
464   Constant *Initializer = Ident->getInitializer();
465   EXPECT_TRUE(
466       isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
467   GlobalVariable *SrcStrGlob =
468       cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
469   if (!SrcStrGlob)
470     return;
471   EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
472   ConstantDataArray *SrcSrc =
473       dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
474   if (!SrcSrc)
475     return;
476   EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;");
477 }
478 
479 TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
480   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
481   OpenMPIRBuilder OMPBuilder(*M);
482   OMPBuilder.initialize();
483   F->setName("func");
484   IRBuilder<> Builder(BB);
485 
486   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
487   Builder.CreateBr(EnterBB);
488   Builder.SetInsertPoint(EnterBB);
489   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
490 
491   AllocaInst *PrivAI = nullptr;
492 
493   unsigned NumBodiesGenerated = 0;
494   unsigned NumPrivatizedVars = 0;
495   unsigned NumFinalizationPoints = 0;
496 
497   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
498                        BasicBlock &ContinuationIP) {
499     ++NumBodiesGenerated;
500 
501     Builder.restoreIP(AllocaIP);
502     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
503     Builder.CreateStore(F->arg_begin(), PrivAI);
504 
505     Builder.restoreIP(CodeGenIP);
506     Value *PrivLoad =
507         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
508     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
509     Instruction *ThenTerm, *ElseTerm;
510     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
511                                   &ThenTerm, &ElseTerm);
512 
513     Builder.SetInsertPoint(ThenTerm);
514     Builder.CreateBr(&ContinuationIP);
515     ThenTerm->eraseFromParent();
516   };
517 
518   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
519                     Value &Orig, Value &Inner,
520                     Value *&ReplacementValue) -> InsertPointTy {
521     ++NumPrivatizedVars;
522 
523     if (!isa<AllocaInst>(Orig)) {
524       EXPECT_EQ(&Orig, F->arg_begin());
525       ReplacementValue = &Inner;
526       return CodeGenIP;
527     }
528 
529     // Since the original value is an allocation, it has a pointer type and
530     // therefore no additional wrapping should happen.
531     EXPECT_EQ(&Orig, &Inner);
532 
533     // Trivial copy (=firstprivate).
534     Builder.restoreIP(AllocaIP);
535     Type *VTy = Inner.getType()->getPointerElementType();
536     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
537     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
538     Builder.restoreIP(CodeGenIP);
539     Builder.CreateStore(V, ReplacementValue);
540     return CodeGenIP;
541   };
542 
543   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
544 
545   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
546                                     F->getEntryBlock().getFirstInsertionPt());
547   IRBuilder<>::InsertPoint AfterIP =
548       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
549                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
550   EXPECT_EQ(NumBodiesGenerated, 1U);
551   EXPECT_EQ(NumPrivatizedVars, 1U);
552   EXPECT_EQ(NumFinalizationPoints, 1U);
553 
554   Builder.restoreIP(AfterIP);
555   Builder.CreateRetVoid();
556 
557   OMPBuilder.finalize();
558 
559   EXPECT_NE(PrivAI, nullptr);
560   Function *OutlinedFn = PrivAI->getFunction();
561   EXPECT_NE(F, OutlinedFn);
562   EXPECT_FALSE(verifyModule(*M, &errs()));
563   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
564   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
565   EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
566   EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
567 
568   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
569   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
570 
571   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
572   EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
573   User *Usr = OutlinedFn->user_back();
574   ASSERT_TRUE(isa<ConstantExpr>(Usr));
575   CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
576   ASSERT_NE(ForkCI, nullptr);
577 
578   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
579   EXPECT_EQ(ForkCI->arg_size(), 4U);
580   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
581   EXPECT_EQ(ForkCI->getArgOperand(1),
582             ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
583   EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
584   EXPECT_EQ(findStoredValue<AllocaInst>(ForkCI->getArgOperand(3)),
585             F->arg_begin());
586 }
587 
588 TEST_F(OpenMPIRBuilderTest, ParallelNested) {
589   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
590   OpenMPIRBuilder OMPBuilder(*M);
591   OMPBuilder.initialize();
592   F->setName("func");
593   IRBuilder<> Builder(BB);
594 
595   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
596   Builder.CreateBr(EnterBB);
597   Builder.SetInsertPoint(EnterBB);
598   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
599 
600   unsigned NumInnerBodiesGenerated = 0;
601   unsigned NumOuterBodiesGenerated = 0;
602   unsigned NumFinalizationPoints = 0;
603 
604   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
605                             BasicBlock &ContinuationIP) {
606     ++NumInnerBodiesGenerated;
607   };
608 
609   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
610                     Value &Orig, Value &Inner,
611                     Value *&ReplacementValue) -> InsertPointTy {
612     // Trivial copy (=firstprivate).
613     Builder.restoreIP(AllocaIP);
614     Type *VTy = Inner.getType()->getPointerElementType();
615     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
616     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
617     Builder.restoreIP(CodeGenIP);
618     Builder.CreateStore(V, ReplacementValue);
619     return CodeGenIP;
620   };
621 
622   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
623 
624   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
625                             BasicBlock &ContinuationIP) {
626     ++NumOuterBodiesGenerated;
627     Builder.restoreIP(CodeGenIP);
628     BasicBlock *CGBB = CodeGenIP.getBlock();
629     BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint());
630     CGBB->getTerminator()->eraseFromParent();
631     ;
632 
633     IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel(
634         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
635         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
636 
637     Builder.restoreIP(AfterIP);
638     Builder.CreateBr(NewBB);
639   };
640 
641   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
642                                     F->getEntryBlock().getFirstInsertionPt());
643   IRBuilder<>::InsertPoint AfterIP =
644       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
645                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
646 
647   EXPECT_EQ(NumInnerBodiesGenerated, 1U);
648   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
649   EXPECT_EQ(NumFinalizationPoints, 2U);
650 
651   Builder.restoreIP(AfterIP);
652   Builder.CreateRetVoid();
653 
654   OMPBuilder.finalize();
655 
656   EXPECT_EQ(M->size(), 5U);
657   for (Function &OutlinedFn : *M) {
658     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
659       continue;
660     EXPECT_FALSE(verifyModule(*M, &errs()));
661     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
662     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
663     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
664     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
665 
666     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
667     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
668 
669     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
670     User *Usr = OutlinedFn.user_back();
671     ASSERT_TRUE(isa<ConstantExpr>(Usr));
672     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
673     ASSERT_NE(ForkCI, nullptr);
674 
675     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
676     EXPECT_EQ(ForkCI->arg_size(), 3U);
677     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
678     EXPECT_EQ(ForkCI->getArgOperand(1),
679               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
680     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
681   }
682 }
683 
684 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) {
685   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
686   OpenMPIRBuilder OMPBuilder(*M);
687   OMPBuilder.initialize();
688   F->setName("func");
689   IRBuilder<> Builder(BB);
690 
691   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
692   Builder.CreateBr(EnterBB);
693   Builder.SetInsertPoint(EnterBB);
694   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
695 
696   unsigned NumInnerBodiesGenerated = 0;
697   unsigned NumOuterBodiesGenerated = 0;
698   unsigned NumFinalizationPoints = 0;
699 
700   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
701                             BasicBlock &ContinuationIP) {
702     ++NumInnerBodiesGenerated;
703   };
704 
705   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
706                     Value &Orig, Value &Inner,
707                     Value *&ReplacementValue) -> InsertPointTy {
708     // Trivial copy (=firstprivate).
709     Builder.restoreIP(AllocaIP);
710     Type *VTy = Inner.getType()->getPointerElementType();
711     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
712     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
713     Builder.restoreIP(CodeGenIP);
714     Builder.CreateStore(V, ReplacementValue);
715     return CodeGenIP;
716   };
717 
718   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
719 
720   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
721                             BasicBlock &ContinuationIP) {
722     ++NumOuterBodiesGenerated;
723     Builder.restoreIP(CodeGenIP);
724     BasicBlock *CGBB = CodeGenIP.getBlock();
725     BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint());
726     BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt());
727     CGBB->getTerminator()->eraseFromParent();
728     ;
729     NewBB1->getTerminator()->eraseFromParent();
730     ;
731 
732     IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel(
733         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
734         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
735 
736     Builder.restoreIP(AfterIP1);
737     Builder.CreateBr(NewBB1);
738 
739     IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel(
740         InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB,
741         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
742 
743     Builder.restoreIP(AfterIP2);
744     Builder.CreateBr(NewBB2);
745   };
746 
747   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
748                                     F->getEntryBlock().getFirstInsertionPt());
749   IRBuilder<>::InsertPoint AfterIP =
750       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
751                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
752 
753   EXPECT_EQ(NumInnerBodiesGenerated, 2U);
754   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
755   EXPECT_EQ(NumFinalizationPoints, 3U);
756 
757   Builder.restoreIP(AfterIP);
758   Builder.CreateRetVoid();
759 
760   OMPBuilder.finalize();
761 
762   EXPECT_EQ(M->size(), 6U);
763   for (Function &OutlinedFn : *M) {
764     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
765       continue;
766     EXPECT_FALSE(verifyModule(*M, &errs()));
767     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
768     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
769     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
770     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
771 
772     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
773     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
774 
775     unsigned NumAllocas = 0;
776     for (Instruction &I : instructions(OutlinedFn))
777       NumAllocas += isa<AllocaInst>(I);
778     EXPECT_EQ(NumAllocas, 1U);
779 
780     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
781     User *Usr = OutlinedFn.user_back();
782     ASSERT_TRUE(isa<ConstantExpr>(Usr));
783     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
784     ASSERT_NE(ForkCI, nullptr);
785 
786     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
787     EXPECT_EQ(ForkCI->arg_size(), 3U);
788     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
789     EXPECT_EQ(ForkCI->getArgOperand(1),
790               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
791     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
792   }
793 }
794 
795 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
796   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
797   OpenMPIRBuilder OMPBuilder(*M);
798   OMPBuilder.initialize();
799   F->setName("func");
800   IRBuilder<> Builder(BB);
801 
802   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
803   Builder.CreateBr(EnterBB);
804   Builder.SetInsertPoint(EnterBB);
805   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
806 
807   AllocaInst *PrivAI = nullptr;
808 
809   unsigned NumBodiesGenerated = 0;
810   unsigned NumPrivatizedVars = 0;
811   unsigned NumFinalizationPoints = 0;
812 
813   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
814                        BasicBlock &ContinuationIP) {
815     ++NumBodiesGenerated;
816 
817     Builder.restoreIP(AllocaIP);
818     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
819     Builder.CreateStore(F->arg_begin(), PrivAI);
820 
821     Builder.restoreIP(CodeGenIP);
822     Value *PrivLoad =
823         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
824     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
825     Instruction *ThenTerm, *ElseTerm;
826     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
827                                   &ThenTerm, &ElseTerm);
828 
829     Builder.SetInsertPoint(ThenTerm);
830     Builder.CreateBr(&ContinuationIP);
831     ThenTerm->eraseFromParent();
832   };
833 
834   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
835                     Value &Orig, Value &Inner,
836                     Value *&ReplacementValue) -> InsertPointTy {
837     ++NumPrivatizedVars;
838 
839     if (!isa<AllocaInst>(Orig)) {
840       EXPECT_EQ(&Orig, F->arg_begin());
841       ReplacementValue = &Inner;
842       return CodeGenIP;
843     }
844 
845     // Since the original value is an allocation, it has a pointer type and
846     // therefore no additional wrapping should happen.
847     EXPECT_EQ(&Orig, &Inner);
848 
849     // Trivial copy (=firstprivate).
850     Builder.restoreIP(AllocaIP);
851     Type *VTy = Inner.getType()->getPointerElementType();
852     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
853     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
854     Builder.restoreIP(CodeGenIP);
855     Builder.CreateStore(V, ReplacementValue);
856     return CodeGenIP;
857   };
858 
859   auto FiniCB = [&](InsertPointTy CodeGenIP) {
860     ++NumFinalizationPoints;
861     // No destructors.
862   };
863 
864   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
865                                     F->getEntryBlock().getFirstInsertionPt());
866   IRBuilder<>::InsertPoint AfterIP =
867       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
868                                 Builder.CreateIsNotNull(F->arg_begin()),
869                                 nullptr, OMP_PROC_BIND_default, false);
870 
871   EXPECT_EQ(NumBodiesGenerated, 1U);
872   EXPECT_EQ(NumPrivatizedVars, 1U);
873   EXPECT_EQ(NumFinalizationPoints, 1U);
874 
875   Builder.restoreIP(AfterIP);
876   Builder.CreateRetVoid();
877   OMPBuilder.finalize();
878 
879   EXPECT_NE(PrivAI, nullptr);
880   Function *OutlinedFn = PrivAI->getFunction();
881   EXPECT_NE(F, OutlinedFn);
882   EXPECT_FALSE(verifyModule(*M, &errs()));
883 
884   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
885   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
886 
887   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
888   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
889 
890   CallInst *DirectCI = nullptr;
891   CallInst *ForkCI = nullptr;
892   for (User *Usr : OutlinedFn->users()) {
893     if (isa<CallInst>(Usr)) {
894       ASSERT_EQ(DirectCI, nullptr);
895       DirectCI = cast<CallInst>(Usr);
896     } else {
897       ASSERT_TRUE(isa<ConstantExpr>(Usr));
898       ASSERT_EQ(Usr->getNumUses(), 1U);
899       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
900       ForkCI = cast<CallInst>(Usr->user_back());
901     }
902   }
903 
904   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
905   EXPECT_EQ(ForkCI->arg_size(), 4U);
906   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
907   EXPECT_EQ(ForkCI->getArgOperand(1),
908             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
909   Value *StoredForkArg = findStoredValue<AllocaInst>(ForkCI->getArgOperand(3));
910   EXPECT_EQ(StoredForkArg, F->arg_begin());
911 
912   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
913   EXPECT_EQ(DirectCI->arg_size(), 3U);
914   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
915   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
916   Value *StoredDirectArg =
917       findStoredValue<AllocaInst>(DirectCI->getArgOperand(2));
918   EXPECT_EQ(StoredDirectArg, F->arg_begin());
919 }
920 
921 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
922   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
923   OpenMPIRBuilder OMPBuilder(*M);
924   OMPBuilder.initialize();
925   F->setName("func");
926   IRBuilder<> Builder(BB);
927 
928   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
929   Builder.CreateBr(EnterBB);
930   Builder.SetInsertPoint(EnterBB);
931   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
932 
933   unsigned NumBodiesGenerated = 0;
934   unsigned NumPrivatizedVars = 0;
935   unsigned NumFinalizationPoints = 0;
936 
937   CallInst *CheckedBarrier = nullptr;
938   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
939                        BasicBlock &ContinuationIP) {
940     ++NumBodiesGenerated;
941 
942     Builder.restoreIP(CodeGenIP);
943 
944     // Create three barriers, two cancel barriers but only one checked.
945     Function *CBFn, *BFn;
946 
947     Builder.restoreIP(
948         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel));
949 
950     CBFn = M->getFunction("__kmpc_cancel_barrier");
951     BFn = M->getFunction("__kmpc_barrier");
952     ASSERT_NE(CBFn, nullptr);
953     ASSERT_EQ(BFn, nullptr);
954     ASSERT_EQ(CBFn->getNumUses(), 1U);
955     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
956     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
957     CheckedBarrier = cast<CallInst>(CBFn->user_back());
958 
959     Builder.restoreIP(
960         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true));
961     CBFn = M->getFunction("__kmpc_cancel_barrier");
962     BFn = M->getFunction("__kmpc_barrier");
963     ASSERT_NE(CBFn, nullptr);
964     ASSERT_NE(BFn, nullptr);
965     ASSERT_EQ(CBFn->getNumUses(), 1U);
966     ASSERT_EQ(BFn->getNumUses(), 1U);
967     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
968     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
969 
970     Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel,
971                                                false, false));
972     ASSERT_EQ(CBFn->getNumUses(), 2U);
973     ASSERT_EQ(BFn->getNumUses(), 1U);
974     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
975     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
976     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
977   };
978 
979   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &,
980                     Value *&) -> InsertPointTy {
981     ++NumPrivatizedVars;
982     llvm_unreachable("No privatization callback call expected!");
983   };
984 
985   FunctionType *FakeDestructorTy =
986       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
987                         /*isVarArg=*/false);
988   auto *FakeDestructor = Function::Create(
989       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
990 
991   auto FiniCB = [&](InsertPointTy IP) {
992     ++NumFinalizationPoints;
993     Builder.restoreIP(IP);
994     Builder.CreateCall(FakeDestructor,
995                        {Builder.getInt32(NumFinalizationPoints)});
996   };
997 
998   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
999                                     F->getEntryBlock().getFirstInsertionPt());
1000   IRBuilder<>::InsertPoint AfterIP =
1001       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1002                                 Builder.CreateIsNotNull(F->arg_begin()),
1003                                 nullptr, OMP_PROC_BIND_default, true);
1004 
1005   EXPECT_EQ(NumBodiesGenerated, 1U);
1006   EXPECT_EQ(NumPrivatizedVars, 0U);
1007   EXPECT_EQ(NumFinalizationPoints, 2U);
1008   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
1009 
1010   Builder.restoreIP(AfterIP);
1011   Builder.CreateRetVoid();
1012   OMPBuilder.finalize();
1013 
1014   EXPECT_FALSE(verifyModule(*M, &errs()));
1015 
1016   BasicBlock *ExitBB = nullptr;
1017   for (const User *Usr : FakeDestructor->users()) {
1018     const CallInst *CI = dyn_cast<CallInst>(Usr);
1019     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
1020     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
1021     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
1022     if (ExitBB)
1023       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
1024     else
1025       ExitBB = CI->getNextNode()->getSuccessor(0);
1026     ASSERT_EQ(ExitBB->size(), 1U);
1027     if (!isa<ReturnInst>(ExitBB->front())) {
1028       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
1029       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
1030       ASSERT_TRUE(isa<ReturnInst>(
1031           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
1032     }
1033   }
1034 }
1035 
1036 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) {
1037   OpenMPIRBuilder OMPBuilder(*M);
1038   OMPBuilder.initialize();
1039   F->setName("func");
1040   IRBuilder<> Builder(BB);
1041   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1042   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1043 
1044   Type *I32Ty = Type::getInt32Ty(M->getContext());
1045   Type *I32PtrTy = Type::getInt32PtrTy(M->getContext());
1046   Type *StructTy = StructType::get(I32Ty, I32PtrTy);
1047   Type *StructPtrTy = StructTy->getPointerTo();
1048   Type *VoidTy = Type::getVoidTy(M->getContext());
1049   FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty);
1050   FunctionCallee TakeI32Func =
1051       M->getOrInsertFunction("take_i32", VoidTy, I32Ty);
1052   FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy);
1053   FunctionCallee TakeI32PtrFunc =
1054       M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy);
1055   FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy);
1056   FunctionCallee TakeStructFunc =
1057       M->getOrInsertFunction("take_struct", VoidTy, StructTy);
1058   FunctionCallee RetStructPtrFunc =
1059       M->getOrInsertFunction("ret_structptr", StructPtrTy);
1060   FunctionCallee TakeStructPtrFunc =
1061       M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy);
1062   Value *I32Val = Builder.CreateCall(RetI32Func);
1063   Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc);
1064   Value *StructVal = Builder.CreateCall(RetStructFunc);
1065   Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc);
1066 
1067   Instruction *Internal;
1068   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1069                        BasicBlock &ContinuationBB) {
1070     IRBuilder<>::InsertPointGuard Guard(Builder);
1071     Builder.restoreIP(CodeGenIP);
1072     Internal = Builder.CreateCall(TakeI32Func, I32Val);
1073     Builder.CreateCall(TakeI32PtrFunc, I32PtrVal);
1074     Builder.CreateCall(TakeStructFunc, StructVal);
1075     Builder.CreateCall(TakeStructPtrFunc, StructPtrVal);
1076   };
1077   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &,
1078                     Value &Inner, Value *&ReplacementValue) {
1079     ReplacementValue = &Inner;
1080     return CodeGenIP;
1081   };
1082   auto FiniCB = [](InsertPointTy) {};
1083 
1084   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
1085                                     F->getEntryBlock().getFirstInsertionPt());
1086   IRBuilder<>::InsertPoint AfterIP =
1087       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1088                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
1089   Builder.restoreIP(AfterIP);
1090   Builder.CreateRetVoid();
1091 
1092   OMPBuilder.finalize();
1093 
1094   EXPECT_FALSE(verifyModule(*M, &errs()));
1095   Function *OutlinedFn = Internal->getFunction();
1096 
1097   Type *Arg2Type = OutlinedFn->getArg(2)->getType();
1098   EXPECT_TRUE(Arg2Type->isPointerTy());
1099   EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty);
1100 
1101   // Arguments that need to be passed through pointers and reloaded will get
1102   // used earlier in the functions and therefore will appear first in the
1103   // argument list after outlining.
1104   Type *Arg3Type = OutlinedFn->getArg(3)->getType();
1105   EXPECT_TRUE(Arg3Type->isPointerTy());
1106   EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy);
1107 
1108   Type *Arg4Type = OutlinedFn->getArg(4)->getType();
1109   EXPECT_EQ(Arg4Type, I32PtrTy);
1110 
1111   Type *Arg5Type = OutlinedFn->getArg(5)->getType();
1112   EXPECT_EQ(Arg5Type, StructPtrTy);
1113 }
1114 
1115 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) {
1116   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1117   OpenMPIRBuilder OMPBuilder(*M);
1118   OMPBuilder.initialize();
1119   IRBuilder<> Builder(BB);
1120   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1121   Value *TripCount = F->getArg(0);
1122 
1123   unsigned NumBodiesGenerated = 0;
1124   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
1125     NumBodiesGenerated += 1;
1126 
1127     Builder.restoreIP(CodeGenIP);
1128 
1129     Value *Cmp = Builder.CreateICmpEQ(LC, TripCount);
1130     Instruction *ThenTerm, *ElseTerm;
1131     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
1132                                   &ThenTerm, &ElseTerm);
1133   };
1134 
1135   CanonicalLoopInfo *Loop =
1136       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
1137 
1138   Builder.restoreIP(Loop->getAfterIP());
1139   ReturnInst *RetInst = Builder.CreateRetVoid();
1140   OMPBuilder.finalize();
1141 
1142   Loop->assertOK();
1143   EXPECT_FALSE(verifyModule(*M, &errs()));
1144 
1145   EXPECT_EQ(NumBodiesGenerated, 1U);
1146 
1147   // Verify control flow structure (in addition to Loop->assertOK()).
1148   EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock());
1149   EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock());
1150 
1151   Instruction *IndVar = Loop->getIndVar();
1152   EXPECT_TRUE(isa<PHINode>(IndVar));
1153   EXPECT_EQ(IndVar->getType(), TripCount->getType());
1154   EXPECT_EQ(IndVar->getParent(), Loop->getHeader());
1155 
1156   EXPECT_EQ(Loop->getTripCount(), TripCount);
1157 
1158   BasicBlock *Body = Loop->getBody();
1159   Instruction *CmpInst = &Body->getInstList().front();
1160   EXPECT_TRUE(isa<ICmpInst>(CmpInst));
1161   EXPECT_EQ(CmpInst->getOperand(0), IndVar);
1162 
1163   BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor();
1164   EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) {
1165     return SuccBB->getSingleSuccessor() == LatchPred;
1166   }));
1167 
1168   EXPECT_EQ(&Loop->getAfter()->front(), RetInst);
1169 }
1170 
1171 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) {
1172   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1173   OpenMPIRBuilder OMPBuilder(*M);
1174   OMPBuilder.initialize();
1175   IRBuilder<> Builder(BB);
1176 
1177   // Check the trip count is computed correctly. We generate the canonical loop
1178   // but rely on the IRBuilder's constant folder to compute the final result
1179   // since all inputs are constant. To verify overflow situations, limit the
1180   // trip count / loop counter widths to 16 bits.
1181   auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1182                            bool IsSigned, bool InclusiveStop) -> int64_t {
1183     OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1184     Type *LCTy = Type::getInt16Ty(Ctx);
1185     Value *StartVal = ConstantInt::get(LCTy, Start);
1186     Value *StopVal = ConstantInt::get(LCTy, Stop);
1187     Value *StepVal = ConstantInt::get(LCTy, Step);
1188     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1189     CanonicalLoopInfo *Loop =
1190         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1191                                        StepVal, IsSigned, InclusiveStop);
1192     Loop->assertOK();
1193     Builder.restoreIP(Loop->getAfterIP());
1194     Value *TripCount = Loop->getTripCount();
1195     return cast<ConstantInt>(TripCount)->getValue().getZExtValue();
1196   };
1197 
1198   EXPECT_EQ(EvalTripCount(0, 0, 1, false, false), 0);
1199   EXPECT_EQ(EvalTripCount(0, 1, 2, false, false), 1);
1200   EXPECT_EQ(EvalTripCount(0, 42, 1, false, false), 42);
1201   EXPECT_EQ(EvalTripCount(0, 42, 2, false, false), 21);
1202   EXPECT_EQ(EvalTripCount(21, 42, 1, false, false), 21);
1203   EXPECT_EQ(EvalTripCount(0, 5, 5, false, false), 1);
1204   EXPECT_EQ(EvalTripCount(0, 9, 5, false, false), 2);
1205   EXPECT_EQ(EvalTripCount(0, 11, 5, false, false), 3);
1206   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF);
1207   EXPECT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0);
1208   EXPECT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1);
1209   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100);
1210   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1);
1211 
1212   EXPECT_EQ(EvalTripCount(0, 6, 5, false, false), 2);
1213   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2);
1214   EXPECT_EQ(EvalTripCount(0, 0, 1, false, true), 1);
1215   EXPECT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1);
1216   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF);
1217   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000);
1218 
1219   EXPECT_EQ(EvalTripCount(0, 0, -1, true, false), 0);
1220   EXPECT_EQ(EvalTripCount(0, 1, -1, true, true), 0);
1221   EXPECT_EQ(EvalTripCount(20, 5, -5, true, false), 3);
1222   EXPECT_EQ(EvalTripCount(20, 5, -5, true, true), 4);
1223   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, false), 1);
1224   EXPECT_EQ(EvalTripCount(-4, -3, 2, true, false), 1);
1225   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, true), 2);
1226 
1227   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000);
1228   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001);
1229   EXPECT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF);
1230   EXPECT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF);
1231   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2);
1232   EXPECT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF);
1233   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000);
1234   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800);
1235   EXPECT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF);
1236   EXPECT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1);
1237   EXPECT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2);
1238 
1239   // Finalize the function and verify it.
1240   Builder.CreateRetVoid();
1241   OMPBuilder.finalize();
1242   EXPECT_FALSE(verifyModule(*M, &errs()));
1243 }
1244 
1245 TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) {
1246   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1247   OpenMPIRBuilder OMPBuilder(*M);
1248   OMPBuilder.initialize();
1249   F->setName("func");
1250 
1251   IRBuilder<> Builder(BB);
1252 
1253   Type *LCTy = F->getArg(0)->getType();
1254   Constant *One = ConstantInt::get(LCTy, 1);
1255   Constant *Two = ConstantInt::get(LCTy, 2);
1256   Value *OuterTripCount =
1257       Builder.CreateAdd(F->getArg(0), Two, "tripcount.outer");
1258   Value *InnerTripCount =
1259       Builder.CreateAdd(F->getArg(0), One, "tripcount.inner");
1260 
1261   // Fix an insertion point for ComputeIP.
1262   BasicBlock *LoopNextEnter =
1263       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1264                          Builder.GetInsertBlock()->getNextNode());
1265   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1266   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1267 
1268   Builder.SetInsertPoint(LoopNextEnter);
1269   OpenMPIRBuilder::LocationDescription OuterLoc(Builder.saveIP(), DL);
1270 
1271   CanonicalLoopInfo *InnerLoop = nullptr;
1272   CallInst *InbetweenLead = nullptr;
1273   CallInst *InbetweenTrail = nullptr;
1274   CallInst *Call = nullptr;
1275   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, Value *OuterLC) {
1276     Builder.restoreIP(OuterCodeGenIP);
1277     InbetweenLead =
1278         createPrintfCall(Builder, "In-between lead i=%d\\n", {OuterLC});
1279 
1280     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1281                                   Value *InnerLC) {
1282       Builder.restoreIP(InnerCodeGenIP);
1283       Call = createPrintfCall(Builder, "body i=%d j=%d\\n", {OuterLC, InnerLC});
1284     };
1285     InnerLoop = OMPBuilder.createCanonicalLoop(
1286         Builder.saveIP(), InnerLoopBodyGenCB, InnerTripCount, "inner");
1287 
1288     Builder.restoreIP(InnerLoop->getAfterIP());
1289     InbetweenTrail =
1290         createPrintfCall(Builder, "In-between trail i=%d\\n", {OuterLC});
1291   };
1292   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1293       OuterLoc, OuterLoopBodyGenCB, OuterTripCount, "outer");
1294 
1295   // Finish the function.
1296   Builder.restoreIP(OuterLoop->getAfterIP());
1297   Builder.CreateRetVoid();
1298 
1299   CanonicalLoopInfo *Collapsed =
1300       OMPBuilder.collapseLoops(DL, {OuterLoop, InnerLoop}, ComputeIP);
1301 
1302   OMPBuilder.finalize();
1303   EXPECT_FALSE(verifyModule(*M, &errs()));
1304 
1305   // Verify control flow and BB order.
1306   BasicBlock *RefOrder[] = {
1307       Collapsed->getPreheader(),   Collapsed->getHeader(),
1308       Collapsed->getCond(),        Collapsed->getBody(),
1309       InbetweenLead->getParent(),  Call->getParent(),
1310       InbetweenTrail->getParent(), Collapsed->getLatch(),
1311       Collapsed->getExit(),        Collapsed->getAfter(),
1312   };
1313   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1314   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1315 
1316   // Verify the total trip count.
1317   auto *TripCount = cast<MulOperator>(Collapsed->getTripCount());
1318   EXPECT_EQ(TripCount->getOperand(0), OuterTripCount);
1319   EXPECT_EQ(TripCount->getOperand(1), InnerTripCount);
1320 
1321   // Verify the changed indvar.
1322   auto *OuterIV = cast<BinaryOperator>(Call->getOperand(1));
1323   EXPECT_EQ(OuterIV->getOpcode(), Instruction::UDiv);
1324   EXPECT_EQ(OuterIV->getParent(), Collapsed->getBody());
1325   EXPECT_EQ(OuterIV->getOperand(1), InnerTripCount);
1326   EXPECT_EQ(OuterIV->getOperand(0), Collapsed->getIndVar());
1327 
1328   auto *InnerIV = cast<BinaryOperator>(Call->getOperand(2));
1329   EXPECT_EQ(InnerIV->getOpcode(), Instruction::URem);
1330   EXPECT_EQ(InnerIV->getParent(), Collapsed->getBody());
1331   EXPECT_EQ(InnerIV->getOperand(0), Collapsed->getIndVar());
1332   EXPECT_EQ(InnerIV->getOperand(1), InnerTripCount);
1333 
1334   EXPECT_EQ(InbetweenLead->getOperand(1), OuterIV);
1335   EXPECT_EQ(InbetweenTrail->getOperand(1), OuterIV);
1336 }
1337 
1338 TEST_F(OpenMPIRBuilderTest, TileSingleLoop) {
1339   OpenMPIRBuilder OMPBuilder(*M);
1340   Instruction *Call;
1341   BasicBlock *BodyCode;
1342   CanonicalLoopInfo *Loop =
1343       buildSingleLoopFunction(DL, OMPBuilder, &Call, &BodyCode);
1344 
1345   Instruction *OrigIndVar = Loop->getIndVar();
1346   EXPECT_EQ(Call->getOperand(1), OrigIndVar);
1347 
1348   // Tile the loop.
1349   Constant *TileSize = ConstantInt::get(Loop->getIndVarType(), APInt(32, 7));
1350   std::vector<CanonicalLoopInfo *> GenLoops =
1351       OMPBuilder.tileLoops(DL, {Loop}, {TileSize});
1352 
1353   OMPBuilder.finalize();
1354   EXPECT_FALSE(verifyModule(*M, &errs()));
1355 
1356   EXPECT_EQ(GenLoops.size(), 2u);
1357   CanonicalLoopInfo *Floor = GenLoops[0];
1358   CanonicalLoopInfo *Tile = GenLoops[1];
1359 
1360   BasicBlock *RefOrder[] = {
1361       Floor->getPreheader(), Floor->getHeader(),   Floor->getCond(),
1362       Floor->getBody(),      Tile->getPreheader(), Tile->getHeader(),
1363       Tile->getCond(),       Tile->getBody(),      BodyCode,
1364       Tile->getLatch(),      Tile->getExit(),      Tile->getAfter(),
1365       Floor->getLatch(),     Floor->getExit(),     Floor->getAfter(),
1366   };
1367   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1368   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1369 
1370   // Check the induction variable.
1371   EXPECT_EQ(Call->getParent(), BodyCode);
1372   auto *Shift = cast<AddOperator>(Call->getOperand(1));
1373   EXPECT_EQ(cast<Instruction>(Shift)->getParent(), Tile->getBody());
1374   EXPECT_EQ(Shift->getOperand(1), Tile->getIndVar());
1375   auto *Scale = cast<MulOperator>(Shift->getOperand(0));
1376   EXPECT_EQ(cast<Instruction>(Scale)->getParent(), Tile->getBody());
1377   EXPECT_EQ(Scale->getOperand(0), TileSize);
1378   EXPECT_EQ(Scale->getOperand(1), Floor->getIndVar());
1379 }
1380 
1381 TEST_F(OpenMPIRBuilderTest, TileNestedLoops) {
1382   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1383   OpenMPIRBuilder OMPBuilder(*M);
1384   OMPBuilder.initialize();
1385   F->setName("func");
1386 
1387   IRBuilder<> Builder(BB);
1388   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1389   Value *TripCount = F->getArg(0);
1390   Type *LCTy = TripCount->getType();
1391 
1392   BasicBlock *BodyCode = nullptr;
1393   CanonicalLoopInfo *InnerLoop = nullptr;
1394   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1395                                 llvm::Value *OuterLC) {
1396     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1397                                   llvm::Value *InnerLC) {
1398       Builder.restoreIP(InnerCodeGenIP);
1399       BodyCode = Builder.GetInsertBlock();
1400 
1401       // Add something that consumes the induction variables to the body.
1402       createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1403     };
1404     InnerLoop = OMPBuilder.createCanonicalLoop(
1405         OuterCodeGenIP, InnerLoopBodyGenCB, TripCount, "inner");
1406   };
1407   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1408       Loc, OuterLoopBodyGenCB, TripCount, "outer");
1409 
1410   // Finalize the function.
1411   Builder.restoreIP(OuterLoop->getAfterIP());
1412   Builder.CreateRetVoid();
1413 
1414   // Tile to loop nest.
1415   Constant *OuterTileSize = ConstantInt::get(LCTy, APInt(32, 11));
1416   Constant *InnerTileSize = ConstantInt::get(LCTy, APInt(32, 7));
1417   std::vector<CanonicalLoopInfo *> GenLoops = OMPBuilder.tileLoops(
1418       DL, {OuterLoop, InnerLoop}, {OuterTileSize, InnerTileSize});
1419 
1420   OMPBuilder.finalize();
1421   EXPECT_FALSE(verifyModule(*M, &errs()));
1422 
1423   EXPECT_EQ(GenLoops.size(), 4u);
1424   CanonicalLoopInfo *Floor1 = GenLoops[0];
1425   CanonicalLoopInfo *Floor2 = GenLoops[1];
1426   CanonicalLoopInfo *Tile1 = GenLoops[2];
1427   CanonicalLoopInfo *Tile2 = GenLoops[3];
1428 
1429   BasicBlock *RefOrder[] = {
1430       Floor1->getPreheader(),
1431       Floor1->getHeader(),
1432       Floor1->getCond(),
1433       Floor1->getBody(),
1434       Floor2->getPreheader(),
1435       Floor2->getHeader(),
1436       Floor2->getCond(),
1437       Floor2->getBody(),
1438       Tile1->getPreheader(),
1439       Tile1->getHeader(),
1440       Tile1->getCond(),
1441       Tile1->getBody(),
1442       Tile2->getPreheader(),
1443       Tile2->getHeader(),
1444       Tile2->getCond(),
1445       Tile2->getBody(),
1446       BodyCode,
1447       Tile2->getLatch(),
1448       Tile2->getExit(),
1449       Tile2->getAfter(),
1450       Tile1->getLatch(),
1451       Tile1->getExit(),
1452       Tile1->getAfter(),
1453       Floor2->getLatch(),
1454       Floor2->getExit(),
1455       Floor2->getAfter(),
1456       Floor1->getLatch(),
1457       Floor1->getExit(),
1458       Floor1->getAfter(),
1459   };
1460   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1461   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1462 }
1463 
1464 TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) {
1465   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1466   OpenMPIRBuilder OMPBuilder(*M);
1467   OMPBuilder.initialize();
1468   F->setName("func");
1469 
1470   IRBuilder<> Builder(BB);
1471   Value *TripCount = F->getArg(0);
1472   Type *LCTy = TripCount->getType();
1473 
1474   Value *OuterStartVal = ConstantInt::get(LCTy, 2);
1475   Value *OuterStopVal = TripCount;
1476   Value *OuterStep = ConstantInt::get(LCTy, 5);
1477   Value *InnerStartVal = ConstantInt::get(LCTy, 13);
1478   Value *InnerStopVal = TripCount;
1479   Value *InnerStep = ConstantInt::get(LCTy, 3);
1480 
1481   // Fix an insertion point for ComputeIP.
1482   BasicBlock *LoopNextEnter =
1483       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1484                          Builder.GetInsertBlock()->getNextNode());
1485   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1486   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1487 
1488   InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()};
1489   OpenMPIRBuilder::LocationDescription Loc({LoopIP, DL});
1490 
1491   BasicBlock *BodyCode = nullptr;
1492   CanonicalLoopInfo *InnerLoop = nullptr;
1493   CallInst *Call = nullptr;
1494   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1495                                 llvm::Value *OuterLC) {
1496     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1497                                   llvm::Value *InnerLC) {
1498       Builder.restoreIP(InnerCodeGenIP);
1499       BodyCode = Builder.GetInsertBlock();
1500 
1501       // Add something that consumes the induction variable to the body.
1502       Call = createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1503     };
1504     InnerLoop = OMPBuilder.createCanonicalLoop(
1505         OuterCodeGenIP, InnerLoopBodyGenCB, InnerStartVal, InnerStopVal,
1506         InnerStep, false, false, ComputeIP, "inner");
1507   };
1508   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1509       Loc, OuterLoopBodyGenCB, OuterStartVal, OuterStopVal, OuterStep, false,
1510       false, ComputeIP, "outer");
1511 
1512   // Finalize the function
1513   Builder.restoreIP(OuterLoop->getAfterIP());
1514   Builder.CreateRetVoid();
1515 
1516   // Tile the loop nest.
1517   Constant *TileSize0 = ConstantInt::get(LCTy, APInt(32, 11));
1518   Constant *TileSize1 = ConstantInt::get(LCTy, APInt(32, 7));
1519   std::vector<CanonicalLoopInfo *> GenLoops =
1520       OMPBuilder.tileLoops(DL, {OuterLoop, InnerLoop}, {TileSize0, TileSize1});
1521 
1522   OMPBuilder.finalize();
1523   EXPECT_FALSE(verifyModule(*M, &errs()));
1524 
1525   EXPECT_EQ(GenLoops.size(), 4u);
1526   CanonicalLoopInfo *Floor0 = GenLoops[0];
1527   CanonicalLoopInfo *Floor1 = GenLoops[1];
1528   CanonicalLoopInfo *Tile0 = GenLoops[2];
1529   CanonicalLoopInfo *Tile1 = GenLoops[3];
1530 
1531   BasicBlock *RefOrder[] = {
1532       Floor0->getPreheader(),
1533       Floor0->getHeader(),
1534       Floor0->getCond(),
1535       Floor0->getBody(),
1536       Floor1->getPreheader(),
1537       Floor1->getHeader(),
1538       Floor1->getCond(),
1539       Floor1->getBody(),
1540       Tile0->getPreheader(),
1541       Tile0->getHeader(),
1542       Tile0->getCond(),
1543       Tile0->getBody(),
1544       Tile1->getPreheader(),
1545       Tile1->getHeader(),
1546       Tile1->getCond(),
1547       Tile1->getBody(),
1548       BodyCode,
1549       Tile1->getLatch(),
1550       Tile1->getExit(),
1551       Tile1->getAfter(),
1552       Tile0->getLatch(),
1553       Tile0->getExit(),
1554       Tile0->getAfter(),
1555       Floor1->getLatch(),
1556       Floor1->getExit(),
1557       Floor1->getAfter(),
1558       Floor0->getLatch(),
1559       Floor0->getExit(),
1560       Floor0->getAfter(),
1561   };
1562   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1563   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1564 
1565   EXPECT_EQ(Call->getParent(), BodyCode);
1566 
1567   auto *RangeShift0 = cast<AddOperator>(Call->getOperand(1));
1568   EXPECT_EQ(RangeShift0->getOperand(1), OuterStartVal);
1569   auto *RangeScale0 = cast<MulOperator>(RangeShift0->getOperand(0));
1570   EXPECT_EQ(RangeScale0->getOperand(1), OuterStep);
1571   auto *TileShift0 = cast<AddOperator>(RangeScale0->getOperand(0));
1572   EXPECT_EQ(cast<Instruction>(TileShift0)->getParent(), Tile1->getBody());
1573   EXPECT_EQ(TileShift0->getOperand(1), Tile0->getIndVar());
1574   auto *TileScale0 = cast<MulOperator>(TileShift0->getOperand(0));
1575   EXPECT_EQ(cast<Instruction>(TileScale0)->getParent(), Tile1->getBody());
1576   EXPECT_EQ(TileScale0->getOperand(0), TileSize0);
1577   EXPECT_EQ(TileScale0->getOperand(1), Floor0->getIndVar());
1578 
1579   auto *RangeShift1 = cast<AddOperator>(Call->getOperand(2));
1580   EXPECT_EQ(cast<Instruction>(RangeShift1)->getParent(), BodyCode);
1581   EXPECT_EQ(RangeShift1->getOperand(1), InnerStartVal);
1582   auto *RangeScale1 = cast<MulOperator>(RangeShift1->getOperand(0));
1583   EXPECT_EQ(cast<Instruction>(RangeScale1)->getParent(), BodyCode);
1584   EXPECT_EQ(RangeScale1->getOperand(1), InnerStep);
1585   auto *TileShift1 = cast<AddOperator>(RangeScale1->getOperand(0));
1586   EXPECT_EQ(cast<Instruction>(TileShift1)->getParent(), Tile1->getBody());
1587   EXPECT_EQ(TileShift1->getOperand(1), Tile1->getIndVar());
1588   auto *TileScale1 = cast<MulOperator>(TileShift1->getOperand(0));
1589   EXPECT_EQ(cast<Instruction>(TileScale1)->getParent(), Tile1->getBody());
1590   EXPECT_EQ(TileScale1->getOperand(0), TileSize1);
1591   EXPECT_EQ(TileScale1->getOperand(1), Floor1->getIndVar());
1592 }
1593 
1594 TEST_F(OpenMPIRBuilderTest, TileSingleLoopCounts) {
1595   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1596   OpenMPIRBuilder OMPBuilder(*M);
1597   OMPBuilder.initialize();
1598   IRBuilder<> Builder(BB);
1599 
1600   // Create a loop, tile it, and extract its trip count. All input values are
1601   // constant and IRBuilder evaluates all-constant arithmetic inplace, such that
1602   // the floor trip count itself will be a ConstantInt. Unfortunately we cannot
1603   // do the same for the tile loop.
1604   auto GetFloorCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1605                            bool IsSigned, bool InclusiveStop,
1606                            int64_t TileSize) -> uint64_t {
1607     OpenMPIRBuilder::LocationDescription Loc(Builder.saveIP(), DL);
1608     Type *LCTy = Type::getInt16Ty(Ctx);
1609     Value *StartVal = ConstantInt::get(LCTy, Start);
1610     Value *StopVal = ConstantInt::get(LCTy, Stop);
1611     Value *StepVal = ConstantInt::get(LCTy, Step);
1612 
1613     // Generate a loop.
1614     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1615     CanonicalLoopInfo *Loop =
1616         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1617                                        StepVal, IsSigned, InclusiveStop);
1618     InsertPointTy AfterIP = Loop->getAfterIP();
1619 
1620     // Tile the loop.
1621     Value *TileSizeVal = ConstantInt::get(LCTy, TileSize);
1622     std::vector<CanonicalLoopInfo *> GenLoops =
1623         OMPBuilder.tileLoops(Loc.DL, {Loop}, {TileSizeVal});
1624 
1625     // Set the insertion pointer to after loop, where the next loop will be
1626     // emitted.
1627     Builder.restoreIP(AfterIP);
1628 
1629     // Extract the trip count.
1630     CanonicalLoopInfo *FloorLoop = GenLoops[0];
1631     Value *FloorTripCount = FloorLoop->getTripCount();
1632     return cast<ConstantInt>(FloorTripCount)->getValue().getZExtValue();
1633   };
1634 
1635   // Empty iteration domain.
1636   EXPECT_EQ(GetFloorCount(0, 0, 1, false, false, 7), 0u);
1637   EXPECT_EQ(GetFloorCount(0, -1, 1, false, true, 7), 0u);
1638   EXPECT_EQ(GetFloorCount(-1, -1, -1, true, false, 7), 0u);
1639   EXPECT_EQ(GetFloorCount(-1, 0, -1, true, true, 7), 0u);
1640   EXPECT_EQ(GetFloorCount(-1, -1, 3, true, false, 7), 0u);
1641 
1642   // Only complete tiles.
1643   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1644   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1645   EXPECT_EQ(GetFloorCount(1, 15, 1, false, false, 7), 2u);
1646   EXPECT_EQ(GetFloorCount(0, -14, -1, true, false, 7), 2u);
1647   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, true, 7), 2u);
1648   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 2, 3, false, false, 7), 2u);
1649 
1650   // Only a partial tile.
1651   EXPECT_EQ(GetFloorCount(0, 1, 1, false, false, 7), 1u);
1652   EXPECT_EQ(GetFloorCount(0, 6, 1, false, false, 7), 1u);
1653   EXPECT_EQ(GetFloorCount(-1, 1, 3, true, false, 7), 1u);
1654   EXPECT_EQ(GetFloorCount(-1, -2, -1, true, false, 7), 1u);
1655   EXPECT_EQ(GetFloorCount(0, 2, 3, false, false, 7), 1u);
1656 
1657   // Complete and partial tiles.
1658   EXPECT_EQ(GetFloorCount(0, 13, 1, false, false, 7), 2u);
1659   EXPECT_EQ(GetFloorCount(0, 15, 1, false, false, 7), 3u);
1660   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, false, 7), 2u);
1661   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 5 - 1, 3, false, false, 7), 5u);
1662   EXPECT_EQ(GetFloorCount(-1, -3 * 7 * 5, -3, true, false, 7), 5u);
1663 
1664   // Close to 16-bit integer range.
1665   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 1), 0xFFFFu);
1666   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 7), 0xFFFFu / 7 + 1);
1667   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, true, 7), 0xFFFFu / 7 + 1);
1668   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 7), 0xFFFFu / 7 + 1);
1669   EXPECT_EQ(GetFloorCount(-0x7FFF, 0x7FFF, 1, true, true, 7), 0xFFFFu / 7 + 1);
1670   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, false, 0xFFFF), 1u);
1671   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 0xFFFF), 1u);
1672 
1673   // Finalize the function.
1674   Builder.CreateRetVoid();
1675   OMPBuilder.finalize();
1676 
1677   EXPECT_FALSE(verifyModule(*M, &errs()));
1678 }
1679 
1680 TEST_F(OpenMPIRBuilderTest, ApplySimd) {
1681   OpenMPIRBuilder OMPBuilder(*M);
1682 
1683   CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder);
1684 
1685   // Simd-ize the loop.
1686   OMPBuilder.applySimd(DL, CLI);
1687 
1688   OMPBuilder.finalize();
1689   EXPECT_FALSE(verifyModule(*M, &errs()));
1690 
1691   PassBuilder PB;
1692   FunctionAnalysisManager FAM;
1693   PB.registerFunctionAnalyses(FAM);
1694   LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F);
1695 
1696   const std::vector<Loop *> &TopLvl = LI.getTopLevelLoops();
1697   EXPECT_EQ(TopLvl.size(), 1u);
1698 
1699   Loop *L = TopLvl.front();
1700   EXPECT_TRUE(findStringMetadataForLoop(L, "llvm.loop.parallel_accesses"));
1701   EXPECT_TRUE(getBooleanLoopAttribute(L, "llvm.loop.vectorize.enable"));
1702 
1703   // Check for llvm.access.group metadata attached to the printf
1704   // function in the loop body.
1705   BasicBlock *LoopBody = CLI->getBody();
1706   EXPECT_TRUE(any_of(*LoopBody, [](Instruction &I) {
1707     return I.getMetadata("llvm.access.group") != nullptr;
1708   }));
1709 }
1710 
1711 TEST_F(OpenMPIRBuilderTest, UnrollLoopFull) {
1712   OpenMPIRBuilder OMPBuilder(*M);
1713 
1714   CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder);
1715 
1716   // Unroll the loop.
1717   OMPBuilder.unrollLoopFull(DL, CLI);
1718 
1719   OMPBuilder.finalize();
1720   EXPECT_FALSE(verifyModule(*M, &errs()));
1721 
1722   PassBuilder PB;
1723   FunctionAnalysisManager FAM;
1724   PB.registerFunctionAnalyses(FAM);
1725   LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F);
1726 
1727   const std::vector<Loop *> &TopLvl = LI.getTopLevelLoops();
1728   EXPECT_EQ(TopLvl.size(), 1u);
1729 
1730   Loop *L = TopLvl.front();
1731   EXPECT_TRUE(getBooleanLoopAttribute(L, "llvm.loop.unroll.enable"));
1732   EXPECT_TRUE(getBooleanLoopAttribute(L, "llvm.loop.unroll.full"));
1733 }
1734 
1735 TEST_F(OpenMPIRBuilderTest, UnrollLoopPartial) {
1736   OpenMPIRBuilder OMPBuilder(*M);
1737   CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder);
1738 
1739   // Unroll the loop.
1740   CanonicalLoopInfo *UnrolledLoop = nullptr;
1741   OMPBuilder.unrollLoopPartial(DL, CLI, 5, &UnrolledLoop);
1742   ASSERT_NE(UnrolledLoop, nullptr);
1743 
1744   OMPBuilder.finalize();
1745   EXPECT_FALSE(verifyModule(*M, &errs()));
1746   UnrolledLoop->assertOK();
1747 
1748   PassBuilder PB;
1749   FunctionAnalysisManager FAM;
1750   PB.registerFunctionAnalyses(FAM);
1751   LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F);
1752 
1753   const std::vector<Loop *> &TopLvl = LI.getTopLevelLoops();
1754   EXPECT_EQ(TopLvl.size(), 1u);
1755   Loop *Outer = TopLvl.front();
1756   EXPECT_EQ(Outer->getHeader(), UnrolledLoop->getHeader());
1757   EXPECT_EQ(Outer->getLoopLatch(), UnrolledLoop->getLatch());
1758   EXPECT_EQ(Outer->getExitingBlock(), UnrolledLoop->getCond());
1759   EXPECT_EQ(Outer->getExitBlock(), UnrolledLoop->getExit());
1760 
1761   EXPECT_EQ(Outer->getSubLoops().size(), 1u);
1762   Loop *Inner = Outer->getSubLoops().front();
1763 
1764   EXPECT_TRUE(getBooleanLoopAttribute(Inner, "llvm.loop.unroll.enable"));
1765   EXPECT_EQ(getIntLoopAttribute(Inner, "llvm.loop.unroll.count"), 5);
1766 }
1767 
1768 TEST_F(OpenMPIRBuilderTest, UnrollLoopHeuristic) {
1769   OpenMPIRBuilder OMPBuilder(*M);
1770 
1771   CanonicalLoopInfo *CLI = buildSingleLoopFunction(DL, OMPBuilder);
1772 
1773   // Unroll the loop.
1774   OMPBuilder.unrollLoopHeuristic(DL, CLI);
1775 
1776   OMPBuilder.finalize();
1777   EXPECT_FALSE(verifyModule(*M, &errs()));
1778 
1779   PassBuilder PB;
1780   FunctionAnalysisManager FAM;
1781   PB.registerFunctionAnalyses(FAM);
1782   LoopInfo &LI = FAM.getResult<LoopAnalysis>(*F);
1783 
1784   const std::vector<Loop *> &TopLvl = LI.getTopLevelLoops();
1785   EXPECT_EQ(TopLvl.size(), 1u);
1786 
1787   Loop *L = TopLvl.front();
1788   EXPECT_TRUE(getBooleanLoopAttribute(L, "llvm.loop.unroll.enable"));
1789 }
1790 
1791 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) {
1792   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1793   OpenMPIRBuilder OMPBuilder(*M);
1794   OMPBuilder.initialize();
1795   IRBuilder<> Builder(BB);
1796   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1797 
1798   Type *LCTy = Type::getInt32Ty(Ctx);
1799   Value *StartVal = ConstantInt::get(LCTy, 10);
1800   Value *StopVal = ConstantInt::get(LCTy, 52);
1801   Value *StepVal = ConstantInt::get(LCTy, 2);
1802   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1803 
1804   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1805       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1806       /*IsSigned=*/false, /*InclusiveStop=*/false);
1807   BasicBlock *Preheader = CLI->getPreheader();
1808   BasicBlock *Body = CLI->getBody();
1809   Value *IV = CLI->getIndVar();
1810   BasicBlock *ExitBlock = CLI->getExit();
1811 
1812   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1813   InsertPointTy AllocaIP = Builder.saveIP();
1814 
1815   OMPBuilder.applyStaticWorkshareLoop(DL, CLI, AllocaIP, /*NeedsBarrier=*/true);
1816 
1817   BasicBlock *Cond = Body->getSinglePredecessor();
1818   Instruction *Cmp = &*Cond->begin();
1819   Value *TripCount = Cmp->getOperand(1);
1820 
1821   auto AllocaIter = BB->begin();
1822   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1823   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1824   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1825   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1826   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1827   EXPECT_NE(PLastIter, nullptr);
1828   EXPECT_NE(PLowerBound, nullptr);
1829   EXPECT_NE(PUpperBound, nullptr);
1830   EXPECT_NE(PStride, nullptr);
1831 
1832   auto PreheaderIter = Preheader->begin();
1833   ASSERT_GE(std::distance(Preheader->begin(), Preheader->end()), 7);
1834   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1835   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1836   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1837   ASSERT_NE(LowerBoundStore, nullptr);
1838   ASSERT_NE(UpperBoundStore, nullptr);
1839   ASSERT_NE(StrideStore, nullptr);
1840 
1841   auto *OrigLowerBound =
1842       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1843   auto *OrigUpperBound =
1844       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1845   auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1846   ASSERT_NE(OrigLowerBound, nullptr);
1847   ASSERT_NE(OrigUpperBound, nullptr);
1848   ASSERT_NE(OrigStride, nullptr);
1849   EXPECT_EQ(OrigLowerBound->getValue(), 0);
1850   EXPECT_EQ(OrigUpperBound->getValue(), 20);
1851   EXPECT_EQ(OrigStride->getValue(), 1);
1852 
1853   // Check that the loop IV is updated to account for the lower bound returned
1854   // by the OpenMP runtime call.
1855   BinaryOperator *Add = dyn_cast<BinaryOperator>(&Body->front());
1856   EXPECT_EQ(Add->getOperand(0), IV);
1857   auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1));
1858   ASSERT_NE(LoadedLowerBound, nullptr);
1859   EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound);
1860 
1861   // Check that the trip count is updated to account for the lower and upper
1862   // bounds return by the OpenMP runtime call.
1863   auto *AddOne = dyn_cast<Instruction>(TripCount);
1864   ASSERT_NE(AddOne, nullptr);
1865   ASSERT_TRUE(AddOne->isBinaryOp());
1866   auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1));
1867   ASSERT_NE(One, nullptr);
1868   EXPECT_EQ(One->getValue(), 1);
1869   auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0));
1870   ASSERT_NE(Difference, nullptr);
1871   ASSERT_TRUE(Difference->isBinaryOp());
1872   EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound);
1873   auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0));
1874   ASSERT_NE(LoadedUpperBound, nullptr);
1875   EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound);
1876 
1877   // The original loop iterator should only be used in the condition, in the
1878   // increment and in the statement that adds the lower bound to it.
1879   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1880 
1881   // The exit block should contain the "fini" call and the barrier call,
1882   // plus the call to obtain the thread ID.
1883   size_t NumCallsInExitBlock =
1884       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1885   EXPECT_EQ(NumCallsInExitBlock, 3u);
1886 }
1887 
1888 TEST_P(OpenMPIRBuilderTestWithParams, DynamicWorkShareLoop) {
1889   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1890   OpenMPIRBuilder OMPBuilder(*M);
1891   OMPBuilder.initialize();
1892   IRBuilder<> Builder(BB);
1893   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1894 
1895   omp::OMPScheduleType SchedType = GetParam();
1896   uint32_t ChunkSize = 1;
1897   switch (SchedType & ~omp::OMPScheduleType::ModifierMask) {
1898   case omp::OMPScheduleType::DynamicChunked:
1899   case omp::OMPScheduleType::GuidedChunked:
1900     ChunkSize = 7;
1901     break;
1902   case omp::OMPScheduleType::Auto:
1903   case omp::OMPScheduleType::Runtime:
1904     ChunkSize = 1;
1905     break;
1906   default:
1907     assert(0 && "unknown type for this test");
1908     break;
1909   }
1910 
1911   Type *LCTy = Type::getInt32Ty(Ctx);
1912   Value *StartVal = ConstantInt::get(LCTy, 10);
1913   Value *StopVal = ConstantInt::get(LCTy, 52);
1914   Value *StepVal = ConstantInt::get(LCTy, 2);
1915   Value *ChunkVal = ConstantInt::get(LCTy, ChunkSize);
1916   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1917 
1918   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1919       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1920       /*IsSigned=*/false, /*InclusiveStop=*/false);
1921 
1922   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1923   InsertPointTy AllocaIP = Builder.saveIP();
1924 
1925   // Collect all the info from CLI, as it isn't usable after the call to
1926   // createDynamicWorkshareLoop.
1927   InsertPointTy AfterIP = CLI->getAfterIP();
1928   BasicBlock *Preheader = CLI->getPreheader();
1929   BasicBlock *ExitBlock = CLI->getExit();
1930   Value *IV = CLI->getIndVar();
1931 
1932   InsertPointTy EndIP =
1933       OMPBuilder.applyDynamicWorkshareLoop(DL, CLI, AllocaIP, SchedType,
1934                                            /*NeedsBarrier=*/true, ChunkVal);
1935   // The returned value should be the "after" point.
1936   ASSERT_EQ(EndIP.getBlock(), AfterIP.getBlock());
1937   ASSERT_EQ(EndIP.getPoint(), AfterIP.getPoint());
1938 
1939   auto AllocaIter = BB->begin();
1940   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1941   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1942   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1943   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1944   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1945   EXPECT_NE(PLastIter, nullptr);
1946   EXPECT_NE(PLowerBound, nullptr);
1947   EXPECT_NE(PUpperBound, nullptr);
1948   EXPECT_NE(PStride, nullptr);
1949 
1950   auto PreheaderIter = Preheader->begin();
1951   ASSERT_GE(std::distance(Preheader->begin(), Preheader->end()), 6);
1952   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1953   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1954   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1955   ASSERT_NE(LowerBoundStore, nullptr);
1956   ASSERT_NE(UpperBoundStore, nullptr);
1957   ASSERT_NE(StrideStore, nullptr);
1958 
1959   CallInst *ThreadIdCall = dyn_cast<CallInst>(&*(PreheaderIter++));
1960   ASSERT_NE(ThreadIdCall, nullptr);
1961   EXPECT_EQ(ThreadIdCall->getCalledFunction()->getName(),
1962             "__kmpc_global_thread_num");
1963 
1964   CallInst *InitCall = dyn_cast<CallInst>(&*PreheaderIter);
1965 
1966   ASSERT_NE(InitCall, nullptr);
1967   EXPECT_EQ(InitCall->getCalledFunction()->getName(),
1968             "__kmpc_dispatch_init_4u");
1969   EXPECT_EQ(InitCall->arg_size(), 7U);
1970   EXPECT_EQ(InitCall->getArgOperand(6), ConstantInt::get(LCTy, ChunkSize));
1971   ConstantInt *SchedVal = cast<ConstantInt>(InitCall->getArgOperand(2));
1972   EXPECT_EQ(SchedVal->getValue(), static_cast<uint64_t>(SchedType));
1973 
1974   ConstantInt *OrigLowerBound =
1975       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1976   ConstantInt *OrigUpperBound =
1977       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1978   ConstantInt *OrigStride =
1979       dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1980   ASSERT_NE(OrigLowerBound, nullptr);
1981   ASSERT_NE(OrigUpperBound, nullptr);
1982   ASSERT_NE(OrigStride, nullptr);
1983   EXPECT_EQ(OrigLowerBound->getValue(), 1);
1984   EXPECT_EQ(OrigUpperBound->getValue(), 21);
1985   EXPECT_EQ(OrigStride->getValue(), 1);
1986 
1987   // The original loop iterator should only be used in the condition, in the
1988   // increment and in the statement that adds the lower bound to it.
1989   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1990 
1991   // The exit block should contain the barrier call, plus the call to obtain
1992   // the thread ID.
1993   size_t NumCallsInExitBlock =
1994       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1995   EXPECT_EQ(NumCallsInExitBlock, 2u);
1996 
1997   // Add a termination to our block and check that it is internally consistent.
1998   Builder.restoreIP(EndIP);
1999   Builder.CreateRetVoid();
2000   OMPBuilder.finalize();
2001   EXPECT_FALSE(verifyModule(*M, &errs()));
2002 }
2003 
2004 INSTANTIATE_TEST_SUITE_P(
2005     OpenMPWSLoopSchedulingTypes, OpenMPIRBuilderTestWithParams,
2006     ::testing::Values(omp::OMPScheduleType::DynamicChunked,
2007                       omp::OMPScheduleType::GuidedChunked,
2008                       omp::OMPScheduleType::Auto, omp::OMPScheduleType::Runtime,
2009                       omp::OMPScheduleType::DynamicChunked |
2010                           omp::OMPScheduleType::ModifierMonotonic,
2011                       omp::OMPScheduleType::DynamicChunked |
2012                           omp::OMPScheduleType::ModifierNonmonotonic,
2013                       omp::OMPScheduleType::GuidedChunked |
2014                           omp::OMPScheduleType::ModifierMonotonic,
2015                       omp::OMPScheduleType::GuidedChunked |
2016                           omp::OMPScheduleType::ModifierNonmonotonic,
2017                       omp::OMPScheduleType::Auto |
2018                           omp::OMPScheduleType::ModifierMonotonic,
2019                       omp::OMPScheduleType::Runtime |
2020                           omp::OMPScheduleType::ModifierMonotonic));
2021 
2022 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
2023   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2024   OpenMPIRBuilder OMPBuilder(*M);
2025   OMPBuilder.initialize();
2026   F->setName("func");
2027   IRBuilder<> Builder(BB);
2028 
2029   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2030 
2031   AllocaInst *PrivAI = nullptr;
2032 
2033   BasicBlock *EntryBB = nullptr;
2034   BasicBlock *ExitBB = nullptr;
2035   BasicBlock *ThenBB = nullptr;
2036 
2037   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2038                        BasicBlock &FiniBB) {
2039     if (AllocaIP.isSet())
2040       Builder.restoreIP(AllocaIP);
2041     else
2042       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
2043     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2044     Builder.CreateStore(F->arg_begin(), PrivAI);
2045 
2046     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2047     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2048     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2049 
2050     Builder.restoreIP(CodeGenIP);
2051 
2052     // collect some info for checks later
2053     ExitBB = FiniBB.getUniqueSuccessor();
2054     ThenBB = Builder.GetInsertBlock();
2055     EntryBB = ThenBB->getUniquePredecessor();
2056 
2057     // simple instructions for body
2058     Value *PrivLoad =
2059         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2060     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2061   };
2062 
2063   auto FiniCB = [&](InsertPointTy IP) {
2064     BasicBlock *IPBB = IP.getBlock();
2065     EXPECT_NE(IPBB->end(), IP.getPoint());
2066   };
2067 
2068   Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
2069   Value *EntryBBTI = EntryBB->getTerminator();
2070   EXPECT_NE(EntryBBTI, nullptr);
2071   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2072   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2073   EXPECT_TRUE(EntryBr->isConditional());
2074   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2075   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2076   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2077 
2078   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2079   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2080 
2081   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
2082   EXPECT_EQ(MasterEntryCI->arg_size(), 2U);
2083   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
2084   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
2085 
2086   CallInst *MasterEndCI = nullptr;
2087   for (auto &FI : *ThenBB) {
2088     Instruction *cur = &FI;
2089     if (isa<CallInst>(cur)) {
2090       MasterEndCI = cast<CallInst>(cur);
2091       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
2092         break;
2093       MasterEndCI = nullptr;
2094     }
2095   }
2096   EXPECT_NE(MasterEndCI, nullptr);
2097   EXPECT_EQ(MasterEndCI->arg_size(), 2U);
2098   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
2099   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
2100 }
2101 
2102 TEST_F(OpenMPIRBuilderTest, MaskedDirective) {
2103   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2104   OpenMPIRBuilder OMPBuilder(*M);
2105   OMPBuilder.initialize();
2106   F->setName("func");
2107   IRBuilder<> Builder(BB);
2108 
2109   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2110 
2111   AllocaInst *PrivAI = nullptr;
2112 
2113   BasicBlock *EntryBB = nullptr;
2114   BasicBlock *ExitBB = nullptr;
2115   BasicBlock *ThenBB = nullptr;
2116 
2117   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2118                        BasicBlock &FiniBB) {
2119     if (AllocaIP.isSet())
2120       Builder.restoreIP(AllocaIP);
2121     else
2122       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
2123     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2124     Builder.CreateStore(F->arg_begin(), PrivAI);
2125 
2126     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2127     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2128     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2129 
2130     Builder.restoreIP(CodeGenIP);
2131 
2132     // collect some info for checks later
2133     ExitBB = FiniBB.getUniqueSuccessor();
2134     ThenBB = Builder.GetInsertBlock();
2135     EntryBB = ThenBB->getUniquePredecessor();
2136 
2137     // simple instructions for body
2138     Value *PrivLoad =
2139         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2140     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2141   };
2142 
2143   auto FiniCB = [&](InsertPointTy IP) {
2144     BasicBlock *IPBB = IP.getBlock();
2145     EXPECT_NE(IPBB->end(), IP.getPoint());
2146   };
2147 
2148   Constant *Filter = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0);
2149   Builder.restoreIP(
2150       OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, Filter));
2151   Value *EntryBBTI = EntryBB->getTerminator();
2152   EXPECT_NE(EntryBBTI, nullptr);
2153   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2154   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2155   EXPECT_TRUE(EntryBr->isConditional());
2156   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2157   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2158   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2159 
2160   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2161   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2162 
2163   CallInst *MaskedEntryCI = cast<CallInst>(CondInst->getOperand(0));
2164   EXPECT_EQ(MaskedEntryCI->arg_size(), 3U);
2165   EXPECT_EQ(MaskedEntryCI->getCalledFunction()->getName(), "__kmpc_masked");
2166   EXPECT_TRUE(isa<GlobalVariable>(MaskedEntryCI->getArgOperand(0)));
2167 
2168   CallInst *MaskedEndCI = nullptr;
2169   for (auto &FI : *ThenBB) {
2170     Instruction *cur = &FI;
2171     if (isa<CallInst>(cur)) {
2172       MaskedEndCI = cast<CallInst>(cur);
2173       if (MaskedEndCI->getCalledFunction()->getName() == "__kmpc_end_masked")
2174         break;
2175       MaskedEndCI = nullptr;
2176     }
2177   }
2178   EXPECT_NE(MaskedEndCI, nullptr);
2179   EXPECT_EQ(MaskedEndCI->arg_size(), 2U);
2180   EXPECT_TRUE(isa<GlobalVariable>(MaskedEndCI->getArgOperand(0)));
2181   EXPECT_EQ(MaskedEndCI->getArgOperand(1), MaskedEntryCI->getArgOperand(1));
2182 }
2183 
2184 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
2185   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2186   OpenMPIRBuilder OMPBuilder(*M);
2187   OMPBuilder.initialize();
2188   F->setName("func");
2189   IRBuilder<> Builder(BB);
2190 
2191   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2192 
2193   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2194 
2195   BasicBlock *EntryBB = nullptr;
2196 
2197   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2198                        BasicBlock &FiniBB) {
2199     // collect some info for checks later
2200     EntryBB = FiniBB.getUniquePredecessor();
2201 
2202     // actual start for bodyCB
2203     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2204     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2205     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2206     EXPECT_EQ(EntryBB, CodeGenIPBB);
2207 
2208     // body begin
2209     Builder.restoreIP(CodeGenIP);
2210     Builder.CreateStore(F->arg_begin(), PrivAI);
2211     Value *PrivLoad =
2212         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2213     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2214   };
2215 
2216   auto FiniCB = [&](InsertPointTy IP) {
2217     BasicBlock *IPBB = IP.getBlock();
2218     EXPECT_NE(IPBB->end(), IP.getPoint());
2219   };
2220 
2221   Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
2222                                               "testCRT", nullptr));
2223 
2224   Value *EntryBBTI = EntryBB->getTerminator();
2225   EXPECT_EQ(EntryBBTI, nullptr);
2226 
2227   CallInst *CriticalEntryCI = nullptr;
2228   for (auto &EI : *EntryBB) {
2229     Instruction *cur = &EI;
2230     if (isa<CallInst>(cur)) {
2231       CriticalEntryCI = cast<CallInst>(cur);
2232       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
2233         break;
2234       CriticalEntryCI = nullptr;
2235     }
2236   }
2237   EXPECT_NE(CriticalEntryCI, nullptr);
2238   EXPECT_EQ(CriticalEntryCI->arg_size(), 3U);
2239   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
2240   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
2241 
2242   CallInst *CriticalEndCI = nullptr;
2243   for (auto &FI : *EntryBB) {
2244     Instruction *cur = &FI;
2245     if (isa<CallInst>(cur)) {
2246       CriticalEndCI = cast<CallInst>(cur);
2247       if (CriticalEndCI->getCalledFunction()->getName() ==
2248           "__kmpc_end_critical")
2249         break;
2250       CriticalEndCI = nullptr;
2251     }
2252   }
2253   EXPECT_NE(CriticalEndCI, nullptr);
2254   EXPECT_EQ(CriticalEndCI->arg_size(), 3U);
2255   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
2256   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
2257   PointerType *CriticalNamePtrTy =
2258       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
2259   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
2260   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
2261 }
2262 
2263 TEST_F(OpenMPIRBuilderTest, OrderedDirectiveDependSource) {
2264   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2265   OpenMPIRBuilder OMPBuilder(*M);
2266   OMPBuilder.initialize();
2267   F->setName("func");
2268   IRBuilder<> Builder(BB);
2269   LLVMContext &Ctx = M->getContext();
2270 
2271   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2272 
2273   InsertPointTy AllocaIP(&F->getEntryBlock(),
2274                          F->getEntryBlock().getFirstInsertionPt());
2275 
2276   unsigned NumLoops = 2;
2277   SmallVector<Value *, 2> StoreValues;
2278   Type *LCTy = Type::getInt64Ty(Ctx);
2279   StoreValues.emplace_back(ConstantInt::get(LCTy, 1));
2280   StoreValues.emplace_back(ConstantInt::get(LCTy, 2));
2281 
2282   // Test for "#omp ordered depend(source)"
2283   Builder.restoreIP(OMPBuilder.createOrderedDepend(Builder, AllocaIP, NumLoops,
2284                                                    StoreValues, ".cnt.addr",
2285                                                    /*IsDependSource=*/true));
2286 
2287   Builder.CreateRetVoid();
2288   OMPBuilder.finalize();
2289   EXPECT_FALSE(verifyModule(*M, &errs()));
2290 
2291   AllocaInst *AllocInst = dyn_cast<AllocaInst>(&BB->front());
2292   ASSERT_NE(AllocInst, nullptr);
2293   ArrayType *ArrType = dyn_cast<ArrayType>(AllocInst->getAllocatedType());
2294   EXPECT_EQ(ArrType->getNumElements(), NumLoops);
2295   EXPECT_TRUE(
2296       AllocInst->getAllocatedType()->getArrayElementType()->isIntegerTy(64));
2297 
2298   Instruction *IterInst = dyn_cast<Instruction>(AllocInst);
2299   for (unsigned Iter = 0; Iter < NumLoops; Iter++) {
2300     GetElementPtrInst *DependAddrGEPIter =
2301         dyn_cast<GetElementPtrInst>(IterInst->getNextNode());
2302     ASSERT_NE(DependAddrGEPIter, nullptr);
2303     EXPECT_EQ(DependAddrGEPIter->getPointerOperand(), AllocInst);
2304     EXPECT_EQ(DependAddrGEPIter->getNumIndices(), (unsigned)2);
2305     auto *FirstIdx = dyn_cast<ConstantInt>(DependAddrGEPIter->getOperand(1));
2306     auto *SecondIdx = dyn_cast<ConstantInt>(DependAddrGEPIter->getOperand(2));
2307     ASSERT_NE(FirstIdx, nullptr);
2308     ASSERT_NE(SecondIdx, nullptr);
2309     EXPECT_EQ(FirstIdx->getValue(), 0);
2310     EXPECT_EQ(SecondIdx->getValue(), Iter);
2311     StoreInst *StoreValue =
2312         dyn_cast<StoreInst>(DependAddrGEPIter->getNextNode());
2313     ASSERT_NE(StoreValue, nullptr);
2314     EXPECT_EQ(StoreValue->getValueOperand(), StoreValues[Iter]);
2315     EXPECT_EQ(StoreValue->getPointerOperand(), DependAddrGEPIter);
2316     EXPECT_EQ(StoreValue->getAlignment(), 8UL);
2317     IterInst = dyn_cast<Instruction>(StoreValue);
2318   }
2319 
2320   GetElementPtrInst *DependBaseAddrGEP =
2321       dyn_cast<GetElementPtrInst>(IterInst->getNextNode());
2322   ASSERT_NE(DependBaseAddrGEP, nullptr);
2323   EXPECT_EQ(DependBaseAddrGEP->getPointerOperand(), AllocInst);
2324   EXPECT_EQ(DependBaseAddrGEP->getNumIndices(), (unsigned)2);
2325   auto *FirstIdx = dyn_cast<ConstantInt>(DependBaseAddrGEP->getOperand(1));
2326   auto *SecondIdx = dyn_cast<ConstantInt>(DependBaseAddrGEP->getOperand(2));
2327   ASSERT_NE(FirstIdx, nullptr);
2328   ASSERT_NE(SecondIdx, nullptr);
2329   EXPECT_EQ(FirstIdx->getValue(), 0);
2330   EXPECT_EQ(SecondIdx->getValue(), 0);
2331 
2332   CallInst *GTID = dyn_cast<CallInst>(DependBaseAddrGEP->getNextNode());
2333   ASSERT_NE(GTID, nullptr);
2334   EXPECT_EQ(GTID->arg_size(), 1U);
2335   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
2336   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
2337   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
2338 
2339   CallInst *Depend = dyn_cast<CallInst>(GTID->getNextNode());
2340   ASSERT_NE(Depend, nullptr);
2341   EXPECT_EQ(Depend->arg_size(), 3U);
2342   EXPECT_EQ(Depend->getCalledFunction()->getName(), "__kmpc_doacross_post");
2343   EXPECT_TRUE(isa<GlobalVariable>(Depend->getArgOperand(0)));
2344   EXPECT_EQ(Depend->getArgOperand(1), GTID);
2345   EXPECT_EQ(Depend->getArgOperand(2), DependBaseAddrGEP);
2346 }
2347 
2348 TEST_F(OpenMPIRBuilderTest, OrderedDirectiveDependSink) {
2349   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2350   OpenMPIRBuilder OMPBuilder(*M);
2351   OMPBuilder.initialize();
2352   F->setName("func");
2353   IRBuilder<> Builder(BB);
2354   LLVMContext &Ctx = M->getContext();
2355 
2356   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2357 
2358   InsertPointTy AllocaIP(&F->getEntryBlock(),
2359                          F->getEntryBlock().getFirstInsertionPt());
2360 
2361   unsigned NumLoops = 2;
2362   SmallVector<Value *, 2> StoreValues;
2363   Type *LCTy = Type::getInt64Ty(Ctx);
2364   StoreValues.emplace_back(ConstantInt::get(LCTy, 1));
2365   StoreValues.emplace_back(ConstantInt::get(LCTy, 2));
2366 
2367   // Test for "#omp ordered depend(sink: vec)"
2368   Builder.restoreIP(OMPBuilder.createOrderedDepend(Builder, AllocaIP, NumLoops,
2369                                                    StoreValues, ".cnt.addr",
2370                                                    /*IsDependSource=*/false));
2371 
2372   Builder.CreateRetVoid();
2373   OMPBuilder.finalize();
2374   EXPECT_FALSE(verifyModule(*M, &errs()));
2375 
2376   AllocaInst *AllocInst = dyn_cast<AllocaInst>(&BB->front());
2377   ASSERT_NE(AllocInst, nullptr);
2378   ArrayType *ArrType = dyn_cast<ArrayType>(AllocInst->getAllocatedType());
2379   EXPECT_EQ(ArrType->getNumElements(), NumLoops);
2380   EXPECT_TRUE(
2381       AllocInst->getAllocatedType()->getArrayElementType()->isIntegerTy(64));
2382 
2383   Instruction *IterInst = dyn_cast<Instruction>(AllocInst);
2384   for (unsigned Iter = 0; Iter < NumLoops; Iter++) {
2385     GetElementPtrInst *DependAddrGEPIter =
2386         dyn_cast<GetElementPtrInst>(IterInst->getNextNode());
2387     ASSERT_NE(DependAddrGEPIter, nullptr);
2388     EXPECT_EQ(DependAddrGEPIter->getPointerOperand(), AllocInst);
2389     EXPECT_EQ(DependAddrGEPIter->getNumIndices(), (unsigned)2);
2390     auto *FirstIdx = dyn_cast<ConstantInt>(DependAddrGEPIter->getOperand(1));
2391     auto *SecondIdx = dyn_cast<ConstantInt>(DependAddrGEPIter->getOperand(2));
2392     ASSERT_NE(FirstIdx, nullptr);
2393     ASSERT_NE(SecondIdx, nullptr);
2394     EXPECT_EQ(FirstIdx->getValue(), 0);
2395     EXPECT_EQ(SecondIdx->getValue(), Iter);
2396     StoreInst *StoreValue =
2397         dyn_cast<StoreInst>(DependAddrGEPIter->getNextNode());
2398     ASSERT_NE(StoreValue, nullptr);
2399     EXPECT_EQ(StoreValue->getValueOperand(), StoreValues[Iter]);
2400     EXPECT_EQ(StoreValue->getPointerOperand(), DependAddrGEPIter);
2401     EXPECT_EQ(StoreValue->getAlignment(), 8UL);
2402     IterInst = dyn_cast<Instruction>(StoreValue);
2403   }
2404 
2405   GetElementPtrInst *DependBaseAddrGEP =
2406       dyn_cast<GetElementPtrInst>(IterInst->getNextNode());
2407   ASSERT_NE(DependBaseAddrGEP, nullptr);
2408   EXPECT_EQ(DependBaseAddrGEP->getPointerOperand(), AllocInst);
2409   EXPECT_EQ(DependBaseAddrGEP->getNumIndices(), (unsigned)2);
2410   auto *FirstIdx = dyn_cast<ConstantInt>(DependBaseAddrGEP->getOperand(1));
2411   auto *SecondIdx = dyn_cast<ConstantInt>(DependBaseAddrGEP->getOperand(2));
2412   ASSERT_NE(FirstIdx, nullptr);
2413   ASSERT_NE(SecondIdx, nullptr);
2414   EXPECT_EQ(FirstIdx->getValue(), 0);
2415   EXPECT_EQ(SecondIdx->getValue(), 0);
2416 
2417   CallInst *GTID = dyn_cast<CallInst>(DependBaseAddrGEP->getNextNode());
2418   ASSERT_NE(GTID, nullptr);
2419   EXPECT_EQ(GTID->arg_size(), 1U);
2420   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
2421   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
2422   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
2423 
2424   CallInst *Depend = dyn_cast<CallInst>(GTID->getNextNode());
2425   ASSERT_NE(Depend, nullptr);
2426   EXPECT_EQ(Depend->arg_size(), 3U);
2427   EXPECT_EQ(Depend->getCalledFunction()->getName(), "__kmpc_doacross_wait");
2428   EXPECT_TRUE(isa<GlobalVariable>(Depend->getArgOperand(0)));
2429   EXPECT_EQ(Depend->getArgOperand(1), GTID);
2430   EXPECT_EQ(Depend->getArgOperand(2), DependBaseAddrGEP);
2431 }
2432 
2433 TEST_F(OpenMPIRBuilderTest, OrderedDirectiveThreads) {
2434   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2435   OpenMPIRBuilder OMPBuilder(*M);
2436   OMPBuilder.initialize();
2437   F->setName("func");
2438   IRBuilder<> Builder(BB);
2439 
2440   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2441 
2442   AllocaInst *PrivAI =
2443       Builder.CreateAlloca(F->arg_begin()->getType(), nullptr, "priv.inst");
2444 
2445   BasicBlock *EntryBB = nullptr;
2446 
2447   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2448                        BasicBlock &FiniBB) {
2449     EntryBB = FiniBB.getUniquePredecessor();
2450 
2451     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2452     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2453     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2454     EXPECT_EQ(EntryBB, CodeGenIPBB);
2455 
2456     Builder.restoreIP(CodeGenIP);
2457     Builder.CreateStore(F->arg_begin(), PrivAI);
2458     Value *PrivLoad =
2459         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2460     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2461   };
2462 
2463   auto FiniCB = [&](InsertPointTy IP) {
2464     BasicBlock *IPBB = IP.getBlock();
2465     EXPECT_NE(IPBB->end(), IP.getPoint());
2466   };
2467 
2468   // Test for "#omp ordered [threads]"
2469   Builder.restoreIP(
2470       OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, true));
2471 
2472   Builder.CreateRetVoid();
2473   OMPBuilder.finalize();
2474   EXPECT_FALSE(verifyModule(*M, &errs()));
2475 
2476   EXPECT_NE(EntryBB->getTerminator(), nullptr);
2477 
2478   CallInst *OrderedEntryCI = nullptr;
2479   for (auto &EI : *EntryBB) {
2480     Instruction *Cur = &EI;
2481     if (isa<CallInst>(Cur)) {
2482       OrderedEntryCI = cast<CallInst>(Cur);
2483       if (OrderedEntryCI->getCalledFunction()->getName() == "__kmpc_ordered")
2484         break;
2485       OrderedEntryCI = nullptr;
2486     }
2487   }
2488   EXPECT_NE(OrderedEntryCI, nullptr);
2489   EXPECT_EQ(OrderedEntryCI->arg_size(), 2U);
2490   EXPECT_EQ(OrderedEntryCI->getCalledFunction()->getName(), "__kmpc_ordered");
2491   EXPECT_TRUE(isa<GlobalVariable>(OrderedEntryCI->getArgOperand(0)));
2492 
2493   CallInst *OrderedEndCI = nullptr;
2494   for (auto &FI : *EntryBB) {
2495     Instruction *Cur = &FI;
2496     if (isa<CallInst>(Cur)) {
2497       OrderedEndCI = cast<CallInst>(Cur);
2498       if (OrderedEndCI->getCalledFunction()->getName() == "__kmpc_end_ordered")
2499         break;
2500       OrderedEndCI = nullptr;
2501     }
2502   }
2503   EXPECT_NE(OrderedEndCI, nullptr);
2504   EXPECT_EQ(OrderedEndCI->arg_size(), 2U);
2505   EXPECT_TRUE(isa<GlobalVariable>(OrderedEndCI->getArgOperand(0)));
2506   EXPECT_EQ(OrderedEndCI->getArgOperand(1), OrderedEntryCI->getArgOperand(1));
2507 }
2508 
2509 TEST_F(OpenMPIRBuilderTest, OrderedDirectiveSimd) {
2510   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2511   OpenMPIRBuilder OMPBuilder(*M);
2512   OMPBuilder.initialize();
2513   F->setName("func");
2514   IRBuilder<> Builder(BB);
2515 
2516   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2517 
2518   AllocaInst *PrivAI =
2519       Builder.CreateAlloca(F->arg_begin()->getType(), nullptr, "priv.inst");
2520 
2521   BasicBlock *EntryBB = nullptr;
2522 
2523   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2524                        BasicBlock &FiniBB) {
2525     EntryBB = FiniBB.getUniquePredecessor();
2526 
2527     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2528     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2529     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2530     EXPECT_EQ(EntryBB, CodeGenIPBB);
2531 
2532     Builder.restoreIP(CodeGenIP);
2533     Builder.CreateStore(F->arg_begin(), PrivAI);
2534     Value *PrivLoad =
2535         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2536     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2537   };
2538 
2539   auto FiniCB = [&](InsertPointTy IP) {
2540     BasicBlock *IPBB = IP.getBlock();
2541     EXPECT_NE(IPBB->end(), IP.getPoint());
2542   };
2543 
2544   // Test for "#omp ordered simd"
2545   Builder.restoreIP(
2546       OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, false));
2547 
2548   Builder.CreateRetVoid();
2549   OMPBuilder.finalize();
2550   EXPECT_FALSE(verifyModule(*M, &errs()));
2551 
2552   EXPECT_NE(EntryBB->getTerminator(), nullptr);
2553 
2554   CallInst *OrderedEntryCI = nullptr;
2555   for (auto &EI : *EntryBB) {
2556     Instruction *Cur = &EI;
2557     if (isa<CallInst>(Cur)) {
2558       OrderedEntryCI = cast<CallInst>(Cur);
2559       if (OrderedEntryCI->getCalledFunction()->getName() == "__kmpc_ordered")
2560         break;
2561       OrderedEntryCI = nullptr;
2562     }
2563   }
2564   EXPECT_EQ(OrderedEntryCI, nullptr);
2565 
2566   CallInst *OrderedEndCI = nullptr;
2567   for (auto &FI : *EntryBB) {
2568     Instruction *Cur = &FI;
2569     if (isa<CallInst>(Cur)) {
2570       OrderedEndCI = cast<CallInst>(Cur);
2571       if (OrderedEndCI->getCalledFunction()->getName() == "__kmpc_end_ordered")
2572         break;
2573       OrderedEndCI = nullptr;
2574     }
2575   }
2576   EXPECT_EQ(OrderedEndCI, nullptr);
2577 }
2578 
2579 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
2580   OpenMPIRBuilder OMPBuilder(*M);
2581   OMPBuilder.initialize();
2582   F->setName("func");
2583   IRBuilder<> Builder(BB);
2584 
2585   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2586 
2587   IntegerType *Int32 = Type::getInt32Ty(M->getContext());
2588   AllocaInst *MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
2589   AllocaInst *PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
2590 
2591   BasicBlock *EntryBB = BB;
2592 
2593   OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress,
2594                                       PrivAddress, Int32, /*BranchtoEnd*/ true);
2595 
2596   BranchInst *EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
2597 
2598   EXPECT_NE(EntryBr, nullptr);
2599   EXPECT_TRUE(EntryBr->isConditional());
2600 
2601   BasicBlock *NotMasterBB = EntryBr->getSuccessor(0);
2602   BasicBlock *CopyinEnd = EntryBr->getSuccessor(1);
2603   CmpInst *CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
2604 
2605   EXPECT_NE(CMP, nullptr);
2606   EXPECT_NE(NotMasterBB, nullptr);
2607   EXPECT_NE(CopyinEnd, nullptr);
2608 
2609   BranchInst *NotMasterBr =
2610       dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
2611   EXPECT_NE(NotMasterBr, nullptr);
2612   EXPECT_FALSE(NotMasterBr->isConditional());
2613   EXPECT_EQ(CopyinEnd, NotMasterBr->getSuccessor(0));
2614 }
2615 
2616 TEST_F(OpenMPIRBuilderTest, SingleDirective) {
2617   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2618   OpenMPIRBuilder OMPBuilder(*M);
2619   OMPBuilder.initialize();
2620   F->setName("func");
2621   IRBuilder<> Builder(BB);
2622 
2623   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2624 
2625   AllocaInst *PrivAI = nullptr;
2626 
2627   BasicBlock *EntryBB = nullptr;
2628   BasicBlock *ExitBB = nullptr;
2629   BasicBlock *ThenBB = nullptr;
2630 
2631   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2632                        BasicBlock &FiniBB) {
2633     if (AllocaIP.isSet())
2634       Builder.restoreIP(AllocaIP);
2635     else
2636       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
2637     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2638     Builder.CreateStore(F->arg_begin(), PrivAI);
2639 
2640     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2641     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2642     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2643 
2644     Builder.restoreIP(CodeGenIP);
2645 
2646     // collect some info for checks later
2647     ExitBB = FiniBB.getUniqueSuccessor();
2648     ThenBB = Builder.GetInsertBlock();
2649     EntryBB = ThenBB->getUniquePredecessor();
2650 
2651     // simple instructions for body
2652     Value *PrivLoad =
2653         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
2654     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2655   };
2656 
2657   auto FiniCB = [&](InsertPointTy IP) {
2658     BasicBlock *IPBB = IP.getBlock();
2659     EXPECT_NE(IPBB->end(), IP.getPoint());
2660   };
2661 
2662   Builder.restoreIP(
2663       OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
2664   Value *EntryBBTI = EntryBB->getTerminator();
2665   EXPECT_NE(EntryBBTI, nullptr);
2666   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2667   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2668   EXPECT_TRUE(EntryBr->isConditional());
2669   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2670   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2671   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2672 
2673   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2674   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2675 
2676   CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
2677   EXPECT_EQ(SingleEntryCI->arg_size(), 2U);
2678   EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
2679   EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
2680 
2681   CallInst *SingleEndCI = nullptr;
2682   for (auto &FI : *ThenBB) {
2683     Instruction *cur = &FI;
2684     if (isa<CallInst>(cur)) {
2685       SingleEndCI = cast<CallInst>(cur);
2686       if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
2687         break;
2688       SingleEndCI = nullptr;
2689     }
2690   }
2691   EXPECT_NE(SingleEndCI, nullptr);
2692   EXPECT_EQ(SingleEndCI->arg_size(), 2U);
2693   EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
2694   EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
2695 }
2696 
2697 TEST_F(OpenMPIRBuilderTest, OMPAtomicReadFlt) {
2698   OpenMPIRBuilder OMPBuilder(*M);
2699   OMPBuilder.initialize();
2700   F->setName("func");
2701   IRBuilder<> Builder(BB);
2702 
2703   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2704 
2705   Type *Float32 = Type::getFloatTy(M->getContext());
2706   AllocaInst *XVal = Builder.CreateAlloca(Float32);
2707   XVal->setName("AtomicVar");
2708   AllocaInst *VVal = Builder.CreateAlloca(Float32);
2709   VVal->setName("AtomicRead");
2710   AtomicOrdering AO = AtomicOrdering::Monotonic;
2711   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2712   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2713 
2714   Builder.restoreIP(OMPBuilder.createAtomicRead(Loc, X, V, AO));
2715 
2716   IntegerType *IntCastTy =
2717       IntegerType::get(M->getContext(), Float32->getScalarSizeInBits());
2718 
2719   BitCastInst *CastFrmFlt = cast<BitCastInst>(VVal->getNextNode());
2720   EXPECT_EQ(CastFrmFlt->getSrcTy(), Float32->getPointerTo());
2721   EXPECT_EQ(CastFrmFlt->getDestTy(), IntCastTy->getPointerTo());
2722   EXPECT_EQ(CastFrmFlt->getOperand(0), XVal);
2723 
2724   LoadInst *AtomicLoad = cast<LoadInst>(CastFrmFlt->getNextNode());
2725   EXPECT_TRUE(AtomicLoad->isAtomic());
2726   EXPECT_EQ(AtomicLoad->getPointerOperand(), CastFrmFlt);
2727 
2728   BitCastInst *CastToFlt = cast<BitCastInst>(AtomicLoad->getNextNode());
2729   EXPECT_EQ(CastToFlt->getSrcTy(), IntCastTy);
2730   EXPECT_EQ(CastToFlt->getDestTy(), Float32);
2731   EXPECT_EQ(CastToFlt->getOperand(0), AtomicLoad);
2732 
2733   StoreInst *StoreofAtomic = cast<StoreInst>(CastToFlt->getNextNode());
2734   EXPECT_EQ(StoreofAtomic->getValueOperand(), CastToFlt);
2735   EXPECT_EQ(StoreofAtomic->getPointerOperand(), VVal);
2736 
2737   Builder.CreateRetVoid();
2738   OMPBuilder.finalize();
2739   EXPECT_FALSE(verifyModule(*M, &errs()));
2740 }
2741 
2742 TEST_F(OpenMPIRBuilderTest, OMPAtomicReadInt) {
2743   OpenMPIRBuilder OMPBuilder(*M);
2744   OMPBuilder.initialize();
2745   F->setName("func");
2746   IRBuilder<> Builder(BB);
2747 
2748   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2749 
2750   IntegerType *Int32 = Type::getInt32Ty(M->getContext());
2751   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2752   XVal->setName("AtomicVar");
2753   AllocaInst *VVal = Builder.CreateAlloca(Int32);
2754   VVal->setName("AtomicRead");
2755   AtomicOrdering AO = AtomicOrdering::Monotonic;
2756   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2757   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2758 
2759   BasicBlock *EntryBB = BB;
2760 
2761   Builder.restoreIP(OMPBuilder.createAtomicRead(Loc, X, V, AO));
2762   LoadInst *AtomicLoad = nullptr;
2763   StoreInst *StoreofAtomic = nullptr;
2764 
2765   for (Instruction &Cur : *EntryBB) {
2766     if (isa<LoadInst>(Cur)) {
2767       AtomicLoad = cast<LoadInst>(&Cur);
2768       if (AtomicLoad->getPointerOperand() == XVal)
2769         continue;
2770       AtomicLoad = nullptr;
2771     } else if (isa<StoreInst>(Cur)) {
2772       StoreofAtomic = cast<StoreInst>(&Cur);
2773       if (StoreofAtomic->getPointerOperand() == VVal)
2774         continue;
2775       StoreofAtomic = nullptr;
2776     }
2777   }
2778 
2779   EXPECT_NE(AtomicLoad, nullptr);
2780   EXPECT_TRUE(AtomicLoad->isAtomic());
2781 
2782   EXPECT_NE(StoreofAtomic, nullptr);
2783   EXPECT_EQ(StoreofAtomic->getValueOperand(), AtomicLoad);
2784 
2785   Builder.CreateRetVoid();
2786   OMPBuilder.finalize();
2787 
2788   EXPECT_FALSE(verifyModule(*M, &errs()));
2789 }
2790 
2791 TEST_F(OpenMPIRBuilderTest, OMPAtomicWriteFlt) {
2792   OpenMPIRBuilder OMPBuilder(*M);
2793   OMPBuilder.initialize();
2794   F->setName("func");
2795   IRBuilder<> Builder(BB);
2796 
2797   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2798 
2799   LLVMContext &Ctx = M->getContext();
2800   Type *Float32 = Type::getFloatTy(Ctx);
2801   AllocaInst *XVal = Builder.CreateAlloca(Float32);
2802   XVal->setName("AtomicVar");
2803   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2804   AtomicOrdering AO = AtomicOrdering::Monotonic;
2805   Constant *ValToWrite = ConstantFP::get(Float32, 1.0);
2806 
2807   Builder.restoreIP(OMPBuilder.createAtomicWrite(Loc, X, ValToWrite, AO));
2808 
2809   IntegerType *IntCastTy =
2810       IntegerType::get(M->getContext(), Float32->getScalarSizeInBits());
2811 
2812   BitCastInst *CastFrmFlt = cast<BitCastInst>(XVal->getNextNode());
2813   EXPECT_EQ(CastFrmFlt->getSrcTy(), Float32->getPointerTo());
2814   EXPECT_EQ(CastFrmFlt->getDestTy(), IntCastTy->getPointerTo());
2815   EXPECT_EQ(CastFrmFlt->getOperand(0), XVal);
2816 
2817   Value *ExprCast = Builder.CreateBitCast(ValToWrite, IntCastTy);
2818 
2819   StoreInst *StoreofAtomic = cast<StoreInst>(CastFrmFlt->getNextNode());
2820   EXPECT_EQ(StoreofAtomic->getValueOperand(), ExprCast);
2821   EXPECT_EQ(StoreofAtomic->getPointerOperand(), CastFrmFlt);
2822   EXPECT_TRUE(StoreofAtomic->isAtomic());
2823 
2824   Builder.CreateRetVoid();
2825   OMPBuilder.finalize();
2826   EXPECT_FALSE(verifyModule(*M, &errs()));
2827 }
2828 
2829 TEST_F(OpenMPIRBuilderTest, OMPAtomicWriteInt) {
2830   OpenMPIRBuilder OMPBuilder(*M);
2831   OMPBuilder.initialize();
2832   F->setName("func");
2833   IRBuilder<> Builder(BB);
2834 
2835   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2836 
2837   LLVMContext &Ctx = M->getContext();
2838   IntegerType *Int32 = Type::getInt32Ty(Ctx);
2839   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2840   XVal->setName("AtomicVar");
2841   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2842   AtomicOrdering AO = AtomicOrdering::Monotonic;
2843   ConstantInt *ValToWrite = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2844 
2845   BasicBlock *EntryBB = BB;
2846 
2847   Builder.restoreIP(OMPBuilder.createAtomicWrite(Loc, X, ValToWrite, AO));
2848 
2849   StoreInst *StoreofAtomic = nullptr;
2850 
2851   for (Instruction &Cur : *EntryBB) {
2852     if (isa<StoreInst>(Cur)) {
2853       StoreofAtomic = cast<StoreInst>(&Cur);
2854       if (StoreofAtomic->getPointerOperand() == XVal)
2855         continue;
2856       StoreofAtomic = nullptr;
2857     }
2858   }
2859 
2860   EXPECT_NE(StoreofAtomic, nullptr);
2861   EXPECT_TRUE(StoreofAtomic->isAtomic());
2862   EXPECT_EQ(StoreofAtomic->getValueOperand(), ValToWrite);
2863 
2864   Builder.CreateRetVoid();
2865   OMPBuilder.finalize();
2866   EXPECT_FALSE(verifyModule(*M, &errs()));
2867 }
2868 
2869 TEST_F(OpenMPIRBuilderTest, OMPAtomicUpdate) {
2870   OpenMPIRBuilder OMPBuilder(*M);
2871   OMPBuilder.initialize();
2872   F->setName("func");
2873   IRBuilder<> Builder(BB);
2874 
2875   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2876 
2877   IntegerType *Int32 = Type::getInt32Ty(M->getContext());
2878   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2879   XVal->setName("AtomicVar");
2880   Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Ctx), 0U), XVal);
2881   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2882   AtomicOrdering AO = AtomicOrdering::Monotonic;
2883   ConstantInt *ConstVal = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2884   Value *Expr = nullptr;
2885   AtomicRMWInst::BinOp RMWOp = AtomicRMWInst::Sub;
2886   bool IsXLHSInRHSPart = false;
2887 
2888   BasicBlock *EntryBB = BB;
2889   Instruction *AllocIP = EntryBB->getFirstNonPHI();
2890   Value *Sub = nullptr;
2891 
2892   auto UpdateOp = [&](Value *Atomic, IRBuilder<> &IRB) {
2893     Sub = IRB.CreateSub(ConstVal, Atomic);
2894     return Sub;
2895   };
2896   Builder.restoreIP(OMPBuilder.createAtomicUpdate(
2897       Builder, AllocIP, X, Expr, AO, RMWOp, UpdateOp, IsXLHSInRHSPart));
2898   BasicBlock *ContBB = EntryBB->getSingleSuccessor();
2899   BranchInst *ContTI = dyn_cast<BranchInst>(ContBB->getTerminator());
2900   EXPECT_NE(ContTI, nullptr);
2901   BasicBlock *EndBB = ContTI->getSuccessor(0);
2902   EXPECT_TRUE(ContTI->isConditional());
2903   EXPECT_EQ(ContTI->getSuccessor(1), ContBB);
2904   EXPECT_NE(EndBB, nullptr);
2905 
2906   PHINode *Phi = dyn_cast<PHINode>(&ContBB->front());
2907   EXPECT_NE(Phi, nullptr);
2908   EXPECT_EQ(Phi->getNumIncomingValues(), 2U);
2909   EXPECT_EQ(Phi->getIncomingBlock(0), EntryBB);
2910   EXPECT_EQ(Phi->getIncomingBlock(1), ContBB);
2911 
2912   EXPECT_EQ(Sub->getNumUses(), 1U);
2913   StoreInst *St = dyn_cast<StoreInst>(Sub->user_back());
2914   AllocaInst *UpdateTemp = dyn_cast<AllocaInst>(St->getPointerOperand());
2915 
2916   ExtractValueInst *ExVI1 =
2917       dyn_cast<ExtractValueInst>(Phi->getIncomingValueForBlock(ContBB));
2918   EXPECT_NE(ExVI1, nullptr);
2919   AtomicCmpXchgInst *CmpExchg =
2920       dyn_cast<AtomicCmpXchgInst>(ExVI1->getAggregateOperand());
2921   EXPECT_NE(CmpExchg, nullptr);
2922   EXPECT_EQ(CmpExchg->getPointerOperand(), XVal);
2923   EXPECT_EQ(CmpExchg->getCompareOperand(), Phi);
2924   EXPECT_EQ(CmpExchg->getSuccessOrdering(), AtomicOrdering::Monotonic);
2925 
2926   LoadInst *Ld = dyn_cast<LoadInst>(CmpExchg->getNewValOperand());
2927   EXPECT_NE(Ld, nullptr);
2928   EXPECT_EQ(UpdateTemp, Ld->getPointerOperand());
2929 
2930   Builder.CreateRetVoid();
2931   OMPBuilder.finalize();
2932   EXPECT_FALSE(verifyModule(*M, &errs()));
2933 }
2934 
2935 TEST_F(OpenMPIRBuilderTest, OMPAtomicCapture) {
2936   OpenMPIRBuilder OMPBuilder(*M);
2937   OMPBuilder.initialize();
2938   F->setName("func");
2939   IRBuilder<> Builder(BB);
2940 
2941   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2942 
2943   LLVMContext &Ctx = M->getContext();
2944   IntegerType *Int32 = Type::getInt32Ty(Ctx);
2945   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2946   XVal->setName("AtomicVar");
2947   AllocaInst *VVal = Builder.CreateAlloca(Int32);
2948   VVal->setName("AtomicCapTar");
2949   StoreInst *Init =
2950       Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Ctx), 0U), XVal);
2951 
2952   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2953   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2954   AtomicOrdering AO = AtomicOrdering::Monotonic;
2955   ConstantInt *Expr = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2956   AtomicRMWInst::BinOp RMWOp = AtomicRMWInst::Add;
2957   bool IsXLHSInRHSPart = true;
2958   bool IsPostfixUpdate = true;
2959   bool UpdateExpr = true;
2960 
2961   BasicBlock *EntryBB = BB;
2962   Instruction *AllocIP = EntryBB->getFirstNonPHI();
2963 
2964   // integer update - not used
2965   auto UpdateOp = [&](Value *Atomic, IRBuilder<> &IRB) { return nullptr; };
2966 
2967   Builder.restoreIP(OMPBuilder.createAtomicCapture(
2968       Builder, AllocIP, X, V, Expr, AO, RMWOp, UpdateOp, UpdateExpr,
2969       IsPostfixUpdate, IsXLHSInRHSPart));
2970   EXPECT_EQ(EntryBB->getParent()->size(), 1U);
2971   AtomicRMWInst *ARWM = dyn_cast<AtomicRMWInst>(Init->getNextNode());
2972   EXPECT_NE(ARWM, nullptr);
2973   EXPECT_EQ(ARWM->getPointerOperand(), XVal);
2974   EXPECT_EQ(ARWM->getOperation(), RMWOp);
2975   StoreInst *St = dyn_cast<StoreInst>(ARWM->user_back());
2976   EXPECT_NE(St, nullptr);
2977   EXPECT_EQ(St->getPointerOperand(), VVal);
2978 
2979   Builder.CreateRetVoid();
2980   OMPBuilder.finalize();
2981   EXPECT_FALSE(verifyModule(*M, &errs()));
2982 }
2983 
2984 /// Returns the single instruction of InstTy type in BB that uses the value V.
2985 /// If there is more than one such instruction, returns null.
2986 template <typename InstTy>
2987 static InstTy *findSingleUserInBlock(Value *V, BasicBlock *BB) {
2988   InstTy *Result = nullptr;
2989   for (User *U : V->users()) {
2990     auto *Inst = dyn_cast<InstTy>(U);
2991     if (!Inst || Inst->getParent() != BB)
2992       continue;
2993     if (Result)
2994       return nullptr;
2995     Result = Inst;
2996   }
2997   return Result;
2998 }
2999 
3000 /// Returns true if BB contains a simple binary reduction that loads a value
3001 /// from Accum, performs some binary operation with it, and stores it back to
3002 /// Accum.
3003 static bool isSimpleBinaryReduction(Value *Accum, BasicBlock *BB,
3004                                     Instruction::BinaryOps *OpCode = nullptr) {
3005   StoreInst *Store = findSingleUserInBlock<StoreInst>(Accum, BB);
3006   if (!Store)
3007     return false;
3008   auto *Stored = dyn_cast<BinaryOperator>(Store->getOperand(0));
3009   if (!Stored)
3010     return false;
3011   if (OpCode && *OpCode != Stored->getOpcode())
3012     return false;
3013   auto *Load = dyn_cast<LoadInst>(Stored->getOperand(0));
3014   return Load && Load->getOperand(0) == Accum;
3015 }
3016 
3017 /// Returns true if BB contains a binary reduction that reduces V using a binary
3018 /// operator into an accumulator that is a function argument.
3019 static bool isValueReducedToFuncArg(Value *V, BasicBlock *BB) {
3020   auto *ReductionOp = findSingleUserInBlock<BinaryOperator>(V, BB);
3021   if (!ReductionOp)
3022     return false;
3023 
3024   auto *GlobalLoad = dyn_cast<LoadInst>(ReductionOp->getOperand(0));
3025   if (!GlobalLoad)
3026     return false;
3027 
3028   auto *Store = findSingleUserInBlock<StoreInst>(ReductionOp, BB);
3029   if (!Store)
3030     return false;
3031 
3032   return Store->getPointerOperand() == GlobalLoad->getPointerOperand() &&
3033          isa<Argument>(GlobalLoad->getPointerOperand());
3034 }
3035 
3036 /// Finds among users of Ptr a pair of GEP instructions with indices [0, 0] and
3037 /// [0, 1], respectively, and assigns results of these instructions to Zero and
3038 /// One. Returns true on success, false on failure or if such instructions are
3039 /// not unique among the users of Ptr.
3040 static bool findGEPZeroOne(Value *Ptr, Value *&Zero, Value *&One) {
3041   Zero = nullptr;
3042   One = nullptr;
3043   for (User *U : Ptr->users()) {
3044     if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
3045       if (GEP->getNumIndices() != 2)
3046         continue;
3047       auto *FirstIdx = dyn_cast<ConstantInt>(GEP->getOperand(1));
3048       auto *SecondIdx = dyn_cast<ConstantInt>(GEP->getOperand(2));
3049       EXPECT_NE(FirstIdx, nullptr);
3050       EXPECT_NE(SecondIdx, nullptr);
3051 
3052       EXPECT_TRUE(FirstIdx->isZero());
3053       if (SecondIdx->isZero()) {
3054         if (Zero)
3055           return false;
3056         Zero = GEP;
3057       } else if (SecondIdx->isOne()) {
3058         if (One)
3059           return false;
3060         One = GEP;
3061       } else {
3062         return false;
3063       }
3064     }
3065   }
3066   return Zero != nullptr && One != nullptr;
3067 }
3068 
3069 static OpenMPIRBuilder::InsertPointTy
3070 sumReduction(OpenMPIRBuilder::InsertPointTy IP, Value *LHS, Value *RHS,
3071              Value *&Result) {
3072   IRBuilder<> Builder(IP.getBlock(), IP.getPoint());
3073   Result = Builder.CreateFAdd(LHS, RHS, "red.add");
3074   return Builder.saveIP();
3075 }
3076 
3077 static OpenMPIRBuilder::InsertPointTy
3078 sumAtomicReduction(OpenMPIRBuilder::InsertPointTy IP, Type *Ty, Value *LHS,
3079                    Value *RHS) {
3080   IRBuilder<> Builder(IP.getBlock(), IP.getPoint());
3081   Value *Partial = Builder.CreateLoad(Ty, RHS, "red.partial");
3082   Builder.CreateAtomicRMW(AtomicRMWInst::FAdd, LHS, Partial, None,
3083                           AtomicOrdering::Monotonic);
3084   return Builder.saveIP();
3085 }
3086 
3087 static OpenMPIRBuilder::InsertPointTy
3088 xorReduction(OpenMPIRBuilder::InsertPointTy IP, Value *LHS, Value *RHS,
3089              Value *&Result) {
3090   IRBuilder<> Builder(IP.getBlock(), IP.getPoint());
3091   Result = Builder.CreateXor(LHS, RHS, "red.xor");
3092   return Builder.saveIP();
3093 }
3094 
3095 static OpenMPIRBuilder::InsertPointTy
3096 xorAtomicReduction(OpenMPIRBuilder::InsertPointTy IP, Type *Ty, Value *LHS,
3097                    Value *RHS) {
3098   IRBuilder<> Builder(IP.getBlock(), IP.getPoint());
3099   Value *Partial = Builder.CreateLoad(Ty, RHS, "red.partial");
3100   Builder.CreateAtomicRMW(AtomicRMWInst::Xor, LHS, Partial, None,
3101                           AtomicOrdering::Monotonic);
3102   return Builder.saveIP();
3103 }
3104 
3105 /// Populate Calls with call instructions calling the function with the given
3106 /// FnID from the given function F.
3107 static void findCalls(Function *F, omp::RuntimeFunction FnID,
3108                       OpenMPIRBuilder &OMPBuilder,
3109                       SmallVectorImpl<CallInst *> &Calls) {
3110   Function *Fn = OMPBuilder.getOrCreateRuntimeFunctionPtr(FnID);
3111   for (BasicBlock &BB : *F) {
3112     for (Instruction &I : BB) {
3113       auto *Call = dyn_cast<CallInst>(&I);
3114       if (Call && Call->getCalledFunction() == Fn)
3115         Calls.push_back(Call);
3116     }
3117   }
3118 }
3119 
3120 TEST_F(OpenMPIRBuilderTest, CreateReductions) {
3121   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3122   OpenMPIRBuilder OMPBuilder(*M);
3123   OMPBuilder.initialize();
3124   F->setName("func");
3125   IRBuilder<> Builder(BB);
3126 
3127   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
3128   Builder.CreateBr(EnterBB);
3129   Builder.SetInsertPoint(EnterBB);
3130   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3131 
3132   // Create variables to be reduced.
3133   InsertPointTy OuterAllocaIP(&F->getEntryBlock(),
3134                               F->getEntryBlock().getFirstInsertionPt());
3135   Type *SumType = Builder.getFloatTy();
3136   Type *XorType = Builder.getInt32Ty();
3137   Value *SumReduced;
3138   Value *XorReduced;
3139   {
3140     IRBuilderBase::InsertPointGuard Guard(Builder);
3141     Builder.restoreIP(OuterAllocaIP);
3142     SumReduced = Builder.CreateAlloca(SumType);
3143     XorReduced = Builder.CreateAlloca(XorType);
3144   }
3145 
3146   // Store initial values of reductions into global variables.
3147   Builder.CreateStore(ConstantFP::get(Builder.getFloatTy(), 0.0), SumReduced);
3148   Builder.CreateStore(Builder.getInt32(1), XorReduced);
3149 
3150   // The loop body computes two reductions:
3151   //   sum of (float) thread-id;
3152   //   xor of thread-id;
3153   // and store the result in global variables.
3154   InsertPointTy BodyIP, BodyAllocaIP;
3155   auto BodyGenCB = [&](InsertPointTy InnerAllocaIP, InsertPointTy CodeGenIP,
3156                        BasicBlock &ContinuationBB) {
3157     IRBuilderBase::InsertPointGuard Guard(Builder);
3158     Builder.restoreIP(CodeGenIP);
3159 
3160     uint32_t StrSize;
3161     Constant *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(Loc, StrSize);
3162     Value *Ident = OMPBuilder.getOrCreateIdent(SrcLocStr, StrSize);
3163     Value *TID = OMPBuilder.getOrCreateThreadID(Ident);
3164     Value *SumLocal =
3165         Builder.CreateUIToFP(TID, Builder.getFloatTy(), "sum.local");
3166     Value *SumPartial = Builder.CreateLoad(SumType, SumReduced, "sum.partial");
3167     Value *XorPartial = Builder.CreateLoad(XorType, XorReduced, "xor.partial");
3168     Value *Sum = Builder.CreateFAdd(SumPartial, SumLocal, "sum");
3169     Value *Xor = Builder.CreateXor(XorPartial, TID, "xor");
3170     Builder.CreateStore(Sum, SumReduced);
3171     Builder.CreateStore(Xor, XorReduced);
3172 
3173     BodyIP = Builder.saveIP();
3174     BodyAllocaIP = InnerAllocaIP;
3175   };
3176 
3177   // Privatization for reduction creates local copies of reduction variables and
3178   // initializes them to reduction-neutral values.
3179   Value *SumPrivatized;
3180   Value *XorPrivatized;
3181   auto PrivCB = [&](InsertPointTy InnerAllocaIP, InsertPointTy CodeGenIP,
3182                     Value &Original, Value &Inner, Value *&ReplVal) {
3183     IRBuilderBase::InsertPointGuard Guard(Builder);
3184     Builder.restoreIP(InnerAllocaIP);
3185     if (&Original == SumReduced) {
3186       SumPrivatized = Builder.CreateAlloca(Builder.getFloatTy());
3187       ReplVal = SumPrivatized;
3188     } else if (&Original == XorReduced) {
3189       XorPrivatized = Builder.CreateAlloca(Builder.getInt32Ty());
3190       ReplVal = XorPrivatized;
3191     } else {
3192       ReplVal = &Inner;
3193       return CodeGenIP;
3194     }
3195 
3196     Builder.restoreIP(CodeGenIP);
3197     if (&Original == SumReduced)
3198       Builder.CreateStore(ConstantFP::get(Builder.getFloatTy(), 0.0),
3199                           SumPrivatized);
3200     else if (&Original == XorReduced)
3201       Builder.CreateStore(Builder.getInt32(0), XorPrivatized);
3202 
3203     return Builder.saveIP();
3204   };
3205 
3206   // Do nothing in finalization.
3207   auto FiniCB = [&](InsertPointTy CodeGenIP) { return CodeGenIP; };
3208 
3209   InsertPointTy AfterIP =
3210       OMPBuilder.createParallel(Loc, OuterAllocaIP, BodyGenCB, PrivCB, FiniCB,
3211                                 /* IfCondition */ nullptr,
3212                                 /* NumThreads */ nullptr, OMP_PROC_BIND_default,
3213                                 /* IsCancellable */ false);
3214   Builder.restoreIP(AfterIP);
3215 
3216   OpenMPIRBuilder::ReductionInfo ReductionInfos[] = {
3217       {SumType, SumReduced, SumPrivatized, sumReduction, sumAtomicReduction},
3218       {XorType, XorReduced, XorPrivatized, xorReduction, xorAtomicReduction}};
3219 
3220   OMPBuilder.createReductions(BodyIP, BodyAllocaIP, ReductionInfos);
3221 
3222   Builder.restoreIP(AfterIP);
3223   Builder.CreateRetVoid();
3224 
3225   OMPBuilder.finalize(F);
3226 
3227   // The IR must be valid.
3228   EXPECT_FALSE(verifyModule(*M));
3229 
3230   // Outlining must have happened.
3231   SmallVector<CallInst *> ForkCalls;
3232   findCalls(F, omp::RuntimeFunction::OMPRTL___kmpc_fork_call, OMPBuilder,
3233             ForkCalls);
3234   ASSERT_EQ(ForkCalls.size(), 1u);
3235   Value *CalleeVal = cast<Constant>(ForkCalls[0]->getOperand(2))->getOperand(0);
3236   Function *Outlined = dyn_cast<Function>(CalleeVal);
3237   EXPECT_NE(Outlined, nullptr);
3238 
3239   // Check that the lock variable was created with the expected name.
3240   GlobalVariable *LockVar =
3241       M->getGlobalVariable(".gomp_critical_user_.reduction.var");
3242   EXPECT_NE(LockVar, nullptr);
3243 
3244   // Find the allocation of a local array that will be used to call the runtime
3245   // reduciton function.
3246   BasicBlock &AllocBlock = Outlined->getEntryBlock();
3247   Value *LocalArray = nullptr;
3248   for (Instruction &I : AllocBlock) {
3249     if (AllocaInst *Alloc = dyn_cast<AllocaInst>(&I)) {
3250       if (!Alloc->getAllocatedType()->isArrayTy() ||
3251           !Alloc->getAllocatedType()->getArrayElementType()->isPointerTy())
3252         continue;
3253       LocalArray = Alloc;
3254       break;
3255     }
3256   }
3257   ASSERT_NE(LocalArray, nullptr);
3258 
3259   // Find the call to the runtime reduction function.
3260   BasicBlock *BB = AllocBlock.getUniqueSuccessor();
3261   Value *LocalArrayPtr = nullptr;
3262   Value *ReductionFnVal = nullptr;
3263   Value *SwitchArg = nullptr;
3264   for (Instruction &I : *BB) {
3265     if (CallInst *Call = dyn_cast<CallInst>(&I)) {
3266       if (Call->getCalledFunction() !=
3267           OMPBuilder.getOrCreateRuntimeFunctionPtr(
3268               RuntimeFunction::OMPRTL___kmpc_reduce))
3269         continue;
3270       LocalArrayPtr = Call->getOperand(4);
3271       ReductionFnVal = Call->getOperand(5);
3272       SwitchArg = Call;
3273       break;
3274     }
3275   }
3276 
3277   // Check that the local array is passed to the function.
3278   ASSERT_NE(LocalArrayPtr, nullptr);
3279   BitCastInst *BitCast = dyn_cast<BitCastInst>(LocalArrayPtr);
3280   ASSERT_NE(BitCast, nullptr);
3281   EXPECT_EQ(BitCast->getOperand(0), LocalArray);
3282 
3283   // Find the GEP instructions preceding stores to the local array.
3284   Value *FirstArrayElemPtr = nullptr;
3285   Value *SecondArrayElemPtr = nullptr;
3286   EXPECT_EQ(LocalArray->getNumUses(), 3u);
3287   ASSERT_TRUE(
3288       findGEPZeroOne(LocalArray, FirstArrayElemPtr, SecondArrayElemPtr));
3289 
3290   // Check that the values stored into the local array are privatized reduction
3291   // variables.
3292   auto *FirstStored = dyn_cast_or_null<BitCastInst>(
3293       findStoredValue<GetElementPtrInst>(FirstArrayElemPtr));
3294   auto *SecondStored = dyn_cast_or_null<BitCastInst>(
3295       findStoredValue<GetElementPtrInst>(SecondArrayElemPtr));
3296   ASSERT_NE(FirstStored, nullptr);
3297   ASSERT_NE(SecondStored, nullptr);
3298   Value *FirstPrivatized = FirstStored->getOperand(0);
3299   Value *SecondPrivatized = SecondStored->getOperand(0);
3300   EXPECT_TRUE(
3301       isSimpleBinaryReduction(FirstPrivatized, FirstStored->getParent()));
3302   EXPECT_TRUE(
3303       isSimpleBinaryReduction(SecondPrivatized, SecondStored->getParent()));
3304 
3305   // Check that the result of the runtime reduction call is used for further
3306   // dispatch.
3307   ASSERT_EQ(SwitchArg->getNumUses(), 1u);
3308   SwitchInst *Switch = dyn_cast<SwitchInst>(*SwitchArg->user_begin());
3309   ASSERT_NE(Switch, nullptr);
3310   EXPECT_EQ(Switch->getNumSuccessors(), 3u);
3311   BasicBlock *NonAtomicBB = Switch->case_begin()->getCaseSuccessor();
3312   BasicBlock *AtomicBB = std::next(Switch->case_begin())->getCaseSuccessor();
3313 
3314   // Non-atomic block contains reductions to the global reduction variable,
3315   // which is passed into the outlined function as an argument.
3316   Value *FirstLoad =
3317       findSingleUserInBlock<LoadInst>(FirstPrivatized, NonAtomicBB);
3318   Value *SecondLoad =
3319       findSingleUserInBlock<LoadInst>(SecondPrivatized, NonAtomicBB);
3320   EXPECT_TRUE(isValueReducedToFuncArg(FirstLoad, NonAtomicBB));
3321   EXPECT_TRUE(isValueReducedToFuncArg(SecondLoad, NonAtomicBB));
3322 
3323   // Atomic block also constains reductions to the global reduction variable.
3324   FirstLoad = findSingleUserInBlock<LoadInst>(FirstPrivatized, AtomicBB);
3325   SecondLoad = findSingleUserInBlock<LoadInst>(SecondPrivatized, AtomicBB);
3326   auto *FirstAtomic = findSingleUserInBlock<AtomicRMWInst>(FirstLoad, AtomicBB);
3327   auto *SecondAtomic =
3328       findSingleUserInBlock<AtomicRMWInst>(SecondLoad, AtomicBB);
3329   ASSERT_NE(FirstAtomic, nullptr);
3330   EXPECT_TRUE(isa<Argument>(FirstAtomic->getPointerOperand()));
3331   ASSERT_NE(SecondAtomic, nullptr);
3332   EXPECT_TRUE(isa<Argument>(SecondAtomic->getPointerOperand()));
3333 
3334   // Check that the separate reduction function also performs (non-atomic)
3335   // reductions after extracting reduction variables from its arguments.
3336   Function *ReductionFn = cast<Function>(ReductionFnVal);
3337   BasicBlock *FnReductionBB = &ReductionFn->getEntryBlock();
3338   auto *Bitcast =
3339       findSingleUserInBlock<BitCastInst>(ReductionFn->getArg(0), FnReductionBB);
3340   Value *FirstLHSPtr;
3341   Value *SecondLHSPtr;
3342   ASSERT_TRUE(findGEPZeroOne(Bitcast, FirstLHSPtr, SecondLHSPtr));
3343   Value *Opaque = findSingleUserInBlock<LoadInst>(FirstLHSPtr, FnReductionBB);
3344   ASSERT_NE(Opaque, nullptr);
3345   Bitcast = findSingleUserInBlock<BitCastInst>(Opaque, FnReductionBB);
3346   ASSERT_NE(Bitcast, nullptr);
3347   EXPECT_TRUE(isSimpleBinaryReduction(Bitcast, FnReductionBB));
3348   Opaque = findSingleUserInBlock<LoadInst>(SecondLHSPtr, FnReductionBB);
3349   ASSERT_NE(Opaque, nullptr);
3350   Bitcast = findSingleUserInBlock<BitCastInst>(Opaque, FnReductionBB);
3351   ASSERT_NE(Bitcast, nullptr);
3352   EXPECT_TRUE(isSimpleBinaryReduction(Bitcast, FnReductionBB));
3353 
3354   Bitcast =
3355       findSingleUserInBlock<BitCastInst>(ReductionFn->getArg(1), FnReductionBB);
3356   Value *FirstRHS;
3357   Value *SecondRHS;
3358   EXPECT_TRUE(findGEPZeroOne(Bitcast, FirstRHS, SecondRHS));
3359 }
3360 
3361 TEST_F(OpenMPIRBuilderTest, CreateTwoReductions) {
3362   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3363   OpenMPIRBuilder OMPBuilder(*M);
3364   OMPBuilder.initialize();
3365   F->setName("func");
3366   IRBuilder<> Builder(BB);
3367 
3368   BasicBlock *EnterBB = BasicBlock::Create(Ctx, "parallel.enter", F);
3369   Builder.CreateBr(EnterBB);
3370   Builder.SetInsertPoint(EnterBB);
3371   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3372 
3373   // Create variables to be reduced.
3374   InsertPointTy OuterAllocaIP(&F->getEntryBlock(),
3375                               F->getEntryBlock().getFirstInsertionPt());
3376   Type *SumType = Builder.getFloatTy();
3377   Type *XorType = Builder.getInt32Ty();
3378   Value *SumReduced;
3379   Value *XorReduced;
3380   {
3381     IRBuilderBase::InsertPointGuard Guard(Builder);
3382     Builder.restoreIP(OuterAllocaIP);
3383     SumReduced = Builder.CreateAlloca(SumType);
3384     XorReduced = Builder.CreateAlloca(XorType);
3385   }
3386 
3387   // Store initial values of reductions into global variables.
3388   Builder.CreateStore(ConstantFP::get(Builder.getFloatTy(), 0.0), SumReduced);
3389   Builder.CreateStore(Builder.getInt32(1), XorReduced);
3390 
3391   InsertPointTy FirstBodyIP, FirstBodyAllocaIP;
3392   auto FirstBodyGenCB = [&](InsertPointTy InnerAllocaIP,
3393                             InsertPointTy CodeGenIP,
3394                             BasicBlock &ContinuationBB) {
3395     IRBuilderBase::InsertPointGuard Guard(Builder);
3396     Builder.restoreIP(CodeGenIP);
3397 
3398     uint32_t StrSize;
3399     Constant *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(Loc, StrSize);
3400     Value *Ident = OMPBuilder.getOrCreateIdent(SrcLocStr, StrSize);
3401     Value *TID = OMPBuilder.getOrCreateThreadID(Ident);
3402     Value *SumLocal =
3403         Builder.CreateUIToFP(TID, Builder.getFloatTy(), "sum.local");
3404     Value *SumPartial = Builder.CreateLoad(SumType, SumReduced, "sum.partial");
3405     Value *Sum = Builder.CreateFAdd(SumPartial, SumLocal, "sum");
3406     Builder.CreateStore(Sum, SumReduced);
3407 
3408     FirstBodyIP = Builder.saveIP();
3409     FirstBodyAllocaIP = InnerAllocaIP;
3410   };
3411 
3412   InsertPointTy SecondBodyIP, SecondBodyAllocaIP;
3413   auto SecondBodyGenCB = [&](InsertPointTy InnerAllocaIP,
3414                              InsertPointTy CodeGenIP,
3415                              BasicBlock &ContinuationBB) {
3416     IRBuilderBase::InsertPointGuard Guard(Builder);
3417     Builder.restoreIP(CodeGenIP);
3418 
3419     uint32_t StrSize;
3420     Constant *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(Loc, StrSize);
3421     Value *Ident = OMPBuilder.getOrCreateIdent(SrcLocStr, StrSize);
3422     Value *TID = OMPBuilder.getOrCreateThreadID(Ident);
3423     Value *XorPartial = Builder.CreateLoad(XorType, XorReduced, "xor.partial");
3424     Value *Xor = Builder.CreateXor(XorPartial, TID, "xor");
3425     Builder.CreateStore(Xor, XorReduced);
3426 
3427     SecondBodyIP = Builder.saveIP();
3428     SecondBodyAllocaIP = InnerAllocaIP;
3429   };
3430 
3431   // Privatization for reduction creates local copies of reduction variables and
3432   // initializes them to reduction-neutral values. The same privatization
3433   // callback is used for both loops, with dispatch based on the value being
3434   // privatized.
3435   Value *SumPrivatized;
3436   Value *XorPrivatized;
3437   auto PrivCB = [&](InsertPointTy InnerAllocaIP, InsertPointTy CodeGenIP,
3438                     Value &Original, Value &Inner, Value *&ReplVal) {
3439     IRBuilderBase::InsertPointGuard Guard(Builder);
3440     Builder.restoreIP(InnerAllocaIP);
3441     if (&Original == SumReduced) {
3442       SumPrivatized = Builder.CreateAlloca(Builder.getFloatTy());
3443       ReplVal = SumPrivatized;
3444     } else if (&Original == XorReduced) {
3445       XorPrivatized = Builder.CreateAlloca(Builder.getInt32Ty());
3446       ReplVal = XorPrivatized;
3447     } else {
3448       ReplVal = &Inner;
3449       return CodeGenIP;
3450     }
3451 
3452     Builder.restoreIP(CodeGenIP);
3453     if (&Original == SumReduced)
3454       Builder.CreateStore(ConstantFP::get(Builder.getFloatTy(), 0.0),
3455                           SumPrivatized);
3456     else if (&Original == XorReduced)
3457       Builder.CreateStore(Builder.getInt32(0), XorPrivatized);
3458 
3459     return Builder.saveIP();
3460   };
3461 
3462   // Do nothing in finalization.
3463   auto FiniCB = [&](InsertPointTy CodeGenIP) { return CodeGenIP; };
3464 
3465   Builder.restoreIP(
3466       OMPBuilder.createParallel(Loc, OuterAllocaIP, FirstBodyGenCB, PrivCB,
3467                                 FiniCB, /* IfCondition */ nullptr,
3468                                 /* NumThreads */ nullptr, OMP_PROC_BIND_default,
3469                                 /* IsCancellable */ false));
3470   InsertPointTy AfterIP = OMPBuilder.createParallel(
3471       {Builder.saveIP(), DL}, OuterAllocaIP, SecondBodyGenCB, PrivCB, FiniCB,
3472       /* IfCondition */ nullptr,
3473       /* NumThreads */ nullptr, OMP_PROC_BIND_default,
3474       /* IsCancellable */ false);
3475 
3476   OMPBuilder.createReductions(
3477       FirstBodyIP, FirstBodyAllocaIP,
3478       {{SumType, SumReduced, SumPrivatized, sumReduction, sumAtomicReduction}});
3479   OMPBuilder.createReductions(
3480       SecondBodyIP, SecondBodyAllocaIP,
3481       {{XorType, XorReduced, XorPrivatized, xorReduction, xorAtomicReduction}});
3482 
3483   Builder.restoreIP(AfterIP);
3484   Builder.CreateRetVoid();
3485 
3486   OMPBuilder.finalize(F);
3487 
3488   // The IR must be valid.
3489   EXPECT_FALSE(verifyModule(*M));
3490 
3491   // Two different outlined functions must have been created.
3492   SmallVector<CallInst *> ForkCalls;
3493   findCalls(F, omp::RuntimeFunction::OMPRTL___kmpc_fork_call, OMPBuilder,
3494             ForkCalls);
3495   ASSERT_EQ(ForkCalls.size(), 2u);
3496   Value *CalleeVal = cast<Constant>(ForkCalls[0]->getOperand(2))->getOperand(0);
3497   Function *FirstCallee = cast<Function>(CalleeVal);
3498   CalleeVal = cast<Constant>(ForkCalls[1]->getOperand(2))->getOperand(0);
3499   Function *SecondCallee = cast<Function>(CalleeVal);
3500   EXPECT_NE(FirstCallee, SecondCallee);
3501 
3502   // Two different reduction functions must have been created.
3503   SmallVector<CallInst *> ReduceCalls;
3504   findCalls(FirstCallee, omp::RuntimeFunction::OMPRTL___kmpc_reduce, OMPBuilder,
3505             ReduceCalls);
3506   ASSERT_EQ(ReduceCalls.size(), 1u);
3507   auto *AddReduction = cast<Function>(ReduceCalls[0]->getOperand(5));
3508   ReduceCalls.clear();
3509   findCalls(SecondCallee, omp::RuntimeFunction::OMPRTL___kmpc_reduce,
3510             OMPBuilder, ReduceCalls);
3511   auto *XorReduction = cast<Function>(ReduceCalls[0]->getOperand(5));
3512   EXPECT_NE(AddReduction, XorReduction);
3513 
3514   // Each reduction function does its own kind of reduction.
3515   BasicBlock *FnReductionBB = &AddReduction->getEntryBlock();
3516   auto *Bitcast = findSingleUserInBlock<BitCastInst>(AddReduction->getArg(0),
3517                                                      FnReductionBB);
3518   ASSERT_NE(Bitcast, nullptr);
3519   Value *FirstLHSPtr =
3520       findSingleUserInBlock<GetElementPtrInst>(Bitcast, FnReductionBB);
3521   ASSERT_NE(FirstLHSPtr, nullptr);
3522   Value *Opaque = findSingleUserInBlock<LoadInst>(FirstLHSPtr, FnReductionBB);
3523   ASSERT_NE(Opaque, nullptr);
3524   Bitcast = findSingleUserInBlock<BitCastInst>(Opaque, FnReductionBB);
3525   ASSERT_NE(Bitcast, nullptr);
3526   Instruction::BinaryOps Opcode = Instruction::FAdd;
3527   EXPECT_TRUE(isSimpleBinaryReduction(Bitcast, FnReductionBB, &Opcode));
3528 
3529   FnReductionBB = &XorReduction->getEntryBlock();
3530   Bitcast = findSingleUserInBlock<BitCastInst>(XorReduction->getArg(0),
3531                                                FnReductionBB);
3532   ASSERT_NE(Bitcast, nullptr);
3533   Value *SecondLHSPtr =
3534       findSingleUserInBlock<GetElementPtrInst>(Bitcast, FnReductionBB);
3535   ASSERT_NE(FirstLHSPtr, nullptr);
3536   Opaque = findSingleUserInBlock<LoadInst>(SecondLHSPtr, FnReductionBB);
3537   ASSERT_NE(Opaque, nullptr);
3538   Bitcast = findSingleUserInBlock<BitCastInst>(Opaque, FnReductionBB);
3539   ASSERT_NE(Bitcast, nullptr);
3540   Opcode = Instruction::Xor;
3541   EXPECT_TRUE(isSimpleBinaryReduction(Bitcast, FnReductionBB, &Opcode));
3542 }
3543 
3544 TEST_F(OpenMPIRBuilderTest, CreateSectionsSimple) {
3545   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3546   using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
3547   OpenMPIRBuilder OMPBuilder(*M);
3548   OMPBuilder.initialize();
3549   F->setName("func");
3550   IRBuilder<> Builder(BB);
3551   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3552   llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
3553   llvm::SmallVector<BasicBlock *, 4> CaseBBs;
3554 
3555   auto FiniCB = [&](InsertPointTy IP) {};
3556   auto SectionCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
3557                        BasicBlock &FiniBB) {
3558     Builder.restoreIP(CodeGenIP);
3559     Builder.CreateBr(&FiniBB);
3560   };
3561   SectionCBVector.push_back(SectionCB);
3562 
3563   auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
3564                    llvm::Value &, llvm::Value &Val,
3565                    llvm::Value *&ReplVal) { return CodeGenIP; };
3566   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
3567                                     F->getEntryBlock().getFirstInsertionPt());
3568   Builder.restoreIP(OMPBuilder.createSections(Loc, AllocaIP, SectionCBVector,
3569                                               PrivCB, FiniCB, false, false));
3570   Builder.CreateRetVoid(); // Required at the end of the function
3571   EXPECT_NE(F->getEntryBlock().getTerminator(), nullptr);
3572   EXPECT_FALSE(verifyModule(*M, &errs()));
3573 }
3574 
3575 TEST_F(OpenMPIRBuilderTest, CreateSections) {
3576   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3577   using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
3578   OpenMPIRBuilder OMPBuilder(*M);
3579   OMPBuilder.initialize();
3580   F->setName("func");
3581   IRBuilder<> Builder(BB);
3582 
3583   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3584   llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
3585   llvm::SmallVector<BasicBlock *, 4> CaseBBs;
3586 
3587   BasicBlock *SwitchBB = nullptr;
3588   BasicBlock *ForExitBB = nullptr;
3589   BasicBlock *ForIncBB = nullptr;
3590   AllocaInst *PrivAI = nullptr;
3591   SwitchInst *Switch = nullptr;
3592 
3593   unsigned NumBodiesGenerated = 0;
3594   unsigned NumFiniCBCalls = 0;
3595   PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
3596 
3597   auto FiniCB = [&](InsertPointTy IP) {
3598     ++NumFiniCBCalls;
3599     BasicBlock *IPBB = IP.getBlock();
3600     EXPECT_NE(IPBB->end(), IP.getPoint());
3601   };
3602 
3603   auto SectionCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
3604                        BasicBlock &FiniBB) {
3605     ++NumBodiesGenerated;
3606     CaseBBs.push_back(CodeGenIP.getBlock());
3607     SwitchBB = CodeGenIP.getBlock()->getSinglePredecessor();
3608     Builder.restoreIP(CodeGenIP);
3609     Builder.CreateStore(F->arg_begin(), PrivAI);
3610     Value *PrivLoad =
3611         Builder.CreateLoad(F->arg_begin()->getType(), PrivAI, "local.alloca");
3612     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
3613     Builder.CreateBr(&FiniBB);
3614     ForIncBB =
3615         CodeGenIP.getBlock()->getSinglePredecessor()->getSingleSuccessor();
3616   };
3617   auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
3618                    llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
3619     // TODO: Privatization not implemented yet
3620     return CodeGenIP;
3621   };
3622 
3623   SectionCBVector.push_back(SectionCB);
3624   SectionCBVector.push_back(SectionCB);
3625 
3626   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
3627                                     F->getEntryBlock().getFirstInsertionPt());
3628   Builder.restoreIP(OMPBuilder.createSections(Loc, AllocaIP, SectionCBVector,
3629                                               PrivCB, FiniCB, false, false));
3630   Builder.CreateRetVoid(); // Required at the end of the function
3631 
3632   // Switch BB's predecessor is loop condition BB, whose successor at index 1 is
3633   // loop's exit BB
3634   ForExitBB =
3635       SwitchBB->getSinglePredecessor()->getTerminator()->getSuccessor(1);
3636   EXPECT_NE(ForExitBB, nullptr);
3637 
3638   EXPECT_NE(PrivAI, nullptr);
3639   Function *OutlinedFn = PrivAI->getFunction();
3640   EXPECT_EQ(F, OutlinedFn);
3641   EXPECT_FALSE(verifyModule(*M, &errs()));
3642   EXPECT_EQ(OutlinedFn->arg_size(), 1U);
3643   EXPECT_EQ(OutlinedFn->getBasicBlockList().size(), size_t(11));
3644 
3645   BasicBlock *LoopPreheaderBB =
3646       OutlinedFn->getEntryBlock().getSingleSuccessor();
3647   // loop variables are 5 - lower bound, upper bound, stride, islastiter, and
3648   // iterator/counter
3649   bool FoundForInit = false;
3650   for (Instruction &Inst : *LoopPreheaderBB) {
3651     if (isa<CallInst>(Inst)) {
3652       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
3653           "__kmpc_for_static_init_4u") {
3654         FoundForInit = true;
3655       }
3656     }
3657   }
3658   EXPECT_EQ(FoundForInit, true);
3659 
3660   bool FoundForExit = false;
3661   bool FoundBarrier = false;
3662   for (Instruction &Inst : *ForExitBB) {
3663     if (isa<CallInst>(Inst)) {
3664       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
3665           "__kmpc_for_static_fini") {
3666         FoundForExit = true;
3667       }
3668       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
3669           "__kmpc_barrier") {
3670         FoundBarrier = true;
3671       }
3672       if (FoundForExit && FoundBarrier)
3673         break;
3674     }
3675   }
3676   EXPECT_EQ(FoundForExit, true);
3677   EXPECT_EQ(FoundBarrier, true);
3678 
3679   EXPECT_NE(SwitchBB, nullptr);
3680   EXPECT_NE(SwitchBB->getTerminator(), nullptr);
3681   EXPECT_EQ(isa<SwitchInst>(SwitchBB->getTerminator()), true);
3682   Switch = cast<SwitchInst>(SwitchBB->getTerminator());
3683   EXPECT_EQ(Switch->getNumCases(), 2U);
3684   EXPECT_NE(ForIncBB, nullptr);
3685   EXPECT_EQ(Switch->getSuccessor(0), ForIncBB);
3686 
3687   EXPECT_EQ(CaseBBs.size(), 2U);
3688   for (auto *&CaseBB : CaseBBs) {
3689     EXPECT_EQ(CaseBB->getParent(), OutlinedFn);
3690     EXPECT_EQ(CaseBB->getSingleSuccessor(), ForExitBB);
3691   }
3692 
3693   ASSERT_EQ(NumBodiesGenerated, 2U);
3694   ASSERT_EQ(NumFiniCBCalls, 1U);
3695   EXPECT_FALSE(verifyModule(*M, &errs()));
3696 }
3697 
3698 TEST_F(OpenMPIRBuilderTest, CreateSectionsNoWait) {
3699   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3700   using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
3701   OpenMPIRBuilder OMPBuilder(*M);
3702   OMPBuilder.initialize();
3703   F->setName("func");
3704   IRBuilder<> Builder(BB);
3705 
3706   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3707   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
3708                                     F->getEntryBlock().getFirstInsertionPt());
3709   llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
3710   auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
3711                    llvm::Value &, llvm::Value &Val,
3712                    llvm::Value *&ReplVal) { return CodeGenIP; };
3713   auto FiniCB = [&](InsertPointTy IP) {};
3714 
3715   Builder.restoreIP(OMPBuilder.createSections(Loc, AllocaIP, SectionCBVector,
3716                                               PrivCB, FiniCB, false, true));
3717   Builder.CreateRetVoid(); // Required at the end of the function
3718   for (auto &Inst : instructions(*F)) {
3719     EXPECT_FALSE(isa<CallInst>(Inst) &&
3720                  cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
3721                      "__kmpc_barrier" &&
3722                  "call to function __kmpc_barrier found with nowait");
3723   }
3724 }
3725 
3726 TEST_F(OpenMPIRBuilderTest, CreateOffloadMaptypes) {
3727   OpenMPIRBuilder OMPBuilder(*M);
3728   OMPBuilder.initialize();
3729 
3730   IRBuilder<> Builder(BB);
3731 
3732   SmallVector<uint64_t> Mappings = {0, 1};
3733   GlobalVariable *OffloadMaptypesGlobal =
3734       OMPBuilder.createOffloadMaptypes(Mappings, "offload_maptypes");
3735   EXPECT_FALSE(M->global_empty());
3736   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_maptypes");
3737   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
3738   EXPECT_TRUE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
3739   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
3740   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
3741   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
3742   EXPECT_TRUE(isa<ConstantDataArray>(Initializer));
3743   ConstantDataArray *MappingInit = dyn_cast<ConstantDataArray>(Initializer);
3744   EXPECT_EQ(MappingInit->getNumElements(), Mappings.size());
3745   EXPECT_TRUE(MappingInit->getType()->getElementType()->isIntegerTy(64));
3746   Constant *CA = ConstantDataArray::get(Builder.getContext(), Mappings);
3747   EXPECT_EQ(MappingInit, CA);
3748 }
3749 
3750 TEST_F(OpenMPIRBuilderTest, CreateOffloadMapnames) {
3751   OpenMPIRBuilder OMPBuilder(*M);
3752   OMPBuilder.initialize();
3753 
3754   IRBuilder<> Builder(BB);
3755 
3756   uint32_t StrSize;
3757   Constant *Cst1 =
3758       OMPBuilder.getOrCreateSrcLocStr("array1", "file1", 2, 5, StrSize);
3759   Constant *Cst2 =
3760       OMPBuilder.getOrCreateSrcLocStr("array2", "file1", 3, 5, StrSize);
3761   SmallVector<llvm::Constant *> Names = {Cst1, Cst2};
3762 
3763   GlobalVariable *OffloadMaptypesGlobal =
3764       OMPBuilder.createOffloadMapnames(Names, "offload_mapnames");
3765   EXPECT_FALSE(M->global_empty());
3766   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_mapnames");
3767   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
3768   EXPECT_FALSE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
3769   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
3770   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
3771   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
3772   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(0)->stripPointerCasts()));
3773   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(1)->stripPointerCasts()));
3774 
3775   GlobalVariable *Name1Gbl =
3776       cast<GlobalVariable>(Initializer->getOperand(0)->stripPointerCasts());
3777   EXPECT_TRUE(isa<ConstantDataArray>(Name1Gbl->getInitializer()));
3778   ConstantDataArray *Name1GblCA =
3779       dyn_cast<ConstantDataArray>(Name1Gbl->getInitializer());
3780   EXPECT_EQ(Name1GblCA->getAsCString(), ";file1;array1;2;5;;");
3781 
3782   GlobalVariable *Name2Gbl =
3783       cast<GlobalVariable>(Initializer->getOperand(1)->stripPointerCasts());
3784   EXPECT_TRUE(isa<ConstantDataArray>(Name2Gbl->getInitializer()));
3785   ConstantDataArray *Name2GblCA =
3786       dyn_cast<ConstantDataArray>(Name2Gbl->getInitializer());
3787   EXPECT_EQ(Name2GblCA->getAsCString(), ";file1;array2;3;5;;");
3788 
3789   EXPECT_TRUE(Initializer->getType()->getArrayElementType()->isPointerTy());
3790   EXPECT_EQ(Initializer->getType()->getArrayNumElements(), Names.size());
3791 }
3792 
3793 TEST_F(OpenMPIRBuilderTest, CreateMapperAllocas) {
3794   OpenMPIRBuilder OMPBuilder(*M);
3795   OMPBuilder.initialize();
3796   F->setName("func");
3797   IRBuilder<> Builder(BB);
3798 
3799   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3800 
3801   unsigned TotalNbOperand = 2;
3802 
3803   OpenMPIRBuilder::MapperAllocas MapperAllocas;
3804   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
3805                                     F->getEntryBlock().getFirstInsertionPt());
3806   OMPBuilder.createMapperAllocas(Loc, AllocaIP, TotalNbOperand, MapperAllocas);
3807   EXPECT_NE(MapperAllocas.ArgsBase, nullptr);
3808   EXPECT_NE(MapperAllocas.Args, nullptr);
3809   EXPECT_NE(MapperAllocas.ArgSizes, nullptr);
3810   EXPECT_TRUE(MapperAllocas.ArgsBase->getAllocatedType()->isArrayTy());
3811   ArrayType *ArrType =
3812       dyn_cast<ArrayType>(MapperAllocas.ArgsBase->getAllocatedType());
3813   EXPECT_EQ(ArrType->getNumElements(), TotalNbOperand);
3814   EXPECT_TRUE(MapperAllocas.ArgsBase->getAllocatedType()
3815                   ->getArrayElementType()
3816                   ->isPointerTy());
3817   EXPECT_TRUE(MapperAllocas.ArgsBase->getAllocatedType()
3818                   ->getArrayElementType()
3819                   ->getPointerElementType()
3820                   ->isIntegerTy(8));
3821 
3822   EXPECT_TRUE(MapperAllocas.Args->getAllocatedType()->isArrayTy());
3823   ArrType = dyn_cast<ArrayType>(MapperAllocas.Args->getAllocatedType());
3824   EXPECT_EQ(ArrType->getNumElements(), TotalNbOperand);
3825   EXPECT_TRUE(MapperAllocas.Args->getAllocatedType()
3826                   ->getArrayElementType()
3827                   ->isPointerTy());
3828   EXPECT_TRUE(MapperAllocas.Args->getAllocatedType()
3829                   ->getArrayElementType()
3830                   ->getPointerElementType()
3831                   ->isIntegerTy(8));
3832 
3833   EXPECT_TRUE(MapperAllocas.ArgSizes->getAllocatedType()->isArrayTy());
3834   ArrType = dyn_cast<ArrayType>(MapperAllocas.ArgSizes->getAllocatedType());
3835   EXPECT_EQ(ArrType->getNumElements(), TotalNbOperand);
3836   EXPECT_TRUE(MapperAllocas.ArgSizes->getAllocatedType()
3837                   ->getArrayElementType()
3838                   ->isIntegerTy(64));
3839 }
3840 
3841 TEST_F(OpenMPIRBuilderTest, EmitMapperCall) {
3842   OpenMPIRBuilder OMPBuilder(*M);
3843   OMPBuilder.initialize();
3844   F->setName("func");
3845   IRBuilder<> Builder(BB);
3846   LLVMContext &Ctx = M->getContext();
3847 
3848   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
3849 
3850   unsigned TotalNbOperand = 2;
3851 
3852   OpenMPIRBuilder::MapperAllocas MapperAllocas;
3853   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
3854                                     F->getEntryBlock().getFirstInsertionPt());
3855   OMPBuilder.createMapperAllocas(Loc, AllocaIP, TotalNbOperand, MapperAllocas);
3856 
3857   auto *BeginMapperFunc = OMPBuilder.getOrCreateRuntimeFunctionPtr(
3858       omp::OMPRTL___tgt_target_data_begin_mapper);
3859 
3860   SmallVector<uint64_t> Flags = {0, 2};
3861 
3862   uint32_t StrSize;
3863   Constant *SrcLocCst =
3864       OMPBuilder.getOrCreateSrcLocStr("", "file1", 2, 5, StrSize);
3865   Value *SrcLocInfo = OMPBuilder.getOrCreateIdent(SrcLocCst, StrSize);
3866 
3867   Constant *Cst1 =
3868       OMPBuilder.getOrCreateSrcLocStr("array1", "file1", 2, 5, StrSize);
3869   Constant *Cst2 =
3870       OMPBuilder.getOrCreateSrcLocStr("array2", "file1", 3, 5, StrSize);
3871   SmallVector<llvm::Constant *> Names = {Cst1, Cst2};
3872 
3873   GlobalVariable *Maptypes =
3874       OMPBuilder.createOffloadMaptypes(Flags, ".offload_maptypes");
3875   Value *MaptypesArg = Builder.CreateConstInBoundsGEP2_32(
3876       ArrayType::get(Type::getInt64Ty(Ctx), TotalNbOperand), Maptypes,
3877       /*Idx0=*/0, /*Idx1=*/0);
3878 
3879   GlobalVariable *Mapnames =
3880       OMPBuilder.createOffloadMapnames(Names, ".offload_mapnames");
3881   Value *MapnamesArg = Builder.CreateConstInBoundsGEP2_32(
3882       ArrayType::get(Type::getInt8PtrTy(Ctx), TotalNbOperand), Mapnames,
3883       /*Idx0=*/0, /*Idx1=*/0);
3884 
3885   OMPBuilder.emitMapperCall(Builder.saveIP(), BeginMapperFunc, SrcLocInfo,
3886                             MaptypesArg, MapnamesArg, MapperAllocas, -1,
3887                             TotalNbOperand);
3888 
3889   CallInst *MapperCall = dyn_cast<CallInst>(&BB->back());
3890   EXPECT_NE(MapperCall, nullptr);
3891   EXPECT_EQ(MapperCall->arg_size(), 9U);
3892   EXPECT_EQ(MapperCall->getCalledFunction()->getName(),
3893             "__tgt_target_data_begin_mapper");
3894   EXPECT_EQ(MapperCall->getOperand(0), SrcLocInfo);
3895   EXPECT_TRUE(MapperCall->getOperand(1)->getType()->isIntegerTy(64));
3896   EXPECT_TRUE(MapperCall->getOperand(2)->getType()->isIntegerTy(32));
3897 
3898   EXPECT_EQ(MapperCall->getOperand(6), MaptypesArg);
3899   EXPECT_EQ(MapperCall->getOperand(7), MapnamesArg);
3900   EXPECT_TRUE(MapperCall->getOperand(8)->getType()->isPointerTy());
3901 }
3902 
3903 } // namespace
3904