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