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