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 allocation, if no value is stored or if there is
158 // more than one store.
159 static Value *findStoredValue(Value *AllocaValue) {
160   Instruction *Alloca = dyn_cast<AllocaInst>(AllocaValue);
161   if (!Alloca)
162     return nullptr;
163   StoreInst *Store = nullptr;
164   for (Use &U : Alloca->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(ForkCI->getArgOperand(3)), F->arg_begin());
549 }
550 
551 TEST_F(OpenMPIRBuilderTest, ParallelNested) {
552   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
553   OpenMPIRBuilder OMPBuilder(*M);
554   OMPBuilder.initialize();
555   F->setName("func");
556   IRBuilder<> Builder(BB);
557 
558   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
559 
560   unsigned NumInnerBodiesGenerated = 0;
561   unsigned NumOuterBodiesGenerated = 0;
562   unsigned NumFinalizationPoints = 0;
563 
564   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
565                             BasicBlock &ContinuationIP) {
566     ++NumInnerBodiesGenerated;
567   };
568 
569   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
570                     Value &Orig, Value &Inner,
571                     Value *&ReplacementValue) -> InsertPointTy {
572     // Trivial copy (=firstprivate).
573     Builder.restoreIP(AllocaIP);
574     Type *VTy = Inner.getType()->getPointerElementType();
575     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
576     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
577     Builder.restoreIP(CodeGenIP);
578     Builder.CreateStore(V, ReplacementValue);
579     return CodeGenIP;
580   };
581 
582   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
583 
584   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
585                             BasicBlock &ContinuationIP) {
586     ++NumOuterBodiesGenerated;
587     Builder.restoreIP(CodeGenIP);
588     BasicBlock *CGBB = CodeGenIP.getBlock();
589     BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint());
590     CGBB->getTerminator()->eraseFromParent();
591     ;
592 
593     IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel(
594         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
595         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
596 
597     Builder.restoreIP(AfterIP);
598     Builder.CreateBr(NewBB);
599   };
600 
601   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
602                                     F->getEntryBlock().getFirstInsertionPt());
603   IRBuilder<>::InsertPoint AfterIP =
604       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
605                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
606 
607   EXPECT_EQ(NumInnerBodiesGenerated, 1U);
608   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
609   EXPECT_EQ(NumFinalizationPoints, 2U);
610 
611   Builder.restoreIP(AfterIP);
612   Builder.CreateRetVoid();
613 
614   OMPBuilder.finalize();
615 
616   EXPECT_EQ(M->size(), 5U);
617   for (Function &OutlinedFn : *M) {
618     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
619       continue;
620     EXPECT_FALSE(verifyModule(*M, &errs()));
621     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
622     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
623     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
624     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
625 
626     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
627     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
628 
629     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
630     User *Usr = OutlinedFn.user_back();
631     ASSERT_TRUE(isa<ConstantExpr>(Usr));
632     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
633     ASSERT_NE(ForkCI, nullptr);
634 
635     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
636     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
637     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
638     EXPECT_EQ(ForkCI->getArgOperand(1),
639               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
640     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
641   }
642 }
643 
644 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) {
645   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
646   OpenMPIRBuilder OMPBuilder(*M);
647   OMPBuilder.initialize();
648   F->setName("func");
649   IRBuilder<> Builder(BB);
650 
651   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
652 
653   unsigned NumInnerBodiesGenerated = 0;
654   unsigned NumOuterBodiesGenerated = 0;
655   unsigned NumFinalizationPoints = 0;
656 
657   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
658                             BasicBlock &ContinuationIP) {
659     ++NumInnerBodiesGenerated;
660   };
661 
662   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
663                     Value &Orig, Value &Inner,
664                     Value *&ReplacementValue) -> InsertPointTy {
665     // Trivial copy (=firstprivate).
666     Builder.restoreIP(AllocaIP);
667     Type *VTy = Inner.getType()->getPointerElementType();
668     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
669     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
670     Builder.restoreIP(CodeGenIP);
671     Builder.CreateStore(V, ReplacementValue);
672     return CodeGenIP;
673   };
674 
675   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
676 
677   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
678                             BasicBlock &ContinuationIP) {
679     ++NumOuterBodiesGenerated;
680     Builder.restoreIP(CodeGenIP);
681     BasicBlock *CGBB = CodeGenIP.getBlock();
682     BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint());
683     BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt());
684     CGBB->getTerminator()->eraseFromParent();
685     ;
686     NewBB1->getTerminator()->eraseFromParent();
687     ;
688 
689     IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel(
690         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
691         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
692 
693     Builder.restoreIP(AfterIP1);
694     Builder.CreateBr(NewBB1);
695 
696     IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel(
697         InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB,
698         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
699 
700     Builder.restoreIP(AfterIP2);
701     Builder.CreateBr(NewBB2);
702   };
703 
704   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
705                                     F->getEntryBlock().getFirstInsertionPt());
706   IRBuilder<>::InsertPoint AfterIP =
707       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
708                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
709 
710   EXPECT_EQ(NumInnerBodiesGenerated, 2U);
711   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
712   EXPECT_EQ(NumFinalizationPoints, 3U);
713 
714   Builder.restoreIP(AfterIP);
715   Builder.CreateRetVoid();
716 
717   OMPBuilder.finalize();
718 
719   EXPECT_EQ(M->size(), 6U);
720   for (Function &OutlinedFn : *M) {
721     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
722       continue;
723     EXPECT_FALSE(verifyModule(*M, &errs()));
724     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
725     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
726     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
727     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
728 
729     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
730     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
731 
732     unsigned NumAllocas = 0;
733     for (Instruction &I : instructions(OutlinedFn))
734       NumAllocas += isa<AllocaInst>(I);
735     EXPECT_EQ(NumAllocas, 1U);
736 
737     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
738     User *Usr = OutlinedFn.user_back();
739     ASSERT_TRUE(isa<ConstantExpr>(Usr));
740     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
741     ASSERT_NE(ForkCI, nullptr);
742 
743     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
744     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
745     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
746     EXPECT_EQ(ForkCI->getArgOperand(1),
747               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
748     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
749   }
750 }
751 
752 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
753   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
754   OpenMPIRBuilder OMPBuilder(*M);
755   OMPBuilder.initialize();
756   F->setName("func");
757   IRBuilder<> Builder(BB);
758 
759   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
760 
761   AllocaInst *PrivAI = nullptr;
762 
763   unsigned NumBodiesGenerated = 0;
764   unsigned NumPrivatizedVars = 0;
765   unsigned NumFinalizationPoints = 0;
766 
767   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
768                        BasicBlock &ContinuationIP) {
769     ++NumBodiesGenerated;
770 
771     Builder.restoreIP(AllocaIP);
772     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
773     Builder.CreateStore(F->arg_begin(), PrivAI);
774 
775     Builder.restoreIP(CodeGenIP);
776     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
777                                          "local.use");
778     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
779     Instruction *ThenTerm, *ElseTerm;
780     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
781                                   &ThenTerm, &ElseTerm);
782 
783     Builder.SetInsertPoint(ThenTerm);
784     Builder.CreateBr(&ContinuationIP);
785     ThenTerm->eraseFromParent();
786   };
787 
788   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
789                     Value &Orig, Value &Inner,
790                     Value *&ReplacementValue) -> InsertPointTy {
791     ++NumPrivatizedVars;
792 
793     if (!isa<AllocaInst>(Orig)) {
794       EXPECT_EQ(&Orig, F->arg_begin());
795       ReplacementValue = &Inner;
796       return CodeGenIP;
797     }
798 
799     // Since the original value is an allocation, it has a pointer type and
800     // therefore no additional wrapping should happen.
801     EXPECT_EQ(&Orig, &Inner);
802 
803     // Trivial copy (=firstprivate).
804     Builder.restoreIP(AllocaIP);
805     Type *VTy = Inner.getType()->getPointerElementType();
806     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
807     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
808     Builder.restoreIP(CodeGenIP);
809     Builder.CreateStore(V, ReplacementValue);
810     return CodeGenIP;
811   };
812 
813   auto FiniCB = [&](InsertPointTy CodeGenIP) {
814     ++NumFinalizationPoints;
815     // No destructors.
816   };
817 
818   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
819                                     F->getEntryBlock().getFirstInsertionPt());
820   IRBuilder<>::InsertPoint AfterIP =
821       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
822                                 Builder.CreateIsNotNull(F->arg_begin()),
823                                 nullptr, OMP_PROC_BIND_default, false);
824 
825   EXPECT_EQ(NumBodiesGenerated, 1U);
826   EXPECT_EQ(NumPrivatizedVars, 1U);
827   EXPECT_EQ(NumFinalizationPoints, 1U);
828 
829   Builder.restoreIP(AfterIP);
830   Builder.CreateRetVoid();
831   OMPBuilder.finalize();
832 
833   EXPECT_NE(PrivAI, nullptr);
834   Function *OutlinedFn = PrivAI->getFunction();
835   EXPECT_NE(F, OutlinedFn);
836   EXPECT_FALSE(verifyModule(*M, &errs()));
837 
838   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
839   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
840 
841   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
842   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
843 
844   CallInst *DirectCI = nullptr;
845   CallInst *ForkCI = nullptr;
846   for (User *Usr : OutlinedFn->users()) {
847     if (isa<CallInst>(Usr)) {
848       ASSERT_EQ(DirectCI, nullptr);
849       DirectCI = cast<CallInst>(Usr);
850     } else {
851       ASSERT_TRUE(isa<ConstantExpr>(Usr));
852       ASSERT_EQ(Usr->getNumUses(), 1U);
853       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
854       ForkCI = cast<CallInst>(Usr->user_back());
855     }
856   }
857 
858   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
859   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
860   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
861   EXPECT_EQ(ForkCI->getArgOperand(1),
862             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
863   Value *StoredForkArg = findStoredValue(ForkCI->getArgOperand(3));
864   EXPECT_EQ(StoredForkArg, F->arg_begin());
865 
866   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
867   EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
868   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
869   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
870   Value *StoredDirectArg = findStoredValue(DirectCI->getArgOperand(2));
871   EXPECT_EQ(StoredDirectArg, F->arg_begin());
872 }
873 
874 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
875   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
876   OpenMPIRBuilder OMPBuilder(*M);
877   OMPBuilder.initialize();
878   F->setName("func");
879   IRBuilder<> Builder(BB);
880 
881   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
882 
883   unsigned NumBodiesGenerated = 0;
884   unsigned NumPrivatizedVars = 0;
885   unsigned NumFinalizationPoints = 0;
886 
887   CallInst *CheckedBarrier = nullptr;
888   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
889                        BasicBlock &ContinuationIP) {
890     ++NumBodiesGenerated;
891 
892     Builder.restoreIP(CodeGenIP);
893 
894     // Create three barriers, two cancel barriers but only one checked.
895     Function *CBFn, *BFn;
896 
897     Builder.restoreIP(
898         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel));
899 
900     CBFn = M->getFunction("__kmpc_cancel_barrier");
901     BFn = M->getFunction("__kmpc_barrier");
902     ASSERT_NE(CBFn, nullptr);
903     ASSERT_EQ(BFn, nullptr);
904     ASSERT_EQ(CBFn->getNumUses(), 1U);
905     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
906     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
907     CheckedBarrier = cast<CallInst>(CBFn->user_back());
908 
909     Builder.restoreIP(
910         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true));
911     CBFn = M->getFunction("__kmpc_cancel_barrier");
912     BFn = M->getFunction("__kmpc_barrier");
913     ASSERT_NE(CBFn, nullptr);
914     ASSERT_NE(BFn, nullptr);
915     ASSERT_EQ(CBFn->getNumUses(), 1U);
916     ASSERT_EQ(BFn->getNumUses(), 1U);
917     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
918     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
919 
920     Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel,
921                                                false, false));
922     ASSERT_EQ(CBFn->getNumUses(), 2U);
923     ASSERT_EQ(BFn->getNumUses(), 1U);
924     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
925     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
926     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
927   };
928 
929   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &,
930                     Value *&) -> InsertPointTy {
931     ++NumPrivatizedVars;
932     llvm_unreachable("No privatization callback call expected!");
933   };
934 
935   FunctionType *FakeDestructorTy =
936       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
937                         /*isVarArg=*/false);
938   auto *FakeDestructor = Function::Create(
939       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
940 
941   auto FiniCB = [&](InsertPointTy IP) {
942     ++NumFinalizationPoints;
943     Builder.restoreIP(IP);
944     Builder.CreateCall(FakeDestructor,
945                        {Builder.getInt32(NumFinalizationPoints)});
946   };
947 
948   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
949                                     F->getEntryBlock().getFirstInsertionPt());
950   IRBuilder<>::InsertPoint AfterIP =
951       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
952                                 Builder.CreateIsNotNull(F->arg_begin()),
953                                 nullptr, OMP_PROC_BIND_default, true);
954 
955   EXPECT_EQ(NumBodiesGenerated, 1U);
956   EXPECT_EQ(NumPrivatizedVars, 0U);
957   EXPECT_EQ(NumFinalizationPoints, 2U);
958   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
959 
960   Builder.restoreIP(AfterIP);
961   Builder.CreateRetVoid();
962   OMPBuilder.finalize();
963 
964   EXPECT_FALSE(verifyModule(*M, &errs()));
965 
966   BasicBlock *ExitBB = nullptr;
967   for (const User *Usr : FakeDestructor->users()) {
968     const CallInst *CI = dyn_cast<CallInst>(Usr);
969     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
970     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
971     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
972     if (ExitBB)
973       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
974     else
975       ExitBB = CI->getNextNode()->getSuccessor(0);
976     ASSERT_EQ(ExitBB->size(), 1U);
977     if (!isa<ReturnInst>(ExitBB->front())) {
978       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
979       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
980       ASSERT_TRUE(isa<ReturnInst>(
981           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
982     }
983   }
984 }
985 
986 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) {
987   OpenMPIRBuilder OMPBuilder(*M);
988   OMPBuilder.initialize();
989   F->setName("func");
990   IRBuilder<> Builder(BB);
991   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
992   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
993 
994   Type *I32Ty = Type::getInt32Ty(M->getContext());
995   Type *I32PtrTy = Type::getInt32PtrTy(M->getContext());
996   Type *StructTy = StructType::get(I32Ty, I32PtrTy);
997   Type *StructPtrTy = StructTy->getPointerTo();
998   Type *VoidTy = Type::getVoidTy(M->getContext());
999   FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty);
1000   FunctionCallee TakeI32Func =
1001       M->getOrInsertFunction("take_i32", VoidTy, I32Ty);
1002   FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy);
1003   FunctionCallee TakeI32PtrFunc =
1004       M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy);
1005   FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy);
1006   FunctionCallee TakeStructFunc =
1007       M->getOrInsertFunction("take_struct", VoidTy, StructTy);
1008   FunctionCallee RetStructPtrFunc =
1009       M->getOrInsertFunction("ret_structptr", StructPtrTy);
1010   FunctionCallee TakeStructPtrFunc =
1011       M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy);
1012   Value *I32Val = Builder.CreateCall(RetI32Func);
1013   Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc);
1014   Value *StructVal = Builder.CreateCall(RetStructFunc);
1015   Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc);
1016 
1017   Instruction *Internal;
1018   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1019                        BasicBlock &ContinuationBB) {
1020     IRBuilder<>::InsertPointGuard Guard(Builder);
1021     Builder.restoreIP(CodeGenIP);
1022     Internal = Builder.CreateCall(TakeI32Func, I32Val);
1023     Builder.CreateCall(TakeI32PtrFunc, I32PtrVal);
1024     Builder.CreateCall(TakeStructFunc, StructVal);
1025     Builder.CreateCall(TakeStructPtrFunc, StructPtrVal);
1026   };
1027   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &,
1028                     Value &Inner, Value *&ReplacementValue) {
1029     ReplacementValue = &Inner;
1030     return CodeGenIP;
1031   };
1032   auto FiniCB = [](InsertPointTy) {};
1033 
1034   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
1035                                     F->getEntryBlock().getFirstInsertionPt());
1036   IRBuilder<>::InsertPoint AfterIP =
1037       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1038                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
1039   Builder.restoreIP(AfterIP);
1040   Builder.CreateRetVoid();
1041 
1042   OMPBuilder.finalize();
1043 
1044   EXPECT_FALSE(verifyModule(*M, &errs()));
1045   Function *OutlinedFn = Internal->getFunction();
1046 
1047   Type *Arg2Type = OutlinedFn->getArg(2)->getType();
1048   EXPECT_TRUE(Arg2Type->isPointerTy());
1049   EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty);
1050 
1051   // Arguments that need to be passed through pointers and reloaded will get
1052   // used earlier in the functions and therefore will appear first in the
1053   // argument list after outlining.
1054   Type *Arg3Type = OutlinedFn->getArg(3)->getType();
1055   EXPECT_TRUE(Arg3Type->isPointerTy());
1056   EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy);
1057 
1058   Type *Arg4Type = OutlinedFn->getArg(4)->getType();
1059   EXPECT_EQ(Arg4Type, I32PtrTy);
1060 
1061   Type *Arg5Type = OutlinedFn->getArg(5)->getType();
1062   EXPECT_EQ(Arg5Type, StructPtrTy);
1063 }
1064 
1065 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) {
1066   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1067   OpenMPIRBuilder OMPBuilder(*M);
1068   OMPBuilder.initialize();
1069   IRBuilder<> Builder(BB);
1070   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1071   Value *TripCount = F->getArg(0);
1072 
1073   unsigned NumBodiesGenerated = 0;
1074   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
1075     NumBodiesGenerated += 1;
1076 
1077     Builder.restoreIP(CodeGenIP);
1078 
1079     Value *Cmp = Builder.CreateICmpEQ(LC, TripCount);
1080     Instruction *ThenTerm, *ElseTerm;
1081     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
1082                                   &ThenTerm, &ElseTerm);
1083   };
1084 
1085   CanonicalLoopInfo *Loop =
1086       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
1087 
1088   Builder.restoreIP(Loop->getAfterIP());
1089   ReturnInst *RetInst = Builder.CreateRetVoid();
1090   OMPBuilder.finalize();
1091 
1092   Loop->assertOK();
1093   EXPECT_FALSE(verifyModule(*M, &errs()));
1094 
1095   EXPECT_EQ(NumBodiesGenerated, 1U);
1096 
1097   // Verify control flow structure (in addition to Loop->assertOK()).
1098   EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock());
1099   EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock());
1100 
1101   Instruction *IndVar = Loop->getIndVar();
1102   EXPECT_TRUE(isa<PHINode>(IndVar));
1103   EXPECT_EQ(IndVar->getType(), TripCount->getType());
1104   EXPECT_EQ(IndVar->getParent(), Loop->getHeader());
1105 
1106   EXPECT_EQ(Loop->getTripCount(), TripCount);
1107 
1108   BasicBlock *Body = Loop->getBody();
1109   Instruction *CmpInst = &Body->getInstList().front();
1110   EXPECT_TRUE(isa<ICmpInst>(CmpInst));
1111   EXPECT_EQ(CmpInst->getOperand(0), IndVar);
1112 
1113   BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor();
1114   EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) {
1115     return SuccBB->getSingleSuccessor() == LatchPred;
1116   }));
1117 
1118   EXPECT_EQ(&Loop->getAfter()->front(), RetInst);
1119 }
1120 
1121 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) {
1122   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1123   OpenMPIRBuilder OMPBuilder(*M);
1124   OMPBuilder.initialize();
1125   IRBuilder<> Builder(BB);
1126 
1127   // Check the trip count is computed correctly. We generate the canonical loop
1128   // but rely on the IRBuilder's constant folder to compute the final result
1129   // since all inputs are constant. To verify overflow situations, limit the
1130   // trip count / loop counter widths to 16 bits.
1131   auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1132                            bool IsSigned, bool InclusiveStop) -> int64_t {
1133     OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1134     Type *LCTy = Type::getInt16Ty(Ctx);
1135     Value *StartVal = ConstantInt::get(LCTy, Start);
1136     Value *StopVal = ConstantInt::get(LCTy, Stop);
1137     Value *StepVal = ConstantInt::get(LCTy, Step);
1138     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1139     CanonicalLoopInfo *Loop =
1140         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1141                                        StepVal, IsSigned, InclusiveStop);
1142     Loop->assertOK();
1143     Builder.restoreIP(Loop->getAfterIP());
1144     Value *TripCount = Loop->getTripCount();
1145     return cast<ConstantInt>(TripCount)->getValue().getZExtValue();
1146   };
1147 
1148   EXPECT_EQ(EvalTripCount(0, 0, 1, false, false), 0);
1149   EXPECT_EQ(EvalTripCount(0, 1, 2, false, false), 1);
1150   EXPECT_EQ(EvalTripCount(0, 42, 1, false, false), 42);
1151   EXPECT_EQ(EvalTripCount(0, 42, 2, false, false), 21);
1152   EXPECT_EQ(EvalTripCount(21, 42, 1, false, false), 21);
1153   EXPECT_EQ(EvalTripCount(0, 5, 5, false, false), 1);
1154   EXPECT_EQ(EvalTripCount(0, 9, 5, false, false), 2);
1155   EXPECT_EQ(EvalTripCount(0, 11, 5, false, false), 3);
1156   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF);
1157   EXPECT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0);
1158   EXPECT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1);
1159   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100);
1160   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1);
1161 
1162   EXPECT_EQ(EvalTripCount(0, 6, 5, false, false), 2);
1163   EXPECT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2);
1164   EXPECT_EQ(EvalTripCount(0, 0, 1, false, true), 1);
1165   EXPECT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1);
1166   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF);
1167   EXPECT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000);
1168 
1169   EXPECT_EQ(EvalTripCount(0, 0, -1, true, false), 0);
1170   EXPECT_EQ(EvalTripCount(0, 1, -1, true, true), 0);
1171   EXPECT_EQ(EvalTripCount(20, 5, -5, true, false), 3);
1172   EXPECT_EQ(EvalTripCount(20, 5, -5, true, true), 4);
1173   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, false), 1);
1174   EXPECT_EQ(EvalTripCount(-4, -3, 2, true, false), 1);
1175   EXPECT_EQ(EvalTripCount(-4, -2, 2, true, true), 2);
1176 
1177   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000);
1178   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001);
1179   EXPECT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF);
1180   EXPECT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF);
1181   EXPECT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2);
1182   EXPECT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF);
1183   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000);
1184   EXPECT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800);
1185   EXPECT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF);
1186   EXPECT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1);
1187   EXPECT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2);
1188 
1189   // Finalize the function and verify it.
1190   Builder.CreateRetVoid();
1191   OMPBuilder.finalize();
1192   EXPECT_FALSE(verifyModule(*M, &errs()));
1193 }
1194 
1195 TEST_F(OpenMPIRBuilderTest, CollapseNestedLoops) {
1196   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1197   OpenMPIRBuilder OMPBuilder(*M);
1198   OMPBuilder.initialize();
1199   F->setName("func");
1200 
1201   IRBuilder<> Builder(BB);
1202 
1203   Type *LCTy = F->getArg(0)->getType();
1204   Constant *One = ConstantInt::get(LCTy, 1);
1205   Constant *Two = ConstantInt::get(LCTy, 2);
1206   Value *OuterTripCount =
1207       Builder.CreateAdd(F->getArg(0), Two, "tripcount.outer");
1208   Value *InnerTripCount =
1209       Builder.CreateAdd(F->getArg(0), One, "tripcount.inner");
1210 
1211   // Fix an insertion point for ComputeIP.
1212   BasicBlock *LoopNextEnter =
1213       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1214                          Builder.GetInsertBlock()->getNextNode());
1215   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1216   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1217 
1218   Builder.SetInsertPoint(LoopNextEnter);
1219   OpenMPIRBuilder::LocationDescription OuterLoc(Builder.saveIP(), DL);
1220 
1221   CanonicalLoopInfo *InnerLoop = nullptr;
1222   CallInst *InbetweenLead = nullptr;
1223   CallInst *InbetweenTrail = nullptr;
1224   CallInst *Call = nullptr;
1225   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP, Value *OuterLC) {
1226     Builder.restoreIP(OuterCodeGenIP);
1227     InbetweenLead =
1228         createPrintfCall(Builder, "In-between lead i=%d\\n", {OuterLC});
1229 
1230     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1231                                   Value *InnerLC) {
1232       Builder.restoreIP(InnerCodeGenIP);
1233       Call = createPrintfCall(Builder, "body i=%d j=%d\\n", {OuterLC, InnerLC});
1234     };
1235     InnerLoop = OMPBuilder.createCanonicalLoop(
1236         Builder.saveIP(), InnerLoopBodyGenCB, InnerTripCount, "inner");
1237 
1238     Builder.restoreIP(InnerLoop->getAfterIP());
1239     InbetweenTrail =
1240         createPrintfCall(Builder, "In-between trail i=%d\\n", {OuterLC});
1241   };
1242   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1243       OuterLoc, OuterLoopBodyGenCB, OuterTripCount, "outer");
1244 
1245   // Finish the function.
1246   Builder.restoreIP(OuterLoop->getAfterIP());
1247   Builder.CreateRetVoid();
1248 
1249   CanonicalLoopInfo *Collapsed =
1250       OMPBuilder.collapseLoops(DL, {OuterLoop, InnerLoop}, ComputeIP);
1251 
1252   OMPBuilder.finalize();
1253   EXPECT_FALSE(verifyModule(*M, &errs()));
1254 
1255   // Verify control flow and BB order.
1256   BasicBlock *RefOrder[] = {
1257       Collapsed->getPreheader(),   Collapsed->getHeader(),
1258       Collapsed->getCond(),        Collapsed->getBody(),
1259       InbetweenLead->getParent(),  Call->getParent(),
1260       InbetweenTrail->getParent(), Collapsed->getLatch(),
1261       Collapsed->getExit(),        Collapsed->getAfter(),
1262   };
1263   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1264   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1265 
1266   // Verify the total trip count.
1267   auto *TripCount = cast<MulOperator>(Collapsed->getTripCount());
1268   EXPECT_EQ(TripCount->getOperand(0), OuterTripCount);
1269   EXPECT_EQ(TripCount->getOperand(1), InnerTripCount);
1270 
1271   // Verify the changed indvar.
1272   auto *OuterIV = cast<BinaryOperator>(Call->getOperand(1));
1273   EXPECT_EQ(OuterIV->getOpcode(), Instruction::UDiv);
1274   EXPECT_EQ(OuterIV->getParent(), Collapsed->getBody());
1275   EXPECT_EQ(OuterIV->getOperand(1), InnerTripCount);
1276   EXPECT_EQ(OuterIV->getOperand(0), Collapsed->getIndVar());
1277 
1278   auto *InnerIV = cast<BinaryOperator>(Call->getOperand(2));
1279   EXPECT_EQ(InnerIV->getOpcode(), Instruction::URem);
1280   EXPECT_EQ(InnerIV->getParent(), Collapsed->getBody());
1281   EXPECT_EQ(InnerIV->getOperand(0), Collapsed->getIndVar());
1282   EXPECT_EQ(InnerIV->getOperand(1), InnerTripCount);
1283 
1284   EXPECT_EQ(InbetweenLead->getOperand(1), OuterIV);
1285   EXPECT_EQ(InbetweenTrail->getOperand(1), OuterIV);
1286 }
1287 
1288 TEST_F(OpenMPIRBuilderTest, TileSingleLoop) {
1289   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1290   OpenMPIRBuilder OMPBuilder(*M);
1291   OMPBuilder.initialize();
1292   F->setName("func");
1293 
1294   IRBuilder<> Builder(BB);
1295   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1296   Value *TripCount = F->getArg(0);
1297 
1298   BasicBlock *BodyCode = nullptr;
1299   Instruction *Call = nullptr;
1300   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
1301     Builder.restoreIP(CodeGenIP);
1302     BodyCode = Builder.GetInsertBlock();
1303 
1304     // Add something that consumes the induction variable to the body.
1305     Call = createPrintfCall(Builder, "%d\\n", {LC});
1306   };
1307   CanonicalLoopInfo *Loop =
1308       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
1309 
1310   // Finalize the function.
1311   Builder.restoreIP(Loop->getAfterIP());
1312   Builder.CreateRetVoid();
1313 
1314   Instruction *OrigIndVar = Loop->getIndVar();
1315   EXPECT_EQ(Call->getOperand(1), OrigIndVar);
1316 
1317   // Tile the loop.
1318   Constant *TileSize = ConstantInt::get(Loop->getIndVarType(), APInt(32, 7));
1319   std::vector<CanonicalLoopInfo *> GenLoops =
1320       OMPBuilder.tileLoops(DL, {Loop}, {TileSize});
1321 
1322   OMPBuilder.finalize();
1323   EXPECT_FALSE(verifyModule(*M, &errs()));
1324 
1325   EXPECT_EQ(GenLoops.size(), 2u);
1326   CanonicalLoopInfo *Floor = GenLoops[0];
1327   CanonicalLoopInfo *Tile = GenLoops[1];
1328 
1329   BasicBlock *RefOrder[] = {
1330       Floor->getPreheader(), Floor->getHeader(),   Floor->getCond(),
1331       Floor->getBody(),      Tile->getPreheader(), Tile->getHeader(),
1332       Tile->getCond(),       Tile->getBody(),      BodyCode,
1333       Tile->getLatch(),      Tile->getExit(),      Tile->getAfter(),
1334       Floor->getLatch(),     Floor->getExit(),     Floor->getAfter(),
1335   };
1336   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1337   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1338 
1339   // Check the induction variable.
1340   EXPECT_EQ(Call->getParent(), BodyCode);
1341   auto *Shift = cast<AddOperator>(Call->getOperand(1));
1342   EXPECT_EQ(cast<Instruction>(Shift)->getParent(), Tile->getBody());
1343   EXPECT_EQ(Shift->getOperand(1), Tile->getIndVar());
1344   auto *Scale = cast<MulOperator>(Shift->getOperand(0));
1345   EXPECT_EQ(cast<Instruction>(Scale)->getParent(), Tile->getBody());
1346   EXPECT_EQ(Scale->getOperand(0), TileSize);
1347   EXPECT_EQ(Scale->getOperand(1), Floor->getIndVar());
1348 }
1349 
1350 TEST_F(OpenMPIRBuilderTest, TileNestedLoops) {
1351   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1352   OpenMPIRBuilder OMPBuilder(*M);
1353   OMPBuilder.initialize();
1354   F->setName("func");
1355 
1356   IRBuilder<> Builder(BB);
1357   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1358   Value *TripCount = F->getArg(0);
1359   Type *LCTy = TripCount->getType();
1360 
1361   BasicBlock *BodyCode = nullptr;
1362   CanonicalLoopInfo *InnerLoop = nullptr;
1363   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1364                                 llvm::Value *OuterLC) {
1365     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1366                                   llvm::Value *InnerLC) {
1367       Builder.restoreIP(InnerCodeGenIP);
1368       BodyCode = Builder.GetInsertBlock();
1369 
1370       // Add something that consumes the induction variables to the body.
1371       createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1372     };
1373     InnerLoop = OMPBuilder.createCanonicalLoop(
1374         OuterCodeGenIP, InnerLoopBodyGenCB, TripCount, "inner");
1375   };
1376   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1377       Loc, OuterLoopBodyGenCB, TripCount, "outer");
1378 
1379   // Finalize the function.
1380   Builder.restoreIP(OuterLoop->getAfterIP());
1381   Builder.CreateRetVoid();
1382 
1383   // Tile to loop nest.
1384   Constant *OuterTileSize = ConstantInt::get(LCTy, APInt(32, 11));
1385   Constant *InnerTileSize = ConstantInt::get(LCTy, APInt(32, 7));
1386   std::vector<CanonicalLoopInfo *> GenLoops = OMPBuilder.tileLoops(
1387       DL, {OuterLoop, InnerLoop}, {OuterTileSize, InnerTileSize});
1388 
1389   OMPBuilder.finalize();
1390   EXPECT_FALSE(verifyModule(*M, &errs()));
1391 
1392   EXPECT_EQ(GenLoops.size(), 4u);
1393   CanonicalLoopInfo *Floor1 = GenLoops[0];
1394   CanonicalLoopInfo *Floor2 = GenLoops[1];
1395   CanonicalLoopInfo *Tile1 = GenLoops[2];
1396   CanonicalLoopInfo *Tile2 = GenLoops[3];
1397 
1398   BasicBlock *RefOrder[] = {
1399       Floor1->getPreheader(),
1400       Floor1->getHeader(),
1401       Floor1->getCond(),
1402       Floor1->getBody(),
1403       Floor2->getPreheader(),
1404       Floor2->getHeader(),
1405       Floor2->getCond(),
1406       Floor2->getBody(),
1407       Tile1->getPreheader(),
1408       Tile1->getHeader(),
1409       Tile1->getCond(),
1410       Tile1->getBody(),
1411       Tile2->getPreheader(),
1412       Tile2->getHeader(),
1413       Tile2->getCond(),
1414       Tile2->getBody(),
1415       BodyCode,
1416       Tile2->getLatch(),
1417       Tile2->getExit(),
1418       Tile2->getAfter(),
1419       Tile1->getLatch(),
1420       Tile1->getExit(),
1421       Tile1->getAfter(),
1422       Floor2->getLatch(),
1423       Floor2->getExit(),
1424       Floor2->getAfter(),
1425       Floor1->getLatch(),
1426       Floor1->getExit(),
1427       Floor1->getAfter(),
1428   };
1429   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1430   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1431 }
1432 
1433 TEST_F(OpenMPIRBuilderTest, TileNestedLoopsWithBounds) {
1434   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1435   OpenMPIRBuilder OMPBuilder(*M);
1436   OMPBuilder.initialize();
1437   F->setName("func");
1438 
1439   IRBuilder<> Builder(BB);
1440   Value *TripCount = F->getArg(0);
1441   Type *LCTy = TripCount->getType();
1442 
1443   Value *OuterStartVal = ConstantInt::get(LCTy, 2);
1444   Value *OuterStopVal = TripCount;
1445   Value *OuterStep = ConstantInt::get(LCTy, 5);
1446   Value *InnerStartVal = ConstantInt::get(LCTy, 13);
1447   Value *InnerStopVal = TripCount;
1448   Value *InnerStep = ConstantInt::get(LCTy, 3);
1449 
1450   // Fix an insertion point for ComputeIP.
1451   BasicBlock *LoopNextEnter =
1452       BasicBlock::Create(M->getContext(), "loopnest.enter", F,
1453                          Builder.GetInsertBlock()->getNextNode());
1454   BranchInst *EnterBr = Builder.CreateBr(LoopNextEnter);
1455   InsertPointTy ComputeIP{EnterBr->getParent(), EnterBr->getIterator()};
1456 
1457   InsertPointTy LoopIP{LoopNextEnter, LoopNextEnter->begin()};
1458   OpenMPIRBuilder::LocationDescription Loc({LoopIP, DL});
1459 
1460   BasicBlock *BodyCode = nullptr;
1461   CanonicalLoopInfo *InnerLoop = nullptr;
1462   CallInst *Call = nullptr;
1463   auto OuterLoopBodyGenCB = [&](InsertPointTy OuterCodeGenIP,
1464                                 llvm::Value *OuterLC) {
1465     auto InnerLoopBodyGenCB = [&](InsertPointTy InnerCodeGenIP,
1466                                   llvm::Value *InnerLC) {
1467       Builder.restoreIP(InnerCodeGenIP);
1468       BodyCode = Builder.GetInsertBlock();
1469 
1470       // Add something that consumes the induction variable to the body.
1471       Call = createPrintfCall(Builder, "i=%d j=%d\\n", {OuterLC, InnerLC});
1472     };
1473     InnerLoop = OMPBuilder.createCanonicalLoop(
1474         OuterCodeGenIP, InnerLoopBodyGenCB, InnerStartVal, InnerStopVal,
1475         InnerStep, false, false, ComputeIP, "inner");
1476   };
1477   CanonicalLoopInfo *OuterLoop = OMPBuilder.createCanonicalLoop(
1478       Loc, OuterLoopBodyGenCB, OuterStartVal, OuterStopVal, OuterStep, false,
1479       false, ComputeIP, "outer");
1480 
1481   // Finalize the function
1482   Builder.restoreIP(OuterLoop->getAfterIP());
1483   Builder.CreateRetVoid();
1484 
1485   // Tile the loop nest.
1486   Constant *TileSize0 = ConstantInt::get(LCTy, APInt(32, 11));
1487   Constant *TileSize1 = ConstantInt::get(LCTy, APInt(32, 7));
1488   std::vector<CanonicalLoopInfo *> GenLoops =
1489       OMPBuilder.tileLoops(DL, {OuterLoop, InnerLoop}, {TileSize0, TileSize1});
1490 
1491   OMPBuilder.finalize();
1492   EXPECT_FALSE(verifyModule(*M, &errs()));
1493 
1494   EXPECT_EQ(GenLoops.size(), 4u);
1495   CanonicalLoopInfo *Floor0 = GenLoops[0];
1496   CanonicalLoopInfo *Floor1 = GenLoops[1];
1497   CanonicalLoopInfo *Tile0 = GenLoops[2];
1498   CanonicalLoopInfo *Tile1 = GenLoops[3];
1499 
1500   BasicBlock *RefOrder[] = {
1501       Floor0->getPreheader(),
1502       Floor0->getHeader(),
1503       Floor0->getCond(),
1504       Floor0->getBody(),
1505       Floor1->getPreheader(),
1506       Floor1->getHeader(),
1507       Floor1->getCond(),
1508       Floor1->getBody(),
1509       Tile0->getPreheader(),
1510       Tile0->getHeader(),
1511       Tile0->getCond(),
1512       Tile0->getBody(),
1513       Tile1->getPreheader(),
1514       Tile1->getHeader(),
1515       Tile1->getCond(),
1516       Tile1->getBody(),
1517       BodyCode,
1518       Tile1->getLatch(),
1519       Tile1->getExit(),
1520       Tile1->getAfter(),
1521       Tile0->getLatch(),
1522       Tile0->getExit(),
1523       Tile0->getAfter(),
1524       Floor1->getLatch(),
1525       Floor1->getExit(),
1526       Floor1->getAfter(),
1527       Floor0->getLatch(),
1528       Floor0->getExit(),
1529       Floor0->getAfter(),
1530   };
1531   EXPECT_TRUE(verifyDFSOrder(F, RefOrder));
1532   EXPECT_TRUE(verifyListOrder(F, RefOrder));
1533 
1534   EXPECT_EQ(Call->getParent(), BodyCode);
1535 
1536   auto *RangeShift0 = cast<AddOperator>(Call->getOperand(1));
1537   EXPECT_EQ(RangeShift0->getOperand(1), OuterStartVal);
1538   auto *RangeScale0 = cast<MulOperator>(RangeShift0->getOperand(0));
1539   EXPECT_EQ(RangeScale0->getOperand(1), OuterStep);
1540   auto *TileShift0 = cast<AddOperator>(RangeScale0->getOperand(0));
1541   EXPECT_EQ(cast<Instruction>(TileShift0)->getParent(), Tile1->getBody());
1542   EXPECT_EQ(TileShift0->getOperand(1), Tile0->getIndVar());
1543   auto *TileScale0 = cast<MulOperator>(TileShift0->getOperand(0));
1544   EXPECT_EQ(cast<Instruction>(TileScale0)->getParent(), Tile1->getBody());
1545   EXPECT_EQ(TileScale0->getOperand(0), TileSize0);
1546   EXPECT_EQ(TileScale0->getOperand(1), Floor0->getIndVar());
1547 
1548   auto *RangeShift1 = cast<AddOperator>(Call->getOperand(2));
1549   EXPECT_EQ(cast<Instruction>(RangeShift1)->getParent(), BodyCode);
1550   EXPECT_EQ(RangeShift1->getOperand(1), InnerStartVal);
1551   auto *RangeScale1 = cast<MulOperator>(RangeShift1->getOperand(0));
1552   EXPECT_EQ(cast<Instruction>(RangeScale1)->getParent(), BodyCode);
1553   EXPECT_EQ(RangeScale1->getOperand(1), InnerStep);
1554   auto *TileShift1 = cast<AddOperator>(RangeScale1->getOperand(0));
1555   EXPECT_EQ(cast<Instruction>(TileShift1)->getParent(), Tile1->getBody());
1556   EXPECT_EQ(TileShift1->getOperand(1), Tile1->getIndVar());
1557   auto *TileScale1 = cast<MulOperator>(TileShift1->getOperand(0));
1558   EXPECT_EQ(cast<Instruction>(TileScale1)->getParent(), Tile1->getBody());
1559   EXPECT_EQ(TileScale1->getOperand(0), TileSize1);
1560   EXPECT_EQ(TileScale1->getOperand(1), Floor1->getIndVar());
1561 }
1562 
1563 TEST_F(OpenMPIRBuilderTest, TileSingleLoopCounts) {
1564   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1565   OpenMPIRBuilder OMPBuilder(*M);
1566   OMPBuilder.initialize();
1567   IRBuilder<> Builder(BB);
1568 
1569   // Create a loop, tile it, and extract its trip count. All input values are
1570   // constant and IRBuilder evaluates all-constant arithmetic inplace, such that
1571   // the floor trip count itself will be a ConstantInt. Unfortunately we cannot
1572   // do the same for the tile loop.
1573   auto GetFloorCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1574                            bool IsSigned, bool InclusiveStop,
1575                            int64_t TileSize) -> uint64_t {
1576     OpenMPIRBuilder::LocationDescription Loc(Builder.saveIP(), DL);
1577     Type *LCTy = Type::getInt16Ty(Ctx);
1578     Value *StartVal = ConstantInt::get(LCTy, Start);
1579     Value *StopVal = ConstantInt::get(LCTy, Stop);
1580     Value *StepVal = ConstantInt::get(LCTy, Step);
1581 
1582     // Generate a loop.
1583     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1584     CanonicalLoopInfo *Loop =
1585         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1586                                        StepVal, IsSigned, InclusiveStop);
1587 
1588     // Tile the loop.
1589     Value *TileSizeVal = ConstantInt::get(LCTy, TileSize);
1590     std::vector<CanonicalLoopInfo *> GenLoops =
1591         OMPBuilder.tileLoops(Loc.DL, {Loop}, {TileSizeVal});
1592 
1593     // Set the insertion pointer to after loop, where the next loop will be
1594     // emitted.
1595     Builder.restoreIP(Loop->getAfterIP());
1596 
1597     // Extract the trip count.
1598     CanonicalLoopInfo *FloorLoop = GenLoops[0];
1599     Value *FloorTripCount = FloorLoop->getTripCount();
1600     return cast<ConstantInt>(FloorTripCount)->getValue().getZExtValue();
1601   };
1602 
1603   // Empty iteration domain.
1604   EXPECT_EQ(GetFloorCount(0, 0, 1, false, false, 7), 0u);
1605   EXPECT_EQ(GetFloorCount(0, -1, 1, false, true, 7), 0u);
1606   EXPECT_EQ(GetFloorCount(-1, -1, -1, true, false, 7), 0u);
1607   EXPECT_EQ(GetFloorCount(-1, 0, -1, true, true, 7), 0u);
1608   EXPECT_EQ(GetFloorCount(-1, -1, 3, true, false, 7), 0u);
1609 
1610   // Only complete tiles.
1611   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1612   EXPECT_EQ(GetFloorCount(0, 14, 1, false, false, 7), 2u);
1613   EXPECT_EQ(GetFloorCount(1, 15, 1, false, false, 7), 2u);
1614   EXPECT_EQ(GetFloorCount(0, -14, -1, true, false, 7), 2u);
1615   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, true, 7), 2u);
1616   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 2, 3, false, false, 7), 2u);
1617 
1618   // Only a partial tile.
1619   EXPECT_EQ(GetFloorCount(0, 1, 1, false, false, 7), 1u);
1620   EXPECT_EQ(GetFloorCount(0, 6, 1, false, false, 7), 1u);
1621   EXPECT_EQ(GetFloorCount(-1, 1, 3, true, false, 7), 1u);
1622   EXPECT_EQ(GetFloorCount(-1, -2, -1, true, false, 7), 1u);
1623   EXPECT_EQ(GetFloorCount(0, 2, 3, false, false, 7), 1u);
1624 
1625   // Complete and partial tiles.
1626   EXPECT_EQ(GetFloorCount(0, 13, 1, false, false, 7), 2u);
1627   EXPECT_EQ(GetFloorCount(0, 15, 1, false, false, 7), 3u);
1628   EXPECT_EQ(GetFloorCount(-1, -14, -1, true, false, 7), 2u);
1629   EXPECT_EQ(GetFloorCount(0, 3 * 7 * 5 - 1, 3, false, false, 7), 5u);
1630   EXPECT_EQ(GetFloorCount(-1, -3 * 7 * 5, -3, true, false, 7), 5u);
1631 
1632   // Close to 16-bit integer range.
1633   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 1), 0xFFFFu);
1634   EXPECT_EQ(GetFloorCount(0, 0xFFFF, 1, false, false, 7), 0xFFFFu / 7 + 1);
1635   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, true, 7), 0xFFFFu / 7 + 1);
1636   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 7), 0xFFFFu / 7 + 1);
1637   EXPECT_EQ(GetFloorCount(-0x7FFF, 0x7FFF, 1, true, true, 7), 0xFFFFu / 7 + 1);
1638   EXPECT_EQ(GetFloorCount(0, 0xFFFE, 1, false, false, 0xFFFF), 1u);
1639   EXPECT_EQ(GetFloorCount(-0x8000, 0x7FFF, 1, true, false, 0xFFFF), 1u);
1640 
1641   // Finalize the function.
1642   Builder.CreateRetVoid();
1643   OMPBuilder.finalize();
1644 
1645   EXPECT_FALSE(verifyModule(*M, &errs()));
1646 }
1647 
1648 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) {
1649   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1650   OpenMPIRBuilder OMPBuilder(*M);
1651   OMPBuilder.initialize();
1652   IRBuilder<> Builder(BB);
1653   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1654 
1655   Type *LCTy = Type::getInt32Ty(Ctx);
1656   Value *StartVal = ConstantInt::get(LCTy, 10);
1657   Value *StopVal = ConstantInt::get(LCTy, 52);
1658   Value *StepVal = ConstantInt::get(LCTy, 2);
1659   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1660 
1661   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1662       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1663       /*IsSigned=*/false, /*InclusiveStop=*/false);
1664 
1665   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1666   InsertPointTy AllocaIP = Builder.saveIP();
1667 
1668   CLI = OMPBuilder.createStaticWorkshareLoop(Loc, CLI, AllocaIP,
1669                                              /*NeedsBarrier=*/true);
1670   auto AllocaIter = BB->begin();
1671   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1672   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1673   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1674   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1675   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1676   EXPECT_NE(PLastIter, nullptr);
1677   EXPECT_NE(PLowerBound, nullptr);
1678   EXPECT_NE(PUpperBound, nullptr);
1679   EXPECT_NE(PStride, nullptr);
1680 
1681   auto PreheaderIter = CLI->getPreheader()->begin();
1682   ASSERT_GE(
1683       std::distance(CLI->getPreheader()->begin(), CLI->getPreheader()->end()),
1684       7);
1685   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1686   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1687   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1688   ASSERT_NE(LowerBoundStore, nullptr);
1689   ASSERT_NE(UpperBoundStore, nullptr);
1690   ASSERT_NE(StrideStore, nullptr);
1691 
1692   auto *OrigLowerBound =
1693       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1694   auto *OrigUpperBound =
1695       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1696   auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1697   ASSERT_NE(OrigLowerBound, nullptr);
1698   ASSERT_NE(OrigUpperBound, nullptr);
1699   ASSERT_NE(OrigStride, nullptr);
1700   EXPECT_EQ(OrigLowerBound->getValue(), 0);
1701   EXPECT_EQ(OrigUpperBound->getValue(), 20);
1702   EXPECT_EQ(OrigStride->getValue(), 1);
1703 
1704   // Check that the loop IV is updated to account for the lower bound returned
1705   // by the OpenMP runtime call.
1706   BinaryOperator *Add = dyn_cast<BinaryOperator>(&CLI->getBody()->front());
1707   EXPECT_EQ(Add->getOperand(0), CLI->getIndVar());
1708   auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1));
1709   ASSERT_NE(LoadedLowerBound, nullptr);
1710   EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound);
1711 
1712   // Check that the trip count is updated to account for the lower and upper
1713   // bounds return by the OpenMP runtime call.
1714   auto *AddOne = dyn_cast<Instruction>(CLI->getTripCount());
1715   ASSERT_NE(AddOne, nullptr);
1716   ASSERT_TRUE(AddOne->isBinaryOp());
1717   auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1));
1718   ASSERT_NE(One, nullptr);
1719   EXPECT_EQ(One->getValue(), 1);
1720   auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0));
1721   ASSERT_NE(Difference, nullptr);
1722   ASSERT_TRUE(Difference->isBinaryOp());
1723   EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound);
1724   auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0));
1725   ASSERT_NE(LoadedUpperBound, nullptr);
1726   EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound);
1727 
1728   // The original loop iterator should only be used in the condition, in the
1729   // increment and in the statement that adds the lower bound to it.
1730   Value *IV = CLI->getIndVar();
1731   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1732 
1733   // The exit block should contain the "fini" call and the barrier call,
1734   // plus the call to obtain the thread ID.
1735   BasicBlock *ExitBlock = CLI->getExit();
1736   size_t NumCallsInExitBlock =
1737       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1738   EXPECT_EQ(NumCallsInExitBlock, 3u);
1739 }
1740 
1741 TEST_P(OpenMPIRBuilderTestWithParams, DynamicWorkShareLoop) {
1742   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1743   OpenMPIRBuilder OMPBuilder(*M);
1744   OMPBuilder.initialize();
1745   IRBuilder<> Builder(BB);
1746   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1747 
1748   omp::OMPScheduleType SchedType = GetParam();
1749   uint32_t ChunkSize = 1;
1750   switch (SchedType & ~omp::OMPScheduleType::ModifierMask) {
1751   case omp::OMPScheduleType::DynamicChunked:
1752   case omp::OMPScheduleType::GuidedChunked:
1753     ChunkSize = 7;
1754     break;
1755   case omp::OMPScheduleType::Auto:
1756   case omp::OMPScheduleType::Runtime:
1757     ChunkSize = 1;
1758     break;
1759   default:
1760     assert(0 && "unknown type for this test");
1761     break;
1762   }
1763 
1764   Type *LCTy = Type::getInt32Ty(Ctx);
1765   Value *StartVal = ConstantInt::get(LCTy, 10);
1766   Value *StopVal = ConstantInt::get(LCTy, 52);
1767   Value *StepVal = ConstantInt::get(LCTy, 2);
1768   Value *ChunkVal = ConstantInt::get(LCTy, ChunkSize);
1769   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1770 
1771   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1772       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1773       /*IsSigned=*/false, /*InclusiveStop=*/false);
1774 
1775   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1776   InsertPointTy AllocaIP = Builder.saveIP();
1777 
1778   // Collect all the info from CLI, as it isn't usable after the call to
1779   // createDynamicWorkshareLoop.
1780   InsertPointTy AfterIP = CLI->getAfterIP();
1781   BasicBlock *Preheader = CLI->getPreheader();
1782   BasicBlock *ExitBlock = CLI->getExit();
1783   Value *IV = CLI->getIndVar();
1784 
1785   InsertPointTy EndIP =
1786       OMPBuilder.createDynamicWorkshareLoop(Loc, CLI, AllocaIP, SchedType,
1787                                             /*NeedsBarrier=*/true, ChunkVal);
1788   // The returned value should be the "after" point.
1789   ASSERT_EQ(EndIP.getBlock(), AfterIP.getBlock());
1790   ASSERT_EQ(EndIP.getPoint(), AfterIP.getPoint());
1791 
1792   auto AllocaIter = BB->begin();
1793   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1794   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1795   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1796   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1797   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1798   EXPECT_NE(PLastIter, nullptr);
1799   EXPECT_NE(PLowerBound, nullptr);
1800   EXPECT_NE(PUpperBound, nullptr);
1801   EXPECT_NE(PStride, nullptr);
1802 
1803   auto PreheaderIter = Preheader->begin();
1804   ASSERT_GE(std::distance(Preheader->begin(), Preheader->end()), 6);
1805   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1806   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1807   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1808   ASSERT_NE(LowerBoundStore, nullptr);
1809   ASSERT_NE(UpperBoundStore, nullptr);
1810   ASSERT_NE(StrideStore, nullptr);
1811 
1812   CallInst *ThreadIdCall = dyn_cast<CallInst>(&*(PreheaderIter++));
1813   ASSERT_NE(ThreadIdCall, nullptr);
1814   EXPECT_EQ(ThreadIdCall->getCalledFunction()->getName(),
1815             "__kmpc_global_thread_num");
1816 
1817   CallInst *InitCall = dyn_cast<CallInst>(&*PreheaderIter);
1818 
1819   ASSERT_NE(InitCall, nullptr);
1820   EXPECT_EQ(InitCall->getCalledFunction()->getName(),
1821             "__kmpc_dispatch_init_4u");
1822   EXPECT_EQ(InitCall->getNumArgOperands(), 7U);
1823   EXPECT_EQ(InitCall->getArgOperand(6), ConstantInt::get(LCTy, ChunkSize));
1824   ConstantInt *SchedVal = cast<ConstantInt>(InitCall->getArgOperand(2));
1825   EXPECT_EQ(SchedVal->getValue(), static_cast<uint64_t>(SchedType));
1826 
1827   ConstantInt *OrigLowerBound =
1828       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1829   ConstantInt *OrigUpperBound =
1830       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1831   ConstantInt *OrigStride =
1832       dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1833   ASSERT_NE(OrigLowerBound, nullptr);
1834   ASSERT_NE(OrigUpperBound, nullptr);
1835   ASSERT_NE(OrigStride, nullptr);
1836   EXPECT_EQ(OrigLowerBound->getValue(), 1);
1837   EXPECT_EQ(OrigUpperBound->getValue(), 21);
1838   EXPECT_EQ(OrigStride->getValue(), 1);
1839 
1840   // The original loop iterator should only be used in the condition, in the
1841   // increment and in the statement that adds the lower bound to it.
1842   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1843 
1844   // The exit block should contain the barrier call, plus the call to obtain
1845   // the thread ID.
1846   size_t NumCallsInExitBlock =
1847       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1848   EXPECT_EQ(NumCallsInExitBlock, 2u);
1849 
1850   // Add a termination to our block and check that it is internally consistent.
1851   Builder.restoreIP(EndIP);
1852   Builder.CreateRetVoid();
1853   OMPBuilder.finalize();
1854   EXPECT_FALSE(verifyModule(*M, &errs()));
1855 }
1856 
1857 INSTANTIATE_TEST_SUITE_P(
1858     OpenMPWSLoopSchedulingTypes, OpenMPIRBuilderTestWithParams,
1859     ::testing::Values(omp::OMPScheduleType::DynamicChunked,
1860                       omp::OMPScheduleType::GuidedChunked,
1861                       omp::OMPScheduleType::Auto, omp::OMPScheduleType::Runtime,
1862                       omp::OMPScheduleType::DynamicChunked |
1863                           omp::OMPScheduleType::ModifierMonotonic,
1864                       omp::OMPScheduleType::DynamicChunked |
1865                           omp::OMPScheduleType::ModifierNonmonotonic,
1866                       omp::OMPScheduleType::GuidedChunked |
1867                           omp::OMPScheduleType::ModifierMonotonic,
1868                       omp::OMPScheduleType::GuidedChunked |
1869                           omp::OMPScheduleType::ModifierNonmonotonic,
1870                       omp::OMPScheduleType::Auto |
1871                           omp::OMPScheduleType::ModifierMonotonic,
1872                       omp::OMPScheduleType::Runtime |
1873                           omp::OMPScheduleType::ModifierMonotonic));
1874 
1875 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
1876   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1877   OpenMPIRBuilder OMPBuilder(*M);
1878   OMPBuilder.initialize();
1879   F->setName("func");
1880   IRBuilder<> Builder(BB);
1881 
1882   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1883 
1884   AllocaInst *PrivAI = nullptr;
1885 
1886   BasicBlock *EntryBB = nullptr;
1887   BasicBlock *ExitBB = nullptr;
1888   BasicBlock *ThenBB = nullptr;
1889 
1890   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1891                        BasicBlock &FiniBB) {
1892     if (AllocaIP.isSet())
1893       Builder.restoreIP(AllocaIP);
1894     else
1895       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1896     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1897     Builder.CreateStore(F->arg_begin(), PrivAI);
1898 
1899     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1900     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1901     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1902 
1903     Builder.restoreIP(CodeGenIP);
1904 
1905     // collect some info for checks later
1906     ExitBB = FiniBB.getUniqueSuccessor();
1907     ThenBB = Builder.GetInsertBlock();
1908     EntryBB = ThenBB->getUniquePredecessor();
1909 
1910     // simple instructions for body
1911     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
1912                                          "local.use");
1913     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1914   };
1915 
1916   auto FiniCB = [&](InsertPointTy IP) {
1917     BasicBlock *IPBB = IP.getBlock();
1918     EXPECT_NE(IPBB->end(), IP.getPoint());
1919   };
1920 
1921   Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
1922   Value *EntryBBTI = EntryBB->getTerminator();
1923   EXPECT_NE(EntryBBTI, nullptr);
1924   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1925   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1926   EXPECT_TRUE(EntryBr->isConditional());
1927   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1928   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1929   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1930 
1931   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1932   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1933 
1934   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
1935   EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
1936   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
1937   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
1938 
1939   CallInst *MasterEndCI = nullptr;
1940   for (auto &FI : *ThenBB) {
1941     Instruction *cur = &FI;
1942     if (isa<CallInst>(cur)) {
1943       MasterEndCI = cast<CallInst>(cur);
1944       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
1945         break;
1946       MasterEndCI = nullptr;
1947     }
1948   }
1949   EXPECT_NE(MasterEndCI, nullptr);
1950   EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
1951   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
1952   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
1953 }
1954 
1955 TEST_F(OpenMPIRBuilderTest, MaskedDirective) {
1956   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1957   OpenMPIRBuilder OMPBuilder(*M);
1958   OMPBuilder.initialize();
1959   F->setName("func");
1960   IRBuilder<> Builder(BB);
1961 
1962   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1963 
1964   AllocaInst *PrivAI = nullptr;
1965 
1966   BasicBlock *EntryBB = nullptr;
1967   BasicBlock *ExitBB = nullptr;
1968   BasicBlock *ThenBB = nullptr;
1969 
1970   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1971                        BasicBlock &FiniBB) {
1972     if (AllocaIP.isSet())
1973       Builder.restoreIP(AllocaIP);
1974     else
1975       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1976     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1977     Builder.CreateStore(F->arg_begin(), PrivAI);
1978 
1979     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1980     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1981     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1982 
1983     Builder.restoreIP(CodeGenIP);
1984 
1985     // collect some info for checks later
1986     ExitBB = FiniBB.getUniqueSuccessor();
1987     ThenBB = Builder.GetInsertBlock();
1988     EntryBB = ThenBB->getUniquePredecessor();
1989 
1990     // simple instructions for body
1991     Value *PrivLoad =
1992         Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI, "local.use");
1993     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1994   };
1995 
1996   auto FiniCB = [&](InsertPointTy IP) {
1997     BasicBlock *IPBB = IP.getBlock();
1998     EXPECT_NE(IPBB->end(), IP.getPoint());
1999   };
2000 
2001   Constant *Filter = ConstantInt::get(Type::getInt32Ty(M->getContext()), 0);
2002   Builder.restoreIP(
2003       OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, Filter));
2004   Value *EntryBBTI = EntryBB->getTerminator();
2005   EXPECT_NE(EntryBBTI, nullptr);
2006   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2007   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2008   EXPECT_TRUE(EntryBr->isConditional());
2009   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2010   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2011   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2012 
2013   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2014   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2015 
2016   CallInst *MaskedEntryCI = cast<CallInst>(CondInst->getOperand(0));
2017   EXPECT_EQ(MaskedEntryCI->getNumArgOperands(), 3U);
2018   EXPECT_EQ(MaskedEntryCI->getCalledFunction()->getName(), "__kmpc_masked");
2019   EXPECT_TRUE(isa<GlobalVariable>(MaskedEntryCI->getArgOperand(0)));
2020 
2021   CallInst *MaskedEndCI = nullptr;
2022   for (auto &FI : *ThenBB) {
2023     Instruction *cur = &FI;
2024     if (isa<CallInst>(cur)) {
2025       MaskedEndCI = cast<CallInst>(cur);
2026       if (MaskedEndCI->getCalledFunction()->getName() == "__kmpc_end_masked")
2027         break;
2028       MaskedEndCI = nullptr;
2029     }
2030   }
2031   EXPECT_NE(MaskedEndCI, nullptr);
2032   EXPECT_EQ(MaskedEndCI->getNumArgOperands(), 2U);
2033   EXPECT_TRUE(isa<GlobalVariable>(MaskedEndCI->getArgOperand(0)));
2034   EXPECT_EQ(MaskedEndCI->getArgOperand(1), MaskedEntryCI->getArgOperand(1));
2035 }
2036 
2037 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
2038   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2039   OpenMPIRBuilder OMPBuilder(*M);
2040   OMPBuilder.initialize();
2041   F->setName("func");
2042   IRBuilder<> Builder(BB);
2043 
2044   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2045 
2046   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2047 
2048   BasicBlock *EntryBB = nullptr;
2049 
2050   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2051                        BasicBlock &FiniBB) {
2052     // collect some info for checks later
2053     EntryBB = FiniBB.getUniquePredecessor();
2054 
2055     // actual start for bodyCB
2056     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2057     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2058     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2059     EXPECT_EQ(EntryBB, CodeGenIPBB);
2060 
2061     // body begin
2062     Builder.restoreIP(CodeGenIP);
2063     Builder.CreateStore(F->arg_begin(), PrivAI);
2064     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
2065                                          "local.use");
2066     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2067   };
2068 
2069   auto FiniCB = [&](InsertPointTy IP) {
2070     BasicBlock *IPBB = IP.getBlock();
2071     EXPECT_NE(IPBB->end(), IP.getPoint());
2072   };
2073 
2074   Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
2075                                               "testCRT", nullptr));
2076 
2077   Value *EntryBBTI = EntryBB->getTerminator();
2078   EXPECT_EQ(EntryBBTI, nullptr);
2079 
2080   CallInst *CriticalEntryCI = nullptr;
2081   for (auto &EI : *EntryBB) {
2082     Instruction *cur = &EI;
2083     if (isa<CallInst>(cur)) {
2084       CriticalEntryCI = cast<CallInst>(cur);
2085       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
2086         break;
2087       CriticalEntryCI = nullptr;
2088     }
2089   }
2090   EXPECT_NE(CriticalEntryCI, nullptr);
2091   EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
2092   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
2093   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
2094 
2095   CallInst *CriticalEndCI = nullptr;
2096   for (auto &FI : *EntryBB) {
2097     Instruction *cur = &FI;
2098     if (isa<CallInst>(cur)) {
2099       CriticalEndCI = cast<CallInst>(cur);
2100       if (CriticalEndCI->getCalledFunction()->getName() ==
2101           "__kmpc_end_critical")
2102         break;
2103       CriticalEndCI = nullptr;
2104     }
2105   }
2106   EXPECT_NE(CriticalEndCI, nullptr);
2107   EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
2108   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
2109   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
2110   PointerType *CriticalNamePtrTy =
2111       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
2112   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
2113   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
2114 }
2115 
2116 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
2117   OpenMPIRBuilder OMPBuilder(*M);
2118   OMPBuilder.initialize();
2119   F->setName("func");
2120   IRBuilder<> Builder(BB);
2121 
2122   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2123 
2124   IntegerType* Int32 = Type::getInt32Ty(M->getContext());
2125   AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
2126 	AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
2127 
2128   BasicBlock *EntryBB = BB;
2129 
2130   OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress,
2131                                       PrivAddress, Int32, /*BranchtoEnd*/ true);
2132 
2133   BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
2134 
2135   EXPECT_NE(EntryBr, nullptr);
2136   EXPECT_TRUE(EntryBr->isConditional());
2137 
2138   BasicBlock* NotMasterBB = EntryBr->getSuccessor(0);
2139   BasicBlock* CopyinEnd = EntryBr->getSuccessor(1);
2140   CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
2141 
2142   EXPECT_NE(CMP, nullptr);
2143   EXPECT_NE(NotMasterBB, nullptr);
2144   EXPECT_NE(CopyinEnd, nullptr);
2145 
2146   BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
2147   EXPECT_NE(NotMasterBr, nullptr);
2148   EXPECT_FALSE(NotMasterBr->isConditional());
2149   EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
2150 }
2151 
2152 TEST_F(OpenMPIRBuilderTest, SingleDirective) {
2153   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2154   OpenMPIRBuilder OMPBuilder(*M);
2155   OMPBuilder.initialize();
2156   F->setName("func");
2157   IRBuilder<> Builder(BB);
2158 
2159   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2160 
2161   AllocaInst *PrivAI = nullptr;
2162 
2163   BasicBlock *EntryBB = nullptr;
2164   BasicBlock *ExitBB = nullptr;
2165   BasicBlock *ThenBB = nullptr;
2166 
2167   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2168                        BasicBlock &FiniBB) {
2169     if (AllocaIP.isSet())
2170       Builder.restoreIP(AllocaIP);
2171     else
2172       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
2173     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2174     Builder.CreateStore(F->arg_begin(), PrivAI);
2175 
2176     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
2177     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
2178     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
2179 
2180     Builder.restoreIP(CodeGenIP);
2181 
2182     // collect some info for checks later
2183     ExitBB = FiniBB.getUniqueSuccessor();
2184     ThenBB = Builder.GetInsertBlock();
2185     EntryBB = ThenBB->getUniquePredecessor();
2186 
2187     // simple instructions for body
2188     Value *PrivLoad = Builder.CreateLoad(PrivAI->getAllocatedType(), PrivAI,
2189                                          "local.use");
2190     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2191   };
2192 
2193   auto FiniCB = [&](InsertPointTy IP) {
2194     BasicBlock *IPBB = IP.getBlock();
2195     EXPECT_NE(IPBB->end(), IP.getPoint());
2196   };
2197 
2198   Builder.restoreIP(
2199       OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
2200   Value *EntryBBTI = EntryBB->getTerminator();
2201   EXPECT_NE(EntryBBTI, nullptr);
2202   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
2203   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
2204   EXPECT_TRUE(EntryBr->isConditional());
2205   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
2206   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
2207   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
2208 
2209   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
2210   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
2211 
2212   CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
2213   EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
2214   EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
2215   EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
2216 
2217   CallInst *SingleEndCI = nullptr;
2218   for (auto &FI : *ThenBB) {
2219     Instruction *cur = &FI;
2220     if (isa<CallInst>(cur)) {
2221       SingleEndCI = cast<CallInst>(cur);
2222       if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
2223         break;
2224       SingleEndCI = nullptr;
2225     }
2226   }
2227   EXPECT_NE(SingleEndCI, nullptr);
2228   EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
2229   EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
2230   EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
2231 }
2232 
2233 TEST_F(OpenMPIRBuilderTest, OMPAtomicReadFlt) {
2234   OpenMPIRBuilder OMPBuilder(*M);
2235   OMPBuilder.initialize();
2236   F->setName("func");
2237   IRBuilder<> Builder(BB);
2238 
2239   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2240 
2241   Type *Float32 = Type::getFloatTy(M->getContext());
2242   AllocaInst *XVal = Builder.CreateAlloca(Float32);
2243   XVal->setName("AtomicVar");
2244   AllocaInst *VVal = Builder.CreateAlloca(Float32);
2245   VVal->setName("AtomicRead");
2246   AtomicOrdering AO = AtomicOrdering::Monotonic;
2247   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2248   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2249 
2250   Builder.restoreIP(OMPBuilder.createAtomicRead(Loc, X, V, AO));
2251 
2252   IntegerType *IntCastTy =
2253       IntegerType::get(M->getContext(), Float32->getScalarSizeInBits());
2254 
2255   BitCastInst *CastFrmFlt = cast<BitCastInst>(VVal->getNextNode());
2256   EXPECT_EQ(CastFrmFlt->getSrcTy(), Float32->getPointerTo());
2257   EXPECT_EQ(CastFrmFlt->getDestTy(), IntCastTy->getPointerTo());
2258   EXPECT_EQ(CastFrmFlt->getOperand(0), XVal);
2259 
2260   LoadInst *AtomicLoad = cast<LoadInst>(CastFrmFlt->getNextNode());
2261   EXPECT_TRUE(AtomicLoad->isAtomic());
2262   EXPECT_EQ(AtomicLoad->getPointerOperand(), CastFrmFlt);
2263 
2264   BitCastInst *CastToFlt = cast<BitCastInst>(AtomicLoad->getNextNode());
2265   EXPECT_EQ(CastToFlt->getSrcTy(), IntCastTy);
2266   EXPECT_EQ(CastToFlt->getDestTy(), Float32);
2267   EXPECT_EQ(CastToFlt->getOperand(0), AtomicLoad);
2268 
2269   StoreInst *StoreofAtomic = cast<StoreInst>(CastToFlt->getNextNode());
2270   EXPECT_EQ(StoreofAtomic->getValueOperand(), CastToFlt);
2271   EXPECT_EQ(StoreofAtomic->getPointerOperand(), VVal);
2272 
2273   Builder.CreateRetVoid();
2274   OMPBuilder.finalize();
2275   EXPECT_FALSE(verifyModule(*M, &errs()));
2276 }
2277 
2278 TEST_F(OpenMPIRBuilderTest, OMPAtomicReadInt) {
2279   OpenMPIRBuilder OMPBuilder(*M);
2280   OMPBuilder.initialize();
2281   F->setName("func");
2282   IRBuilder<> Builder(BB);
2283 
2284   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2285 
2286   IntegerType *Int32 = Type::getInt32Ty(M->getContext());
2287   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2288   XVal->setName("AtomicVar");
2289   AllocaInst *VVal = Builder.CreateAlloca(Int32);
2290   VVal->setName("AtomicRead");
2291   AtomicOrdering AO = AtomicOrdering::Monotonic;
2292   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2293   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2294 
2295   BasicBlock *EntryBB = BB;
2296 
2297   Builder.restoreIP(OMPBuilder.createAtomicRead(Loc, X, V, AO));
2298   LoadInst *AtomicLoad = nullptr;
2299   StoreInst *StoreofAtomic = nullptr;
2300 
2301   for (Instruction &Cur : *EntryBB) {
2302     if (isa<LoadInst>(Cur)) {
2303       AtomicLoad = cast<LoadInst>(&Cur);
2304       if (AtomicLoad->getPointerOperand() == XVal)
2305         continue;
2306       AtomicLoad = nullptr;
2307     } else if (isa<StoreInst>(Cur)) {
2308       StoreofAtomic = cast<StoreInst>(&Cur);
2309       if (StoreofAtomic->getPointerOperand() == VVal)
2310         continue;
2311       StoreofAtomic = nullptr;
2312     }
2313   }
2314 
2315   EXPECT_NE(AtomicLoad, nullptr);
2316   EXPECT_TRUE(AtomicLoad->isAtomic());
2317 
2318   EXPECT_NE(StoreofAtomic, nullptr);
2319   EXPECT_EQ(StoreofAtomic->getValueOperand(), AtomicLoad);
2320 
2321   Builder.CreateRetVoid();
2322   OMPBuilder.finalize();
2323 
2324   EXPECT_FALSE(verifyModule(*M, &errs()));
2325 }
2326 
2327 TEST_F(OpenMPIRBuilderTest, OMPAtomicWriteFlt) {
2328   OpenMPIRBuilder OMPBuilder(*M);
2329   OMPBuilder.initialize();
2330   F->setName("func");
2331   IRBuilder<> Builder(BB);
2332 
2333   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2334 
2335   LLVMContext &Ctx = M->getContext();
2336   Type *Float32 = Type::getFloatTy(Ctx);
2337   AllocaInst *XVal = Builder.CreateAlloca(Float32);
2338   XVal->setName("AtomicVar");
2339   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2340   AtomicOrdering AO = AtomicOrdering::Monotonic;
2341   Constant *ValToWrite = ConstantFP::get(Float32, 1.0);
2342 
2343   Builder.restoreIP(OMPBuilder.createAtomicWrite(Loc, X, ValToWrite, AO));
2344 
2345   IntegerType *IntCastTy =
2346       IntegerType::get(M->getContext(), Float32->getScalarSizeInBits());
2347 
2348   BitCastInst *CastFrmFlt = cast<BitCastInst>(XVal->getNextNode());
2349   EXPECT_EQ(CastFrmFlt->getSrcTy(), Float32->getPointerTo());
2350   EXPECT_EQ(CastFrmFlt->getDestTy(), IntCastTy->getPointerTo());
2351   EXPECT_EQ(CastFrmFlt->getOperand(0), XVal);
2352 
2353   Value *ExprCast = Builder.CreateBitCast(ValToWrite, IntCastTy);
2354 
2355   StoreInst *StoreofAtomic = cast<StoreInst>(CastFrmFlt->getNextNode());
2356   EXPECT_EQ(StoreofAtomic->getValueOperand(), ExprCast);
2357   EXPECT_EQ(StoreofAtomic->getPointerOperand(), CastFrmFlt);
2358   EXPECT_TRUE(StoreofAtomic->isAtomic());
2359 
2360   Builder.CreateRetVoid();
2361   OMPBuilder.finalize();
2362   EXPECT_FALSE(verifyModule(*M, &errs()));
2363 }
2364 
2365 TEST_F(OpenMPIRBuilderTest, OMPAtomicWriteInt) {
2366   OpenMPIRBuilder OMPBuilder(*M);
2367   OMPBuilder.initialize();
2368   F->setName("func");
2369   IRBuilder<> Builder(BB);
2370 
2371   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2372 
2373   LLVMContext &Ctx = M->getContext();
2374   IntegerType *Int32 = Type::getInt32Ty(Ctx);
2375   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2376   XVal->setName("AtomicVar");
2377   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2378   AtomicOrdering AO = AtomicOrdering::Monotonic;
2379   ConstantInt *ValToWrite = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2380 
2381   BasicBlock *EntryBB = BB;
2382 
2383   Builder.restoreIP(OMPBuilder.createAtomicWrite(Loc, X, ValToWrite, AO));
2384 
2385   StoreInst *StoreofAtomic = nullptr;
2386 
2387   for (Instruction &Cur : *EntryBB) {
2388     if (isa<StoreInst>(Cur)) {
2389       StoreofAtomic = cast<StoreInst>(&Cur);
2390       if (StoreofAtomic->getPointerOperand() == XVal)
2391         continue;
2392       StoreofAtomic = nullptr;
2393     }
2394   }
2395 
2396   EXPECT_NE(StoreofAtomic, nullptr);
2397   EXPECT_TRUE(StoreofAtomic->isAtomic());
2398   EXPECT_EQ(StoreofAtomic->getValueOperand(), ValToWrite);
2399 
2400   Builder.CreateRetVoid();
2401   OMPBuilder.finalize();
2402   EXPECT_FALSE(verifyModule(*M, &errs()));
2403 }
2404 
2405 TEST_F(OpenMPIRBuilderTest, OMPAtomicUpdate) {
2406   OpenMPIRBuilder OMPBuilder(*M);
2407   OMPBuilder.initialize();
2408   F->setName("func");
2409   IRBuilder<> Builder(BB);
2410 
2411   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2412 
2413   IntegerType *Int32 = Type::getInt32Ty(M->getContext());
2414   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2415   XVal->setName("AtomicVar");
2416   Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Ctx), 0U), XVal);
2417   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2418   AtomicOrdering AO = AtomicOrdering::Monotonic;
2419   ConstantInt *ConstVal = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2420   Value *Expr = nullptr;
2421   AtomicRMWInst::BinOp RMWOp = AtomicRMWInst::Sub;
2422   bool IsXLHSInRHSPart = false;
2423 
2424   BasicBlock *EntryBB = BB;
2425   Instruction *AllocIP = EntryBB->getFirstNonPHI();
2426   Value *Sub = nullptr;
2427 
2428   auto UpdateOp = [&](Value *Atomic, IRBuilder<> &IRB) {
2429     Sub = IRB.CreateSub(ConstVal, Atomic);
2430     return Sub;
2431   };
2432   Builder.restoreIP(OMPBuilder.createAtomicUpdate(
2433       Builder, AllocIP, X, Expr, AO, RMWOp, UpdateOp, IsXLHSInRHSPart));
2434   BasicBlock *ContBB = EntryBB->getSingleSuccessor();
2435   BranchInst *ContTI = dyn_cast<BranchInst>(ContBB->getTerminator());
2436   EXPECT_NE(ContTI, nullptr);
2437   BasicBlock *EndBB = ContTI->getSuccessor(0);
2438   EXPECT_TRUE(ContTI->isConditional());
2439   EXPECT_EQ(ContTI->getSuccessor(1), ContBB);
2440   EXPECT_NE(EndBB, nullptr);
2441 
2442   PHINode *Phi = dyn_cast<PHINode>(&ContBB->front());
2443   EXPECT_NE(Phi, nullptr);
2444   EXPECT_EQ(Phi->getNumIncomingValues(), 2U);
2445   EXPECT_EQ(Phi->getIncomingBlock(0), EntryBB);
2446   EXPECT_EQ(Phi->getIncomingBlock(1), ContBB);
2447 
2448   EXPECT_EQ(Sub->getNumUses(), 1U);
2449   StoreInst *St = dyn_cast<StoreInst>(Sub->user_back());
2450   AllocaInst *UpdateTemp = dyn_cast<AllocaInst>(St->getPointerOperand());
2451 
2452   ExtractValueInst *ExVI1 =
2453       dyn_cast<ExtractValueInst>(Phi->getIncomingValueForBlock(ContBB));
2454   EXPECT_NE(ExVI1, nullptr);
2455   AtomicCmpXchgInst *CmpExchg =
2456       dyn_cast<AtomicCmpXchgInst>(ExVI1->getAggregateOperand());
2457   EXPECT_NE(CmpExchg, nullptr);
2458   EXPECT_EQ(CmpExchg->getPointerOperand(), XVal);
2459   EXPECT_EQ(CmpExchg->getCompareOperand(), Phi);
2460   EXPECT_EQ(CmpExchg->getSuccessOrdering(), AtomicOrdering::Monotonic);
2461 
2462   LoadInst *Ld = dyn_cast<LoadInst>(CmpExchg->getNewValOperand());
2463   EXPECT_NE(Ld, nullptr);
2464   EXPECT_EQ(UpdateTemp, Ld->getPointerOperand());
2465 
2466   Builder.CreateRetVoid();
2467   OMPBuilder.finalize();
2468   EXPECT_FALSE(verifyModule(*M, &errs()));
2469 }
2470 
2471 TEST_F(OpenMPIRBuilderTest, OMPAtomicCapture) {
2472   OpenMPIRBuilder OMPBuilder(*M);
2473   OMPBuilder.initialize();
2474   F->setName("func");
2475   IRBuilder<> Builder(BB);
2476 
2477   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2478 
2479   LLVMContext &Ctx = M->getContext();
2480   IntegerType *Int32 = Type::getInt32Ty(Ctx);
2481   AllocaInst *XVal = Builder.CreateAlloca(Int32);
2482   XVal->setName("AtomicVar");
2483   AllocaInst *VVal = Builder.CreateAlloca(Int32);
2484   VVal->setName("AtomicCapTar");
2485   StoreInst *Init =
2486       Builder.CreateStore(ConstantInt::get(Type::getInt32Ty(Ctx), 0U), XVal);
2487 
2488   OpenMPIRBuilder::AtomicOpValue X = {XVal, false, false};
2489   OpenMPIRBuilder::AtomicOpValue V = {VVal, false, false};
2490   AtomicOrdering AO = AtomicOrdering::Monotonic;
2491   ConstantInt *Expr = ConstantInt::get(Type::getInt32Ty(Ctx), 1U);
2492   AtomicRMWInst::BinOp RMWOp = AtomicRMWInst::Add;
2493   bool IsXLHSInRHSPart = true;
2494   bool IsPostfixUpdate = true;
2495   bool UpdateExpr = true;
2496 
2497   BasicBlock *EntryBB = BB;
2498   Instruction *AllocIP = EntryBB->getFirstNonPHI();
2499 
2500   // integer update - not used
2501   auto UpdateOp = [&](Value *Atomic, IRBuilder<> &IRB) { return nullptr; };
2502 
2503   Builder.restoreIP(OMPBuilder.createAtomicCapture(
2504       Builder, AllocIP, X, V, Expr, AO, RMWOp, UpdateOp, UpdateExpr,
2505       IsPostfixUpdate, IsXLHSInRHSPart));
2506   EXPECT_EQ(EntryBB->getParent()->size(), 1U);
2507   AtomicRMWInst *ARWM = dyn_cast<AtomicRMWInst>(Init->getNextNode());
2508   EXPECT_NE(ARWM, nullptr);
2509   EXPECT_EQ(ARWM->getPointerOperand(), XVal);
2510   EXPECT_EQ(ARWM->getOperation(), RMWOp);
2511   StoreInst *St = dyn_cast<StoreInst>(ARWM->user_back());
2512   EXPECT_NE(St, nullptr);
2513   EXPECT_EQ(St->getPointerOperand(), VVal);
2514 
2515   Builder.CreateRetVoid();
2516   OMPBuilder.finalize();
2517   EXPECT_FALSE(verifyModule(*M, &errs()));
2518 }
2519 
2520 TEST_F(OpenMPIRBuilderTest, CreateSections) {
2521   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
2522   using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
2523   OpenMPIRBuilder OMPBuilder(*M);
2524   OMPBuilder.initialize();
2525   F->setName("func");
2526   IRBuilder<> Builder(BB);
2527 
2528   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
2529   llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
2530   llvm::SmallVector<BasicBlock *, 4> CaseBBs;
2531 
2532   BasicBlock *SwitchBB = nullptr;
2533   BasicBlock *ForExitBB = nullptr;
2534   BasicBlock *ForIncBB = nullptr;
2535   AllocaInst *PrivAI = nullptr;
2536   SwitchInst *Switch = nullptr;
2537 
2538   unsigned NumBodiesGenerated = 0;
2539   unsigned NumFiniCBCalls = 0;
2540   PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
2541 
2542   auto FiniCB = [&](InsertPointTy IP) {
2543     ++NumFiniCBCalls;
2544     BasicBlock *IPBB = IP.getBlock();
2545     EXPECT_NE(IPBB->end(), IP.getPoint());
2546   };
2547 
2548   auto SectionCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2549                        BasicBlock &FiniBB) {
2550     ++NumBodiesGenerated;
2551     CaseBBs.push_back(CodeGenIP.getBlock());
2552     SwitchBB = CodeGenIP.getBlock()->getSinglePredecessor();
2553     Builder.restoreIP(CodeGenIP);
2554     Builder.CreateStore(F->arg_begin(), PrivAI);
2555     Value *PrivLoad =
2556         Builder.CreateLoad(F->arg_begin()->getType(), PrivAI, "local.alloca");
2557     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
2558     Builder.CreateBr(&FiniBB);
2559     ForIncBB =
2560         CodeGenIP.getBlock()->getSinglePredecessor()->getSingleSuccessor();
2561   };
2562   auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2563                    llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2564     // TODO: Privatization not implemented yet
2565     return CodeGenIP;
2566   };
2567 
2568   SectionCBVector.push_back(SectionCB);
2569   SectionCBVector.push_back(SectionCB);
2570 
2571   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
2572                                     F->getEntryBlock().getFirstInsertionPt());
2573   Builder.restoreIP(OMPBuilder.createSections(Loc, AllocaIP, SectionCBVector,
2574                                               PrivCB, FiniCB, false, false));
2575   Builder.CreateRetVoid(); // Required at the end of the function
2576 
2577   // Switch BB's predecessor is loop condition BB, whose successor at index 1 is
2578   // loop's exit BB
2579   ForExitBB =
2580       SwitchBB->getSinglePredecessor()->getTerminator()->getSuccessor(1);
2581   EXPECT_NE(ForExitBB, nullptr);
2582 
2583   EXPECT_NE(PrivAI, nullptr);
2584   Function *OutlinedFn = PrivAI->getFunction();
2585   EXPECT_EQ(F, OutlinedFn);
2586   EXPECT_FALSE(verifyModule(*M, &errs()));
2587   EXPECT_EQ(OutlinedFn->arg_size(), 1U);
2588   EXPECT_EQ(OutlinedFn->getBasicBlockList().size(), size_t(11));
2589 
2590   BasicBlock *LoopPreheaderBB =
2591       OutlinedFn->getEntryBlock().getSingleSuccessor();
2592   // loop variables are 5 - lower bound, upper bound, stride, islastiter, and
2593   // iterator/counter
2594   bool FoundForInit = false;
2595   for (Instruction &Inst : *LoopPreheaderBB) {
2596     if (isa<CallInst>(Inst)) {
2597       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2598           "__kmpc_for_static_init_4u") {
2599         FoundForInit = true;
2600       }
2601     }
2602   }
2603   EXPECT_EQ(FoundForInit, true);
2604 
2605   bool FoundForExit = false;
2606   bool FoundBarrier = false;
2607   for (Instruction &Inst : *ForExitBB) {
2608     if (isa<CallInst>(Inst)) {
2609       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2610           "__kmpc_for_static_fini") {
2611         FoundForExit = true;
2612       }
2613       if (cast<CallInst>(&Inst)->getCalledFunction()->getName() ==
2614           "__kmpc_barrier") {
2615         FoundBarrier = true;
2616       }
2617       if (FoundForExit && FoundBarrier)
2618         break;
2619     }
2620   }
2621   EXPECT_EQ(FoundForExit, true);
2622   EXPECT_EQ(FoundBarrier, true);
2623 
2624   EXPECT_NE(SwitchBB, nullptr);
2625   EXPECT_NE(SwitchBB->getTerminator(), nullptr);
2626   EXPECT_EQ(isa<SwitchInst>(SwitchBB->getTerminator()), true);
2627   Switch = cast<SwitchInst>(SwitchBB->getTerminator());
2628   EXPECT_EQ(Switch->getNumCases(), 2U);
2629   EXPECT_NE(ForIncBB, nullptr);
2630   EXPECT_EQ(Switch->getSuccessor(0), ForIncBB);
2631 
2632   EXPECT_EQ(CaseBBs.size(), 2U);
2633   for (auto *&CaseBB : CaseBBs) {
2634     EXPECT_EQ(CaseBB->getParent(), OutlinedFn);
2635     EXPECT_EQ(CaseBB->getSingleSuccessor(), ForExitBB);
2636   }
2637 
2638   ASSERT_EQ(NumBodiesGenerated, 2U);
2639   ASSERT_EQ(NumFiniCBCalls, 1U);
2640 }
2641 
2642 TEST_F(OpenMPIRBuilderTest, CreateOffloadMaptypes) {
2643   OpenMPIRBuilder OMPBuilder(*M);
2644   OMPBuilder.initialize();
2645 
2646   IRBuilder<> Builder(BB);
2647 
2648   SmallVector<uint64_t> Mappings = {0, 1};
2649   GlobalVariable *OffloadMaptypesGlobal =
2650       OMPBuilder.createOffloadMaptypes(Mappings, "offload_maptypes");
2651   EXPECT_FALSE(M->global_empty());
2652   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_maptypes");
2653   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
2654   EXPECT_TRUE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
2655   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
2656   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
2657   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
2658   EXPECT_TRUE(isa<ConstantDataArray>(Initializer));
2659   ConstantDataArray *MappingInit = dyn_cast<ConstantDataArray>(Initializer);
2660   EXPECT_EQ(MappingInit->getNumElements(), Mappings.size());
2661   EXPECT_TRUE(MappingInit->getType()->getElementType()->isIntegerTy(64));
2662   Constant *CA = ConstantDataArray::get(Builder.getContext(), Mappings);
2663   EXPECT_EQ(MappingInit, CA);
2664 }
2665 
2666 TEST_F(OpenMPIRBuilderTest, CreateOffloadMapnames) {
2667   OpenMPIRBuilder OMPBuilder(*M);
2668   OMPBuilder.initialize();
2669 
2670   IRBuilder<> Builder(BB);
2671 
2672   Constant *Cst1 = OMPBuilder.getOrCreateSrcLocStr("array1", "file1", 2, 5);
2673   Constant *Cst2 = OMPBuilder.getOrCreateSrcLocStr("array2", "file1", 3, 5);
2674   SmallVector<llvm::Constant *> Names = {Cst1, Cst2};
2675 
2676   GlobalVariable *OffloadMaptypesGlobal =
2677       OMPBuilder.createOffloadMapnames(Names, "offload_mapnames");
2678   EXPECT_FALSE(M->global_empty());
2679   EXPECT_EQ(OffloadMaptypesGlobal->getName(), "offload_mapnames");
2680   EXPECT_TRUE(OffloadMaptypesGlobal->isConstant());
2681   EXPECT_FALSE(OffloadMaptypesGlobal->hasGlobalUnnamedAddr());
2682   EXPECT_TRUE(OffloadMaptypesGlobal->hasPrivateLinkage());
2683   EXPECT_TRUE(OffloadMaptypesGlobal->hasInitializer());
2684   Constant *Initializer = OffloadMaptypesGlobal->getInitializer();
2685   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(0)->stripPointerCasts()));
2686   EXPECT_TRUE(isa<Constant>(Initializer->getOperand(1)->stripPointerCasts()));
2687 
2688   GlobalVariable *Name1Gbl =
2689       cast<GlobalVariable>(Initializer->getOperand(0)->stripPointerCasts());
2690   EXPECT_TRUE(isa<ConstantDataArray>(Name1Gbl->getInitializer()));
2691   ConstantDataArray *Name1GblCA =
2692       dyn_cast<ConstantDataArray>(Name1Gbl->getInitializer());
2693   EXPECT_EQ(Name1GblCA->getAsCString(), ";file1;array1;2;5;;");
2694 
2695   GlobalVariable *Name2Gbl =
2696       cast<GlobalVariable>(Initializer->getOperand(1)->stripPointerCasts());
2697   EXPECT_TRUE(isa<ConstantDataArray>(Name2Gbl->getInitializer()));
2698   ConstantDataArray *Name2GblCA =
2699       dyn_cast<ConstantDataArray>(Name2Gbl->getInitializer());
2700   EXPECT_EQ(Name2GblCA->getAsCString(), ";file1;array2;3;5;;");
2701 
2702   EXPECT_TRUE(Initializer->getType()->getArrayElementType()->isPointerTy());
2703   EXPECT_EQ(Initializer->getType()->getArrayNumElements(), Names.size());
2704 }
2705 
2706 } // namespace
2707