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