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