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