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