• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 class OpenMPIRBuilderTest : public testing::Test {
27 protected:
SetUp()28   void SetUp() override {
29     M.reset(new Module("MyModule", Ctx));
30     FunctionType *FTy =
31         FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
32                           /*isVarArg=*/false);
33     F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
34     BB = BasicBlock::Create(Ctx, "", F);
35 
36     DIBuilder DIB(*M);
37     auto File = DIB.createFile("test.dbg", "/src", llvm::None,
38                                Optional<StringRef>("/src/test.dbg"));
39     auto CU =
40         DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0);
41     auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
42     auto SP = DIB.createFunction(
43         CU, "foo", "", File, 1, Type, 1, DINode::FlagZero,
44         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
45     F->setSubprogram(SP);
46     auto Scope = DIB.createLexicalBlockFile(SP, File, 0);
47     DIB.finalize();
48     DL = DebugLoc::get(3, 7, Scope);
49   }
50 
TearDown()51   void TearDown() override {
52     BB = nullptr;
53     M.reset();
54   }
55 
56   LLVMContext Ctx;
57   std::unique_ptr<Module> M;
58   Function *F;
59   BasicBlock *BB;
60   DebugLoc DL;
61 };
62 
63 // Returns the value stored in the given allocation. Returns null if the given
64 // value is not a result of an allocation, if no value is stored or if there is
65 // more than one store.
findStoredValue(Value * AllocaValue)66 static Value *findStoredValue(Value *AllocaValue) {
67   Instruction *Alloca = dyn_cast<AllocaInst>(AllocaValue);
68   if (!Alloca)
69     return nullptr;
70   StoreInst *Store = nullptr;
71   for (Use &U : Alloca->uses()) {
72     if (auto *CandidateStore = dyn_cast<StoreInst>(U.getUser())) {
73       EXPECT_EQ(Store, nullptr);
74       Store = CandidateStore;
75     }
76   }
77   if (!Store)
78     return nullptr;
79   return Store->getValueOperand();
80 }
81 
TEST_F(OpenMPIRBuilderTest,CreateBarrier)82 TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
83   OpenMPIRBuilder OMPBuilder(*M);
84   OMPBuilder.initialize();
85 
86   IRBuilder<> Builder(BB);
87 
88   OMPBuilder.createBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
89   EXPECT_TRUE(M->global_empty());
90   EXPECT_EQ(M->size(), 1U);
91   EXPECT_EQ(F->size(), 1U);
92   EXPECT_EQ(BB->size(), 0U);
93 
94   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
95   OMPBuilder.createBarrier(Loc, OMPD_for);
96   EXPECT_FALSE(M->global_empty());
97   EXPECT_EQ(M->size(), 3U);
98   EXPECT_EQ(F->size(), 1U);
99   EXPECT_EQ(BB->size(), 2U);
100 
101   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
102   EXPECT_NE(GTID, nullptr);
103   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
104   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
105   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
106   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
107 
108   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
109   EXPECT_NE(Barrier, nullptr);
110   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
111   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
112   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
113   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
114 
115   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
116 
117   Builder.CreateUnreachable();
118   EXPECT_FALSE(verifyModule(*M, &errs()));
119 }
120 
TEST_F(OpenMPIRBuilderTest,CreateCancel)121 TEST_F(OpenMPIRBuilderTest, CreateCancel) {
122   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
123   OpenMPIRBuilder OMPBuilder(*M);
124   OMPBuilder.initialize();
125 
126   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
127   new UnreachableInst(Ctx, CBB);
128   auto FiniCB = [&](InsertPointTy IP) {
129     ASSERT_NE(IP.getBlock(), nullptr);
130     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
131     BranchInst::Create(CBB, IP.getBlock());
132   };
133   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
134 
135   IRBuilder<> Builder(BB);
136 
137   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
138   auto NewIP = OMPBuilder.createCancel(Loc, nullptr, OMPD_parallel);
139   Builder.restoreIP(NewIP);
140   EXPECT_FALSE(M->global_empty());
141   EXPECT_EQ(M->size(), 3U);
142   EXPECT_EQ(F->size(), 4U);
143   EXPECT_EQ(BB->size(), 4U);
144 
145   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
146   EXPECT_NE(GTID, nullptr);
147   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
148   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
149   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
150   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
151 
152   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
153   EXPECT_NE(Cancel, nullptr);
154   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
155   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
156   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
157   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
158   EXPECT_EQ(Cancel->getNumUses(), 1U);
159   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
160   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
161   EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
162   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
163   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
164             1U);
165   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
166             CBB);
167 
168   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
169 
170   OMPBuilder.popFinalizationCB();
171 
172   Builder.CreateUnreachable();
173   EXPECT_FALSE(verifyModule(*M, &errs()));
174 }
175 
TEST_F(OpenMPIRBuilderTest,CreateCancelIfCond)176 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
177   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
178   OpenMPIRBuilder OMPBuilder(*M);
179   OMPBuilder.initialize();
180 
181   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
182   new UnreachableInst(Ctx, CBB);
183   auto FiniCB = [&](InsertPointTy IP) {
184     ASSERT_NE(IP.getBlock(), nullptr);
185     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
186     BranchInst::Create(CBB, IP.getBlock());
187   };
188   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
189 
190   IRBuilder<> Builder(BB);
191 
192   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
193   auto NewIP = OMPBuilder.createCancel(Loc, Builder.getTrue(), OMPD_parallel);
194   Builder.restoreIP(NewIP);
195   EXPECT_FALSE(M->global_empty());
196   EXPECT_EQ(M->size(), 3U);
197   EXPECT_EQ(F->size(), 7U);
198   EXPECT_EQ(BB->size(), 1U);
199   ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
200   ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
201   BB = BB->getTerminator()->getSuccessor(0);
202   EXPECT_EQ(BB->size(), 4U);
203 
204 
205   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
206   EXPECT_NE(GTID, nullptr);
207   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
208   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
209   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
210   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
211 
212   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
213   EXPECT_NE(Cancel, nullptr);
214   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
215   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
216   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
217   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
218   EXPECT_EQ(Cancel->getNumUses(), 1U);
219   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
220   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
221   EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
222   EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock());
223   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
224   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
225             1U);
226   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
227             CBB);
228 
229   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
230 
231   OMPBuilder.popFinalizationCB();
232 
233   Builder.CreateUnreachable();
234   EXPECT_FALSE(verifyModule(*M, &errs()));
235 }
236 
TEST_F(OpenMPIRBuilderTest,CreateCancelBarrier)237 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
238   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
239   OpenMPIRBuilder OMPBuilder(*M);
240   OMPBuilder.initialize();
241 
242   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
243   new UnreachableInst(Ctx, CBB);
244   auto FiniCB = [&](InsertPointTy IP) {
245     ASSERT_NE(IP.getBlock(), nullptr);
246     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
247     BranchInst::Create(CBB, IP.getBlock());
248   };
249   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
250 
251   IRBuilder<> Builder(BB);
252 
253   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
254   auto NewIP = OMPBuilder.createBarrier(Loc, OMPD_for);
255   Builder.restoreIP(NewIP);
256   EXPECT_FALSE(M->global_empty());
257   EXPECT_EQ(M->size(), 3U);
258   EXPECT_EQ(F->size(), 4U);
259   EXPECT_EQ(BB->size(), 4U);
260 
261   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
262   EXPECT_NE(GTID, nullptr);
263   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
264   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
265   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
266   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
267 
268   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
269   EXPECT_NE(Barrier, nullptr);
270   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
271   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
272   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
273   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
274   EXPECT_EQ(Barrier->getNumUses(), 1U);
275   Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
276   EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
277   EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
278   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
279   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
280             1U);
281   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
282             CBB);
283 
284   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
285 
286   OMPBuilder.popFinalizationCB();
287 
288   Builder.CreateUnreachable();
289   EXPECT_FALSE(verifyModule(*M, &errs()));
290 }
291 
TEST_F(OpenMPIRBuilderTest,DbgLoc)292 TEST_F(OpenMPIRBuilderTest, DbgLoc) {
293   OpenMPIRBuilder OMPBuilder(*M);
294   OMPBuilder.initialize();
295   F->setName("func");
296 
297   IRBuilder<> Builder(BB);
298 
299   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
300   OMPBuilder.createBarrier(Loc, OMPD_for);
301   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
302   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
303   EXPECT_EQ(GTID->getDebugLoc(), DL);
304   EXPECT_EQ(Barrier->getDebugLoc(), DL);
305   EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
306   if (!isa<GlobalVariable>(Barrier->getOperand(0)))
307     return;
308   GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
309   EXPECT_TRUE(Ident->hasInitializer());
310   if (!Ident->hasInitializer())
311     return;
312   Constant *Initializer = Ident->getInitializer();
313   EXPECT_TRUE(
314       isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
315   GlobalVariable *SrcStrGlob =
316       cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
317   if (!SrcStrGlob)
318     return;
319   EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
320   ConstantDataArray *SrcSrc =
321       dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
322   if (!SrcSrc)
323     return;
324   EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;");
325 }
326 
TEST_F(OpenMPIRBuilderTest,ParallelSimple)327 TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
328   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
329   OpenMPIRBuilder OMPBuilder(*M);
330   OMPBuilder.initialize();
331   F->setName("func");
332   IRBuilder<> Builder(BB);
333 
334   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
335 
336   AllocaInst *PrivAI = nullptr;
337 
338   unsigned NumBodiesGenerated = 0;
339   unsigned NumPrivatizedVars = 0;
340   unsigned NumFinalizationPoints = 0;
341 
342   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
343                        BasicBlock &ContinuationIP) {
344     ++NumBodiesGenerated;
345 
346     Builder.restoreIP(AllocaIP);
347     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
348     Builder.CreateStore(F->arg_begin(), PrivAI);
349 
350     Builder.restoreIP(CodeGenIP);
351     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
352     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
353     Instruction *ThenTerm, *ElseTerm;
354     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
355                                   &ThenTerm, &ElseTerm);
356 
357     Builder.SetInsertPoint(ThenTerm);
358     Builder.CreateBr(&ContinuationIP);
359     ThenTerm->eraseFromParent();
360   };
361 
362   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
363                     Value &Orig, Value &Inner,
364                     Value *&ReplacementValue) -> InsertPointTy {
365     ++NumPrivatizedVars;
366 
367     if (!isa<AllocaInst>(Orig)) {
368       EXPECT_EQ(&Orig, F->arg_begin());
369       ReplacementValue = &Inner;
370       return CodeGenIP;
371     }
372 
373     // Since the original value is an allocation, it has a pointer type and
374     // therefore no additional wrapping should happen.
375     EXPECT_EQ(&Orig, &Inner);
376 
377     // Trivial copy (=firstprivate).
378     Builder.restoreIP(AllocaIP);
379     Type *VTy = Inner.getType()->getPointerElementType();
380     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
381     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
382     Builder.restoreIP(CodeGenIP);
383     Builder.CreateStore(V, ReplacementValue);
384     return CodeGenIP;
385   };
386 
387   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
388 
389   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
390                                     F->getEntryBlock().getFirstInsertionPt());
391   IRBuilder<>::InsertPoint AfterIP =
392       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
393                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
394   EXPECT_EQ(NumBodiesGenerated, 1U);
395   EXPECT_EQ(NumPrivatizedVars, 1U);
396   EXPECT_EQ(NumFinalizationPoints, 1U);
397 
398   Builder.restoreIP(AfterIP);
399   Builder.CreateRetVoid();
400 
401   OMPBuilder.finalize();
402 
403   EXPECT_NE(PrivAI, nullptr);
404   Function *OutlinedFn = PrivAI->getFunction();
405   EXPECT_NE(F, OutlinedFn);
406   EXPECT_FALSE(verifyModule(*M, &errs()));
407   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
408   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
409   EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
410   EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
411 
412   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
413   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
414 
415   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
416   EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
417   User *Usr = OutlinedFn->user_back();
418   ASSERT_TRUE(isa<ConstantExpr>(Usr));
419   CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
420   ASSERT_NE(ForkCI, nullptr);
421 
422   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
423   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
424   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
425   EXPECT_EQ(ForkCI->getArgOperand(1),
426             ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
427   EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
428   EXPECT_EQ(findStoredValue(ForkCI->getArgOperand(3)), F->arg_begin());
429 }
430 
TEST_F(OpenMPIRBuilderTest,ParallelNested)431 TEST_F(OpenMPIRBuilderTest, ParallelNested) {
432   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
433   OpenMPIRBuilder OMPBuilder(*M);
434   OMPBuilder.initialize();
435   F->setName("func");
436   IRBuilder<> Builder(BB);
437 
438   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
439 
440   unsigned NumInnerBodiesGenerated = 0;
441   unsigned NumOuterBodiesGenerated = 0;
442   unsigned NumFinalizationPoints = 0;
443 
444   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
445                             BasicBlock &ContinuationIP) {
446     ++NumInnerBodiesGenerated;
447   };
448 
449   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
450                     Value &Orig, Value &Inner,
451                     Value *&ReplacementValue) -> InsertPointTy {
452     // Trivial copy (=firstprivate).
453     Builder.restoreIP(AllocaIP);
454     Type *VTy = Inner.getType()->getPointerElementType();
455     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
456     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
457     Builder.restoreIP(CodeGenIP);
458     Builder.CreateStore(V, ReplacementValue);
459     return CodeGenIP;
460   };
461 
462   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
463 
464   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
465                             BasicBlock &ContinuationIP) {
466     ++NumOuterBodiesGenerated;
467     Builder.restoreIP(CodeGenIP);
468     BasicBlock *CGBB = CodeGenIP.getBlock();
469     BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint());
470     CGBB->getTerminator()->eraseFromParent();
471     ;
472 
473     IRBuilder<>::InsertPoint AfterIP = OMPBuilder.createParallel(
474         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
475         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
476 
477     Builder.restoreIP(AfterIP);
478     Builder.CreateBr(NewBB);
479   };
480 
481   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
482                                     F->getEntryBlock().getFirstInsertionPt());
483   IRBuilder<>::InsertPoint AfterIP =
484       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
485                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
486 
487   EXPECT_EQ(NumInnerBodiesGenerated, 1U);
488   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
489   EXPECT_EQ(NumFinalizationPoints, 2U);
490 
491   Builder.restoreIP(AfterIP);
492   Builder.CreateRetVoid();
493 
494   OMPBuilder.finalize();
495 
496   EXPECT_EQ(M->size(), 5U);
497   for (Function &OutlinedFn : *M) {
498     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
499       continue;
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(), 2U);
508 
509     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
510     User *Usr = OutlinedFn.user_back();
511     ASSERT_TRUE(isa<ConstantExpr>(Usr));
512     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
513     ASSERT_NE(ForkCI, nullptr);
514 
515     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
516     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
517     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
518     EXPECT_EQ(ForkCI->getArgOperand(1),
519               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
520     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
521   }
522 }
523 
TEST_F(OpenMPIRBuilderTest,ParallelNested2Inner)524 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) {
525   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
526   OpenMPIRBuilder OMPBuilder(*M);
527   OMPBuilder.initialize();
528   F->setName("func");
529   IRBuilder<> Builder(BB);
530 
531   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
532 
533   unsigned NumInnerBodiesGenerated = 0;
534   unsigned NumOuterBodiesGenerated = 0;
535   unsigned NumFinalizationPoints = 0;
536 
537   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
538                             BasicBlock &ContinuationIP) {
539     ++NumInnerBodiesGenerated;
540   };
541 
542   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
543                     Value &Orig, Value &Inner,
544                     Value *&ReplacementValue) -> InsertPointTy {
545     // Trivial copy (=firstprivate).
546     Builder.restoreIP(AllocaIP);
547     Type *VTy = Inner.getType()->getPointerElementType();
548     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
549     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
550     Builder.restoreIP(CodeGenIP);
551     Builder.CreateStore(V, ReplacementValue);
552     return CodeGenIP;
553   };
554 
555   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
556 
557   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
558                             BasicBlock &ContinuationIP) {
559     ++NumOuterBodiesGenerated;
560     Builder.restoreIP(CodeGenIP);
561     BasicBlock *CGBB = CodeGenIP.getBlock();
562     BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint());
563     BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt());
564     CGBB->getTerminator()->eraseFromParent();
565     ;
566     NewBB1->getTerminator()->eraseFromParent();
567     ;
568 
569     IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.createParallel(
570         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
571         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
572 
573     Builder.restoreIP(AfterIP1);
574     Builder.CreateBr(NewBB1);
575 
576     IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.createParallel(
577         InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB,
578         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
579 
580     Builder.restoreIP(AfterIP2);
581     Builder.CreateBr(NewBB2);
582   };
583 
584   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
585                                     F->getEntryBlock().getFirstInsertionPt());
586   IRBuilder<>::InsertPoint AfterIP =
587       OMPBuilder.createParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
588                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
589 
590   EXPECT_EQ(NumInnerBodiesGenerated, 2U);
591   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
592   EXPECT_EQ(NumFinalizationPoints, 3U);
593 
594   Builder.restoreIP(AfterIP);
595   Builder.CreateRetVoid();
596 
597   OMPBuilder.finalize();
598 
599   EXPECT_EQ(M->size(), 6U);
600   for (Function &OutlinedFn : *M) {
601     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
602       continue;
603     EXPECT_FALSE(verifyModule(*M, &errs()));
604     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
605     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
606     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
607     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
608 
609     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
610     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
611 
612     unsigned NumAllocas = 0;
613     for (Instruction &I : instructions(OutlinedFn))
614       NumAllocas += isa<AllocaInst>(I);
615     EXPECT_EQ(NumAllocas, 1U);
616 
617     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
618     User *Usr = OutlinedFn.user_back();
619     ASSERT_TRUE(isa<ConstantExpr>(Usr));
620     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
621     ASSERT_NE(ForkCI, nullptr);
622 
623     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
624     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
625     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
626     EXPECT_EQ(ForkCI->getArgOperand(1),
627               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
628     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
629   }
630 }
631 
TEST_F(OpenMPIRBuilderTest,ParallelIfCond)632 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
633   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
634   OpenMPIRBuilder OMPBuilder(*M);
635   OMPBuilder.initialize();
636   F->setName("func");
637   IRBuilder<> Builder(BB);
638 
639   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
640 
641   AllocaInst *PrivAI = nullptr;
642 
643   unsigned NumBodiesGenerated = 0;
644   unsigned NumPrivatizedVars = 0;
645   unsigned NumFinalizationPoints = 0;
646 
647   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
648                        BasicBlock &ContinuationIP) {
649     ++NumBodiesGenerated;
650 
651     Builder.restoreIP(AllocaIP);
652     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
653     Builder.CreateStore(F->arg_begin(), PrivAI);
654 
655     Builder.restoreIP(CodeGenIP);
656     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
657     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
658     Instruction *ThenTerm, *ElseTerm;
659     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
660                                   &ThenTerm, &ElseTerm);
661 
662     Builder.SetInsertPoint(ThenTerm);
663     Builder.CreateBr(&ContinuationIP);
664     ThenTerm->eraseFromParent();
665   };
666 
667   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
668                     Value &Orig, Value &Inner,
669                     Value *&ReplacementValue) -> InsertPointTy {
670     ++NumPrivatizedVars;
671 
672     if (!isa<AllocaInst>(Orig)) {
673       EXPECT_EQ(&Orig, F->arg_begin());
674       ReplacementValue = &Inner;
675       return CodeGenIP;
676     }
677 
678     // Since the original value is an allocation, it has a pointer type and
679     // therefore no additional wrapping should happen.
680     EXPECT_EQ(&Orig, &Inner);
681 
682     // Trivial copy (=firstprivate).
683     Builder.restoreIP(AllocaIP);
684     Type *VTy = Inner.getType()->getPointerElementType();
685     Value *V = Builder.CreateLoad(VTy, &Inner, Orig.getName() + ".reload");
686     ReplacementValue = Builder.CreateAlloca(VTy, 0, Orig.getName() + ".copy");
687     Builder.restoreIP(CodeGenIP);
688     Builder.CreateStore(V, ReplacementValue);
689     return CodeGenIP;
690   };
691 
692   auto FiniCB = [&](InsertPointTy CodeGenIP) {
693     ++NumFinalizationPoints;
694     // No destructors.
695   };
696 
697   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
698                                     F->getEntryBlock().getFirstInsertionPt());
699   IRBuilder<>::InsertPoint AfterIP =
700       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
701                                 Builder.CreateIsNotNull(F->arg_begin()),
702                                 nullptr, OMP_PROC_BIND_default, false);
703 
704   EXPECT_EQ(NumBodiesGenerated, 1U);
705   EXPECT_EQ(NumPrivatizedVars, 1U);
706   EXPECT_EQ(NumFinalizationPoints, 1U);
707 
708   Builder.restoreIP(AfterIP);
709   Builder.CreateRetVoid();
710   OMPBuilder.finalize();
711 
712   EXPECT_NE(PrivAI, nullptr);
713   Function *OutlinedFn = PrivAI->getFunction();
714   EXPECT_NE(F, OutlinedFn);
715   EXPECT_FALSE(verifyModule(*M, &errs()));
716 
717   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
718   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
719 
720   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
721   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
722 
723   CallInst *DirectCI = nullptr;
724   CallInst *ForkCI = nullptr;
725   for (User *Usr : OutlinedFn->users()) {
726     if (isa<CallInst>(Usr)) {
727       ASSERT_EQ(DirectCI, nullptr);
728       DirectCI = cast<CallInst>(Usr);
729     } else {
730       ASSERT_TRUE(isa<ConstantExpr>(Usr));
731       ASSERT_EQ(Usr->getNumUses(), 1U);
732       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
733       ForkCI = cast<CallInst>(Usr->user_back());
734     }
735   }
736 
737   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
738   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
739   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
740   EXPECT_EQ(ForkCI->getArgOperand(1),
741             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
742   Value *StoredForkArg = findStoredValue(ForkCI->getArgOperand(3));
743   EXPECT_EQ(StoredForkArg, F->arg_begin());
744 
745   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
746   EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
747   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
748   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
749   Value *StoredDirectArg = findStoredValue(DirectCI->getArgOperand(2));
750   EXPECT_EQ(StoredDirectArg, F->arg_begin());
751 }
752 
TEST_F(OpenMPIRBuilderTest,ParallelCancelBarrier)753 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
754   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
755   OpenMPIRBuilder OMPBuilder(*M);
756   OMPBuilder.initialize();
757   F->setName("func");
758   IRBuilder<> Builder(BB);
759 
760   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
761 
762   unsigned NumBodiesGenerated = 0;
763   unsigned NumPrivatizedVars = 0;
764   unsigned NumFinalizationPoints = 0;
765 
766   CallInst *CheckedBarrier = nullptr;
767   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
768                        BasicBlock &ContinuationIP) {
769     ++NumBodiesGenerated;
770 
771     Builder.restoreIP(CodeGenIP);
772 
773     // Create three barriers, two cancel barriers but only one checked.
774     Function *CBFn, *BFn;
775 
776     Builder.restoreIP(
777         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel));
778 
779     CBFn = M->getFunction("__kmpc_cancel_barrier");
780     BFn = M->getFunction("__kmpc_barrier");
781     ASSERT_NE(CBFn, nullptr);
782     ASSERT_EQ(BFn, nullptr);
783     ASSERT_EQ(CBFn->getNumUses(), 1U);
784     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
785     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
786     CheckedBarrier = cast<CallInst>(CBFn->user_back());
787 
788     Builder.restoreIP(
789         OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel, true));
790     CBFn = M->getFunction("__kmpc_cancel_barrier");
791     BFn = M->getFunction("__kmpc_barrier");
792     ASSERT_NE(CBFn, nullptr);
793     ASSERT_NE(BFn, nullptr);
794     ASSERT_EQ(CBFn->getNumUses(), 1U);
795     ASSERT_EQ(BFn->getNumUses(), 1U);
796     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
797     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
798 
799     Builder.restoreIP(OMPBuilder.createBarrier(Builder.saveIP(), OMPD_parallel,
800                                                false, false));
801     ASSERT_EQ(CBFn->getNumUses(), 2U);
802     ASSERT_EQ(BFn->getNumUses(), 1U);
803     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
804     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
805     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
806   };
807 
808   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V, Value &,
809                     Value *&) -> InsertPointTy {
810     ++NumPrivatizedVars;
811     llvm_unreachable("No privatization callback call expected!");
812   };
813 
814   FunctionType *FakeDestructorTy =
815       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
816                         /*isVarArg=*/false);
817   auto *FakeDestructor = Function::Create(
818       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
819 
820   auto FiniCB = [&](InsertPointTy IP) {
821     ++NumFinalizationPoints;
822     Builder.restoreIP(IP);
823     Builder.CreateCall(FakeDestructor,
824                        {Builder.getInt32(NumFinalizationPoints)});
825   };
826 
827   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
828                                     F->getEntryBlock().getFirstInsertionPt());
829   IRBuilder<>::InsertPoint AfterIP =
830       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
831                                 Builder.CreateIsNotNull(F->arg_begin()),
832                                 nullptr, OMP_PROC_BIND_default, true);
833 
834   EXPECT_EQ(NumBodiesGenerated, 1U);
835   EXPECT_EQ(NumPrivatizedVars, 0U);
836   EXPECT_EQ(NumFinalizationPoints, 2U);
837   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
838 
839   Builder.restoreIP(AfterIP);
840   Builder.CreateRetVoid();
841   OMPBuilder.finalize();
842 
843   EXPECT_FALSE(verifyModule(*M, &errs()));
844 
845   BasicBlock *ExitBB = nullptr;
846   for (const User *Usr : FakeDestructor->users()) {
847     const CallInst *CI = dyn_cast<CallInst>(Usr);
848     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
849     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
850     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
851     if (ExitBB)
852       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
853     else
854       ExitBB = CI->getNextNode()->getSuccessor(0);
855     ASSERT_EQ(ExitBB->size(), 1U);
856     if (!isa<ReturnInst>(ExitBB->front())) {
857       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
858       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
859       ASSERT_TRUE(isa<ReturnInst>(
860           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
861     }
862   }
863 }
864 
TEST_F(OpenMPIRBuilderTest,ParallelForwardAsPointers)865 TEST_F(OpenMPIRBuilderTest, ParallelForwardAsPointers) {
866   OpenMPIRBuilder OMPBuilder(*M);
867   OMPBuilder.initialize();
868   F->setName("func");
869   IRBuilder<> Builder(BB);
870   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
871   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
872 
873   Type *I32Ty = Type::getInt32Ty(M->getContext());
874   Type *I32PtrTy = Type::getInt32PtrTy(M->getContext());
875   Type *StructTy = StructType::get(I32Ty, I32PtrTy);
876   Type *StructPtrTy = StructTy->getPointerTo();
877   Type *VoidTy = Type::getVoidTy(M->getContext());
878   FunctionCallee RetI32Func = M->getOrInsertFunction("ret_i32", I32Ty);
879   FunctionCallee TakeI32Func =
880       M->getOrInsertFunction("take_i32", VoidTy, I32Ty);
881   FunctionCallee RetI32PtrFunc = M->getOrInsertFunction("ret_i32ptr", I32PtrTy);
882   FunctionCallee TakeI32PtrFunc =
883       M->getOrInsertFunction("take_i32ptr", VoidTy, I32PtrTy);
884   FunctionCallee RetStructFunc = M->getOrInsertFunction("ret_struct", StructTy);
885   FunctionCallee TakeStructFunc =
886       M->getOrInsertFunction("take_struct", VoidTy, StructTy);
887   FunctionCallee RetStructPtrFunc =
888       M->getOrInsertFunction("ret_structptr", StructPtrTy);
889   FunctionCallee TakeStructPtrFunc =
890       M->getOrInsertFunction("take_structPtr", VoidTy, StructPtrTy);
891   Value *I32Val = Builder.CreateCall(RetI32Func);
892   Value *I32PtrVal = Builder.CreateCall(RetI32PtrFunc);
893   Value *StructVal = Builder.CreateCall(RetStructFunc);
894   Value *StructPtrVal = Builder.CreateCall(RetStructPtrFunc);
895 
896   Instruction *Internal;
897   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
898                        BasicBlock &ContinuationBB) {
899     IRBuilder<>::InsertPointGuard Guard(Builder);
900     Builder.restoreIP(CodeGenIP);
901     Internal = Builder.CreateCall(TakeI32Func, I32Val);
902     Builder.CreateCall(TakeI32PtrFunc, I32PtrVal);
903     Builder.CreateCall(TakeStructFunc, StructVal);
904     Builder.CreateCall(TakeStructPtrFunc, StructPtrVal);
905   };
906   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &,
907                     Value &Inner, Value *&ReplacementValue) {
908     ReplacementValue = &Inner;
909     return CodeGenIP;
910   };
911   auto FiniCB = [](InsertPointTy) {};
912 
913   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
914                                     F->getEntryBlock().getFirstInsertionPt());
915   IRBuilder<>::InsertPoint AfterIP =
916       OMPBuilder.createParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
917                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
918   Builder.restoreIP(AfterIP);
919   Builder.CreateRetVoid();
920 
921   OMPBuilder.finalize();
922 
923   EXPECT_FALSE(verifyModule(*M, &errs()));
924   Function *OutlinedFn = Internal->getFunction();
925 
926   Type *Arg2Type = OutlinedFn->getArg(2)->getType();
927   EXPECT_TRUE(Arg2Type->isPointerTy());
928   EXPECT_EQ(Arg2Type->getPointerElementType(), I32Ty);
929 
930   // Arguments that need to be passed through pointers and reloaded will get
931   // used earlier in the functions and therefore will appear first in the
932   // argument list after outlining.
933   Type *Arg3Type = OutlinedFn->getArg(3)->getType();
934   EXPECT_TRUE(Arg3Type->isPointerTy());
935   EXPECT_EQ(Arg3Type->getPointerElementType(), StructTy);
936 
937   Type *Arg4Type = OutlinedFn->getArg(4)->getType();
938   EXPECT_EQ(Arg4Type, I32PtrTy);
939 
940   Type *Arg5Type = OutlinedFn->getArg(5)->getType();
941   EXPECT_EQ(Arg5Type, StructPtrTy);
942 }
943 
TEST_F(OpenMPIRBuilderTest,CanonicalLoopSimple)944 TEST_F(OpenMPIRBuilderTest, CanonicalLoopSimple) {
945   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
946   OpenMPIRBuilder OMPBuilder(*M);
947   OMPBuilder.initialize();
948   IRBuilder<> Builder(BB);
949   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
950   Value *TripCount = F->getArg(0);
951 
952   unsigned NumBodiesGenerated = 0;
953   auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {
954     NumBodiesGenerated += 1;
955 
956     Builder.restoreIP(CodeGenIP);
957 
958     Value *Cmp = Builder.CreateICmpEQ(LC, TripCount);
959     Instruction *ThenTerm, *ElseTerm;
960     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
961                                   &ThenTerm, &ElseTerm);
962   };
963 
964   CanonicalLoopInfo *Loop =
965       OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, TripCount);
966 
967   Builder.restoreIP(Loop->getAfterIP());
968   ReturnInst *RetInst = Builder.CreateRetVoid();
969   OMPBuilder.finalize();
970 
971   Loop->assertOK();
972   EXPECT_FALSE(verifyModule(*M, &errs()));
973 
974   EXPECT_EQ(NumBodiesGenerated, 1U);
975 
976   // Verify control flow structure (in addition to Loop->assertOK()).
977   EXPECT_EQ(Loop->getPreheader()->getSinglePredecessor(), &F->getEntryBlock());
978   EXPECT_EQ(Loop->getAfter(), Builder.GetInsertBlock());
979 
980   Instruction *IndVar = Loop->getIndVar();
981   EXPECT_TRUE(isa<PHINode>(IndVar));
982   EXPECT_EQ(IndVar->getType(), TripCount->getType());
983   EXPECT_EQ(IndVar->getParent(), Loop->getHeader());
984 
985   EXPECT_EQ(Loop->getTripCount(), TripCount);
986 
987   BasicBlock *Body = Loop->getBody();
988   Instruction *CmpInst = &Body->getInstList().front();
989   EXPECT_TRUE(isa<ICmpInst>(CmpInst));
990   EXPECT_EQ(CmpInst->getOperand(0), IndVar);
991 
992   BasicBlock *LatchPred = Loop->getLatch()->getSinglePredecessor();
993   EXPECT_TRUE(llvm::all_of(successors(Body), [=](BasicBlock *SuccBB) {
994     return SuccBB->getSingleSuccessor() == LatchPred;
995   }));
996 
997   EXPECT_EQ(&Loop->getAfter()->front(), RetInst);
998 }
999 
TEST_F(OpenMPIRBuilderTest,CanonicalLoopBounds)1000 TEST_F(OpenMPIRBuilderTest, CanonicalLoopBounds) {
1001   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1002   OpenMPIRBuilder OMPBuilder(*M);
1003   OMPBuilder.initialize();
1004   IRBuilder<> Builder(BB);
1005 
1006   // Check the trip count is computed correctly. We generate the canonical loop
1007   // but rely on the IRBuilder's constant folder to compute the final result
1008   // since all inputs are constant. To verify overflow situations, limit the
1009   // trip count / loop counter widths to 16 bits.
1010   auto EvalTripCount = [&](int64_t Start, int64_t Stop, int64_t Step,
1011                            bool IsSigned, bool InclusiveStop) -> int64_t {
1012     OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1013     Type *LCTy = Type::getInt16Ty(Ctx);
1014     Value *StartVal = ConstantInt::get(LCTy, Start);
1015     Value *StopVal = ConstantInt::get(LCTy, Stop);
1016     Value *StepVal = ConstantInt::get(LCTy, Step);
1017     auto LoopBodyGenCB = [&](InsertPointTy CodeGenIP, llvm::Value *LC) {};
1018     CanonicalLoopInfo *Loop =
1019         OMPBuilder.createCanonicalLoop(Loc, LoopBodyGenCB, StartVal, StopVal,
1020                                        StepVal, IsSigned, InclusiveStop);
1021     Loop->assertOK();
1022     Builder.restoreIP(Loop->getAfterIP());
1023     Value *TripCount = Loop->getTripCount();
1024     return cast<ConstantInt>(TripCount)->getValue().getZExtValue();
1025   };
1026 
1027   ASSERT_EQ(EvalTripCount(0, 0, 1, false, false), 0);
1028   ASSERT_EQ(EvalTripCount(0, 1, 2, false, false), 1);
1029   ASSERT_EQ(EvalTripCount(0, 42, 1, false, false), 42);
1030   ASSERT_EQ(EvalTripCount(0, 42, 2, false, false), 21);
1031   ASSERT_EQ(EvalTripCount(21, 42, 1, false, false), 21);
1032   ASSERT_EQ(EvalTripCount(0, 5, 5, false, false), 1);
1033   ASSERT_EQ(EvalTripCount(0, 9, 5, false, false), 2);
1034   ASSERT_EQ(EvalTripCount(0, 11, 5, false, false), 3);
1035   ASSERT_EQ(EvalTripCount(0, 0xFFFF, 1, false, false), 0xFFFF);
1036   ASSERT_EQ(EvalTripCount(0xFFFF, 0, 1, false, false), 0);
1037   ASSERT_EQ(EvalTripCount(0xFFFE, 0xFFFF, 1, false, false), 1);
1038   ASSERT_EQ(EvalTripCount(0, 0xFFFF, 0x100, false, false), 0x100);
1039   ASSERT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFF, false, false), 1);
1040 
1041   ASSERT_EQ(EvalTripCount(0, 6, 5, false, false), 2);
1042   ASSERT_EQ(EvalTripCount(0, 0xFFFF, 0xFFFE, false, false), 2);
1043   ASSERT_EQ(EvalTripCount(0, 0, 1, false, true), 1);
1044   ASSERT_EQ(EvalTripCount(0, 0, 0xFFFF, false, true), 1);
1045   ASSERT_EQ(EvalTripCount(0, 0xFFFE, 1, false, true), 0xFFFF);
1046   ASSERT_EQ(EvalTripCount(0, 0xFFFE, 2, false, true), 0x8000);
1047 
1048   ASSERT_EQ(EvalTripCount(0, 0, -1, true, false), 0);
1049   ASSERT_EQ(EvalTripCount(0, 1, -1, true, true), 0);
1050   ASSERT_EQ(EvalTripCount(20, 5, -5, true, false), 3);
1051   ASSERT_EQ(EvalTripCount(20, 5, -5, true, true), 4);
1052   ASSERT_EQ(EvalTripCount(-4, -2, 2, true, false), 1);
1053   ASSERT_EQ(EvalTripCount(-4, -3, 2, true, false), 1);
1054   ASSERT_EQ(EvalTripCount(-4, -2, 2, true, true), 2);
1055 
1056   ASSERT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, false), 0x8000);
1057   ASSERT_EQ(EvalTripCount(INT16_MIN, 0, 1, true, true), 0x8001);
1058   ASSERT_EQ(EvalTripCount(INT16_MIN, 0x7FFF, 1, true, false), 0xFFFF);
1059   ASSERT_EQ(EvalTripCount(INT16_MIN + 1, 0x7FFF, 1, true, true), 0xFFFF);
1060   ASSERT_EQ(EvalTripCount(INT16_MIN, 0, 0x7FFF, true, false), 2);
1061   ASSERT_EQ(EvalTripCount(0x7FFF, 0, -1, true, false), 0x7FFF);
1062   ASSERT_EQ(EvalTripCount(0, INT16_MIN, -1, true, false), 0x8000);
1063   ASSERT_EQ(EvalTripCount(0, INT16_MIN, -16, true, false), 0x800);
1064   ASSERT_EQ(EvalTripCount(0x7FFF, INT16_MIN, -1, true, false), 0xFFFF);
1065   ASSERT_EQ(EvalTripCount(0x7FFF, 1, INT16_MIN, true, false), 1);
1066   ASSERT_EQ(EvalTripCount(0x7FFF, -1, INT16_MIN, true, true), 2);
1067 
1068   // Finalize the function and verify it.
1069   Builder.CreateRetVoid();
1070   OMPBuilder.finalize();
1071   EXPECT_FALSE(verifyModule(*M, &errs()));
1072 }
1073 
TEST_F(OpenMPIRBuilderTest,StaticWorkShareLoop)1074 TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) {
1075   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1076   OpenMPIRBuilder OMPBuilder(*M);
1077   OMPBuilder.initialize();
1078   IRBuilder<> Builder(BB);
1079   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1080 
1081   Type *LCTy = Type::getInt32Ty(Ctx);
1082   Value *StartVal = ConstantInt::get(LCTy, 10);
1083   Value *StopVal = ConstantInt::get(LCTy, 52);
1084   Value *StepVal = ConstantInt::get(LCTy, 2);
1085   auto LoopBodyGen = [&](InsertPointTy, llvm::Value *) {};
1086 
1087   CanonicalLoopInfo *CLI = OMPBuilder.createCanonicalLoop(
1088       Loc, LoopBodyGen, StartVal, StopVal, StepVal,
1089       /*IsSigned=*/false, /*InclusiveStop=*/false);
1090 
1091   Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
1092   InsertPointTy AllocaIP = Builder.saveIP();
1093 
1094   CLI = OMPBuilder.createStaticWorkshareLoop(Loc, CLI, AllocaIP,
1095                                              /*NeedsBarrier=*/true);
1096   auto AllocaIter = BB->begin();
1097   ASSERT_GE(std::distance(BB->begin(), BB->end()), 4);
1098   AllocaInst *PLastIter = dyn_cast<AllocaInst>(&*(AllocaIter++));
1099   AllocaInst *PLowerBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1100   AllocaInst *PUpperBound = dyn_cast<AllocaInst>(&*(AllocaIter++));
1101   AllocaInst *PStride = dyn_cast<AllocaInst>(&*(AllocaIter++));
1102   EXPECT_NE(PLastIter, nullptr);
1103   EXPECT_NE(PLowerBound, nullptr);
1104   EXPECT_NE(PUpperBound, nullptr);
1105   EXPECT_NE(PStride, nullptr);
1106 
1107   auto PreheaderIter = CLI->getPreheader()->begin();
1108   ASSERT_GE(
1109       std::distance(CLI->getPreheader()->begin(), CLI->getPreheader()->end()),
1110       7);
1111   StoreInst *LowerBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1112   StoreInst *UpperBoundStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1113   StoreInst *StrideStore = dyn_cast<StoreInst>(&*(PreheaderIter++));
1114   ASSERT_NE(LowerBoundStore, nullptr);
1115   ASSERT_NE(UpperBoundStore, nullptr);
1116   ASSERT_NE(StrideStore, nullptr);
1117 
1118   auto *OrigLowerBound =
1119       dyn_cast<ConstantInt>(LowerBoundStore->getValueOperand());
1120   auto *OrigUpperBound =
1121       dyn_cast<ConstantInt>(UpperBoundStore->getValueOperand());
1122   auto *OrigStride = dyn_cast<ConstantInt>(StrideStore->getValueOperand());
1123   ASSERT_NE(OrigLowerBound, nullptr);
1124   ASSERT_NE(OrigUpperBound, nullptr);
1125   ASSERT_NE(OrigStride, nullptr);
1126   EXPECT_EQ(OrigLowerBound->getValue(), 0);
1127   EXPECT_EQ(OrigUpperBound->getValue(), 20);
1128   EXPECT_EQ(OrigStride->getValue(), 1);
1129 
1130   // Check that the loop IV is updated to account for the lower bound returned
1131   // by the OpenMP runtime call.
1132   BinaryOperator *Add = dyn_cast<BinaryOperator>(&CLI->getBody()->front());
1133   EXPECT_EQ(Add->getOperand(0), CLI->getIndVar());
1134   auto *LoadedLowerBound = dyn_cast<LoadInst>(Add->getOperand(1));
1135   ASSERT_NE(LoadedLowerBound, nullptr);
1136   EXPECT_EQ(LoadedLowerBound->getPointerOperand(), PLowerBound);
1137 
1138   // Check that the trip count is updated to account for the lower and upper
1139   // bounds return by the OpenMP runtime call.
1140   auto *AddOne = dyn_cast<Instruction>(CLI->getTripCount());
1141   ASSERT_NE(AddOne, nullptr);
1142   ASSERT_TRUE(AddOne->isBinaryOp());
1143   auto *One = dyn_cast<ConstantInt>(AddOne->getOperand(1));
1144   ASSERT_NE(One, nullptr);
1145   EXPECT_EQ(One->getValue(), 1);
1146   auto *Difference = dyn_cast<Instruction>(AddOne->getOperand(0));
1147   ASSERT_NE(Difference, nullptr);
1148   ASSERT_TRUE(Difference->isBinaryOp());
1149   EXPECT_EQ(Difference->getOperand(1), LoadedLowerBound);
1150   auto *LoadedUpperBound = dyn_cast<LoadInst>(Difference->getOperand(0));
1151   ASSERT_NE(LoadedUpperBound, nullptr);
1152   EXPECT_EQ(LoadedUpperBound->getPointerOperand(), PUpperBound);
1153 
1154   // The original loop iterator should only be used in the condition, in the
1155   // increment and in the statement that adds the lower bound to it.
1156   Value *IV = CLI->getIndVar();
1157   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
1158 
1159   // The exit block should contain the "fini" call and the barrier call,
1160   // plus the call to obtain the thread ID.
1161   BasicBlock *ExitBlock = CLI->getExit();
1162   size_t NumCallsInExitBlock =
1163       count_if(*ExitBlock, [](Instruction &I) { return isa<CallInst>(I); });
1164   EXPECT_EQ(NumCallsInExitBlock, 3u);
1165 }
1166 
TEST_F(OpenMPIRBuilderTest,MasterDirective)1167 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
1168   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1169   OpenMPIRBuilder OMPBuilder(*M);
1170   OMPBuilder.initialize();
1171   F->setName("func");
1172   IRBuilder<> Builder(BB);
1173 
1174   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1175 
1176   AllocaInst *PrivAI = nullptr;
1177 
1178   BasicBlock *EntryBB = nullptr;
1179   BasicBlock *ExitBB = nullptr;
1180   BasicBlock *ThenBB = nullptr;
1181 
1182   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1183                        BasicBlock &FiniBB) {
1184     if (AllocaIP.isSet())
1185       Builder.restoreIP(AllocaIP);
1186     else
1187       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1188     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1189     Builder.CreateStore(F->arg_begin(), PrivAI);
1190 
1191     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1192     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1193     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1194 
1195     Builder.restoreIP(CodeGenIP);
1196 
1197     // collect some info for checks later
1198     ExitBB = FiniBB.getUniqueSuccessor();
1199     ThenBB = Builder.GetInsertBlock();
1200     EntryBB = ThenBB->getUniquePredecessor();
1201 
1202     // simple instructions for body
1203     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
1204     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1205   };
1206 
1207   auto FiniCB = [&](InsertPointTy IP) {
1208     BasicBlock *IPBB = IP.getBlock();
1209     EXPECT_NE(IPBB->end(), IP.getPoint());
1210   };
1211 
1212   Builder.restoreIP(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
1213   Value *EntryBBTI = EntryBB->getTerminator();
1214   EXPECT_NE(EntryBBTI, nullptr);
1215   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1216   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1217   EXPECT_TRUE(EntryBr->isConditional());
1218   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1219   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1220   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1221 
1222   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1223   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1224 
1225   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
1226   EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
1227   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
1228   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
1229 
1230   CallInst *MasterEndCI = nullptr;
1231   for (auto &FI : *ThenBB) {
1232     Instruction *cur = &FI;
1233     if (isa<CallInst>(cur)) {
1234       MasterEndCI = cast<CallInst>(cur);
1235       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
1236         break;
1237       MasterEndCI = nullptr;
1238     }
1239   }
1240   EXPECT_NE(MasterEndCI, nullptr);
1241   EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
1242   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
1243   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
1244 }
1245 
TEST_F(OpenMPIRBuilderTest,CriticalDirective)1246 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
1247   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1248   OpenMPIRBuilder OMPBuilder(*M);
1249   OMPBuilder.initialize();
1250   F->setName("func");
1251   IRBuilder<> Builder(BB);
1252 
1253   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1254 
1255   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1256 
1257   BasicBlock *EntryBB = nullptr;
1258 
1259   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1260                        BasicBlock &FiniBB) {
1261     // collect some info for checks later
1262     EntryBB = FiniBB.getUniquePredecessor();
1263 
1264     // actual start for bodyCB
1265     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1266     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1267     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1268     EXPECT_EQ(EntryBB, CodeGenIPBB);
1269 
1270     // body begin
1271     Builder.restoreIP(CodeGenIP);
1272     Builder.CreateStore(F->arg_begin(), PrivAI);
1273     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
1274     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1275   };
1276 
1277   auto FiniCB = [&](InsertPointTy IP) {
1278     BasicBlock *IPBB = IP.getBlock();
1279     EXPECT_NE(IPBB->end(), IP.getPoint());
1280   };
1281 
1282   Builder.restoreIP(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
1283                                               "testCRT", nullptr));
1284 
1285   Value *EntryBBTI = EntryBB->getTerminator();
1286   EXPECT_EQ(EntryBBTI, nullptr);
1287 
1288   CallInst *CriticalEntryCI = nullptr;
1289   for (auto &EI : *EntryBB) {
1290     Instruction *cur = &EI;
1291     if (isa<CallInst>(cur)) {
1292       CriticalEntryCI = cast<CallInst>(cur);
1293       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
1294         break;
1295       CriticalEntryCI = nullptr;
1296     }
1297   }
1298   EXPECT_NE(CriticalEntryCI, nullptr);
1299   EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
1300   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
1301   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
1302 
1303   CallInst *CriticalEndCI = nullptr;
1304   for (auto &FI : *EntryBB) {
1305     Instruction *cur = &FI;
1306     if (isa<CallInst>(cur)) {
1307       CriticalEndCI = cast<CallInst>(cur);
1308       if (CriticalEndCI->getCalledFunction()->getName() ==
1309           "__kmpc_end_critical")
1310         break;
1311       CriticalEndCI = nullptr;
1312     }
1313   }
1314   EXPECT_NE(CriticalEndCI, nullptr);
1315   EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
1316   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
1317   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
1318   PointerType *CriticalNamePtrTy =
1319       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
1320   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
1321   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
1322 }
1323 
TEST_F(OpenMPIRBuilderTest,CopyinBlocks)1324 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
1325   OpenMPIRBuilder OMPBuilder(*M);
1326   OMPBuilder.initialize();
1327   F->setName("func");
1328   IRBuilder<> Builder(BB);
1329 
1330   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1331 
1332   IntegerType* Int32 = Type::getInt32Ty(M->getContext());
1333   AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
1334 	AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
1335 
1336   BasicBlock *EntryBB = BB;
1337 
1338   OMPBuilder.createCopyinClauseBlocks(Builder.saveIP(), MasterAddress,
1339                                       PrivAddress, Int32, /*BranchtoEnd*/ true);
1340 
1341   BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
1342 
1343   EXPECT_NE(EntryBr, nullptr);
1344   EXPECT_TRUE(EntryBr->isConditional());
1345 
1346   BasicBlock* NotMasterBB = EntryBr->getSuccessor(0);
1347   BasicBlock* CopyinEnd = EntryBr->getSuccessor(1);
1348   CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
1349 
1350   EXPECT_NE(CMP, nullptr);
1351   EXPECT_NE(NotMasterBB, nullptr);
1352   EXPECT_NE(CopyinEnd, nullptr);
1353 
1354   BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
1355   EXPECT_NE(NotMasterBr, nullptr);
1356   EXPECT_FALSE(NotMasterBr->isConditional());
1357   EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
1358 }
1359 
TEST_F(OpenMPIRBuilderTest,SingleDirective)1360 TEST_F(OpenMPIRBuilderTest, SingleDirective) {
1361   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1362   OpenMPIRBuilder OMPBuilder(*M);
1363   OMPBuilder.initialize();
1364   F->setName("func");
1365   IRBuilder<> Builder(BB);
1366 
1367   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1368 
1369   AllocaInst *PrivAI = nullptr;
1370 
1371   BasicBlock *EntryBB = nullptr;
1372   BasicBlock *ExitBB = nullptr;
1373   BasicBlock *ThenBB = nullptr;
1374 
1375   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1376                        BasicBlock &FiniBB) {
1377     if (AllocaIP.isSet())
1378       Builder.restoreIP(AllocaIP);
1379     else
1380       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1381     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1382     Builder.CreateStore(F->arg_begin(), PrivAI);
1383 
1384     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1385     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1386     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1387 
1388     Builder.restoreIP(CodeGenIP);
1389 
1390     // collect some info for checks later
1391     ExitBB = FiniBB.getUniqueSuccessor();
1392     ThenBB = Builder.GetInsertBlock();
1393     EntryBB = ThenBB->getUniquePredecessor();
1394 
1395     // simple instructions for body
1396     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
1397     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1398   };
1399 
1400   auto FiniCB = [&](InsertPointTy IP) {
1401     BasicBlock *IPBB = IP.getBlock();
1402     EXPECT_NE(IPBB->end(), IP.getPoint());
1403   };
1404 
1405   Builder.restoreIP(
1406       OMPBuilder.createSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
1407   Value *EntryBBTI = EntryBB->getTerminator();
1408   EXPECT_NE(EntryBBTI, nullptr);
1409   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1410   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1411   EXPECT_TRUE(EntryBr->isConditional());
1412   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1413   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1414   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1415 
1416   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1417   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1418 
1419   CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
1420   EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
1421   EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
1422   EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
1423 
1424   CallInst *SingleEndCI = nullptr;
1425   for (auto &FI : *ThenBB) {
1426     Instruction *cur = &FI;
1427     if (isa<CallInst>(cur)) {
1428       SingleEndCI = cast<CallInst>(cur);
1429       if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
1430         break;
1431       SingleEndCI = nullptr;
1432     }
1433   }
1434   EXPECT_NE(SingleEndCI, nullptr);
1435   EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
1436   EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
1437   EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
1438 }
1439 
1440 } // namespace
1441