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:
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 
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 TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
64   OpenMPIRBuilder OMPBuilder(*M);
65   OMPBuilder.initialize();
66 
67   IRBuilder<> Builder(BB);
68 
69   OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
70   EXPECT_TRUE(M->global_empty());
71   EXPECT_EQ(M->size(), 1U);
72   EXPECT_EQ(F->size(), 1U);
73   EXPECT_EQ(BB->size(), 0U);
74 
75   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
76   OMPBuilder.CreateBarrier(Loc, OMPD_for);
77   EXPECT_FALSE(M->global_empty());
78   EXPECT_EQ(M->size(), 3U);
79   EXPECT_EQ(F->size(), 1U);
80   EXPECT_EQ(BB->size(), 2U);
81 
82   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
83   EXPECT_NE(GTID, nullptr);
84   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
85   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
86   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
87   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
88 
89   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
90   EXPECT_NE(Barrier, nullptr);
91   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
92   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
93   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
94   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
95 
96   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
97 
98   Builder.CreateUnreachable();
99   EXPECT_FALSE(verifyModule(*M, &errs()));
100 }
101 
102 TEST_F(OpenMPIRBuilderTest, CreateCancel) {
103   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
104   OpenMPIRBuilder OMPBuilder(*M);
105   OMPBuilder.initialize();
106 
107   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
108   new UnreachableInst(Ctx, CBB);
109   auto FiniCB = [&](InsertPointTy IP) {
110     ASSERT_NE(IP.getBlock(), nullptr);
111     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
112     BranchInst::Create(CBB, IP.getBlock());
113   };
114   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
115 
116   IRBuilder<> Builder(BB);
117 
118   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
119   auto NewIP = OMPBuilder.CreateCancel(Loc, nullptr, OMPD_parallel);
120   Builder.restoreIP(NewIP);
121   EXPECT_FALSE(M->global_empty());
122   EXPECT_EQ(M->size(), 3U);
123   EXPECT_EQ(F->size(), 4U);
124   EXPECT_EQ(BB->size(), 4U);
125 
126   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
127   EXPECT_NE(GTID, nullptr);
128   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
129   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
130   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
131   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
132 
133   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
134   EXPECT_NE(Cancel, nullptr);
135   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
136   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
137   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
138   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
139   EXPECT_EQ(Cancel->getNumUses(), 1U);
140   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
141   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
142   EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
143   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
144   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
145             1U);
146   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
147             CBB);
148 
149   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
150 
151   OMPBuilder.popFinalizationCB();
152 
153   Builder.CreateUnreachable();
154   EXPECT_FALSE(verifyModule(*M, &errs()));
155 }
156 
157 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
158   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
159   OpenMPIRBuilder OMPBuilder(*M);
160   OMPBuilder.initialize();
161 
162   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
163   new UnreachableInst(Ctx, CBB);
164   auto FiniCB = [&](InsertPointTy IP) {
165     ASSERT_NE(IP.getBlock(), nullptr);
166     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
167     BranchInst::Create(CBB, IP.getBlock());
168   };
169   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
170 
171   IRBuilder<> Builder(BB);
172 
173   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
174   auto NewIP = OMPBuilder.CreateCancel(Loc, Builder.getTrue(), OMPD_parallel);
175   Builder.restoreIP(NewIP);
176   EXPECT_FALSE(M->global_empty());
177   EXPECT_EQ(M->size(), 3U);
178   EXPECT_EQ(F->size(), 7U);
179   EXPECT_EQ(BB->size(), 1U);
180   ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
181   ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
182   BB = BB->getTerminator()->getSuccessor(0);
183   EXPECT_EQ(BB->size(), 4U);
184 
185 
186   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
187   EXPECT_NE(GTID, nullptr);
188   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
189   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
190   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
191   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
192 
193   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
194   EXPECT_NE(Cancel, nullptr);
195   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
196   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
197   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
198   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
199   EXPECT_EQ(Cancel->getNumUses(), 1U);
200   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
201   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
202   EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
203   EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock());
204   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
205   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
206             1U);
207   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
208             CBB);
209 
210   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
211 
212   OMPBuilder.popFinalizationCB();
213 
214   Builder.CreateUnreachable();
215   EXPECT_FALSE(verifyModule(*M, &errs()));
216 }
217 
218 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
219   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
220   OpenMPIRBuilder OMPBuilder(*M);
221   OMPBuilder.initialize();
222 
223   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
224   new UnreachableInst(Ctx, CBB);
225   auto FiniCB = [&](InsertPointTy IP) {
226     ASSERT_NE(IP.getBlock(), nullptr);
227     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
228     BranchInst::Create(CBB, IP.getBlock());
229   };
230   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
231 
232   IRBuilder<> Builder(BB);
233 
234   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
235   auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for);
236   Builder.restoreIP(NewIP);
237   EXPECT_FALSE(M->global_empty());
238   EXPECT_EQ(M->size(), 3U);
239   EXPECT_EQ(F->size(), 4U);
240   EXPECT_EQ(BB->size(), 4U);
241 
242   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
243   EXPECT_NE(GTID, nullptr);
244   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
245   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
246   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
247   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
248 
249   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
250   EXPECT_NE(Barrier, nullptr);
251   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
252   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
253   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
254   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
255   EXPECT_EQ(Barrier->getNumUses(), 1U);
256   Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
257   EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
258   EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
259   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
260   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
261             1U);
262   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
263             CBB);
264 
265   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
266 
267   OMPBuilder.popFinalizationCB();
268 
269   Builder.CreateUnreachable();
270   EXPECT_FALSE(verifyModule(*M, &errs()));
271 }
272 
273 TEST_F(OpenMPIRBuilderTest, DbgLoc) {
274   OpenMPIRBuilder OMPBuilder(*M);
275   OMPBuilder.initialize();
276   F->setName("func");
277 
278   IRBuilder<> Builder(BB);
279 
280   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
281   OMPBuilder.CreateBarrier(Loc, OMPD_for);
282   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
283   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
284   EXPECT_EQ(GTID->getDebugLoc(), DL);
285   EXPECT_EQ(Barrier->getDebugLoc(), DL);
286   EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
287   if (!isa<GlobalVariable>(Barrier->getOperand(0)))
288     return;
289   GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
290   EXPECT_TRUE(Ident->hasInitializer());
291   if (!Ident->hasInitializer())
292     return;
293   Constant *Initializer = Ident->getInitializer();
294   EXPECT_TRUE(
295       isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
296   GlobalVariable *SrcStrGlob =
297       cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
298   if (!SrcStrGlob)
299     return;
300   EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
301   ConstantDataArray *SrcSrc =
302       dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
303   if (!SrcSrc)
304     return;
305   EXPECT_EQ(SrcSrc->getAsCString(), ";/src/test.dbg;foo;3;7;;");
306 }
307 
308 TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
309   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
310   OpenMPIRBuilder OMPBuilder(*M);
311   OMPBuilder.initialize();
312   F->setName("func");
313   IRBuilder<> Builder(BB);
314 
315   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
316 
317   AllocaInst *PrivAI = nullptr;
318 
319   unsigned NumBodiesGenerated = 0;
320   unsigned NumPrivatizedVars = 0;
321   unsigned NumFinalizationPoints = 0;
322 
323   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
324                        BasicBlock &ContinuationIP) {
325     ++NumBodiesGenerated;
326 
327     Builder.restoreIP(AllocaIP);
328     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
329     Builder.CreateStore(F->arg_begin(), PrivAI);
330 
331     Builder.restoreIP(CodeGenIP);
332     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
333     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
334     Instruction *ThenTerm, *ElseTerm;
335     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
336                                   &ThenTerm, &ElseTerm);
337 
338     Builder.SetInsertPoint(ThenTerm);
339     Builder.CreateBr(&ContinuationIP);
340     ThenTerm->eraseFromParent();
341   };
342 
343   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
344                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
345     ++NumPrivatizedVars;
346 
347     if (!isa<AllocaInst>(VPtr)) {
348       EXPECT_EQ(&VPtr, F->arg_begin());
349       ReplacementValue = &VPtr;
350       return CodeGenIP;
351     }
352 
353     // Trivial copy (=firstprivate).
354     Builder.restoreIP(AllocaIP);
355     Type *VTy = VPtr.getType()->getPointerElementType();
356     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
357     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
358     Builder.restoreIP(CodeGenIP);
359     Builder.CreateStore(V, ReplacementValue);
360     return CodeGenIP;
361   };
362 
363   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
364 
365   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
366                                     F->getEntryBlock().getFirstInsertionPt());
367   IRBuilder<>::InsertPoint AfterIP =
368       OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
369                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
370   EXPECT_EQ(NumBodiesGenerated, 1U);
371   EXPECT_EQ(NumPrivatizedVars, 1U);
372   EXPECT_EQ(NumFinalizationPoints, 1U);
373 
374   Builder.restoreIP(AfterIP);
375   Builder.CreateRetVoid();
376 
377   OMPBuilder.finalize();
378 
379   EXPECT_NE(PrivAI, nullptr);
380   Function *OutlinedFn = PrivAI->getFunction();
381   EXPECT_NE(F, OutlinedFn);
382   EXPECT_FALSE(verifyModule(*M, &errs()));
383   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
384   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
385   EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
386   EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
387 
388   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
389   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
390 
391   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
392   EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
393   User *Usr = OutlinedFn->user_back();
394   ASSERT_TRUE(isa<ConstantExpr>(Usr));
395   CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
396   ASSERT_NE(ForkCI, nullptr);
397 
398   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
399   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
400   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
401   EXPECT_EQ(ForkCI->getArgOperand(1),
402             ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
403   EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
404   EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
405 }
406 
407 TEST_F(OpenMPIRBuilderTest, ParallelNested) {
408   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
409   OpenMPIRBuilder OMPBuilder(*M);
410   OMPBuilder.initialize();
411   F->setName("func");
412   IRBuilder<> Builder(BB);
413 
414   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
415 
416   unsigned NumInnerBodiesGenerated = 0;
417   unsigned NumOuterBodiesGenerated = 0;
418   unsigned NumFinalizationPoints = 0;
419 
420   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
421                             BasicBlock &ContinuationIP) {
422     ++NumInnerBodiesGenerated;
423   };
424 
425   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
426                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
427     // Trivial copy (=firstprivate).
428     Builder.restoreIP(AllocaIP);
429     Type *VTy = VPtr.getType()->getPointerElementType();
430     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
431     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
432     Builder.restoreIP(CodeGenIP);
433     Builder.CreateStore(V, ReplacementValue);
434     return CodeGenIP;
435   };
436 
437   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
438 
439   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
440                             BasicBlock &ContinuationIP) {
441     ++NumOuterBodiesGenerated;
442     Builder.restoreIP(CodeGenIP);
443     BasicBlock *CGBB = CodeGenIP.getBlock();
444     BasicBlock *NewBB = SplitBlock(CGBB, &*CodeGenIP.getPoint());
445     CGBB->getTerminator()->eraseFromParent();
446     ;
447 
448     IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
449         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
450         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
451 
452     Builder.restoreIP(AfterIP);
453     Builder.CreateBr(NewBB);
454   };
455 
456   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
457                                     F->getEntryBlock().getFirstInsertionPt());
458   IRBuilder<>::InsertPoint AfterIP =
459       OMPBuilder.CreateParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
460                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
461 
462   EXPECT_EQ(NumInnerBodiesGenerated, 1U);
463   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
464   EXPECT_EQ(NumFinalizationPoints, 2U);
465 
466   Builder.restoreIP(AfterIP);
467   Builder.CreateRetVoid();
468 
469   OMPBuilder.finalize();
470 
471   EXPECT_EQ(M->size(), 5U);
472   for (Function &OutlinedFn : *M) {
473     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
474       continue;
475     EXPECT_FALSE(verifyModule(*M, &errs()));
476     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
477     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
478     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
479     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
480 
481     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
482     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
483 
484     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
485     User *Usr = OutlinedFn.user_back();
486     ASSERT_TRUE(isa<ConstantExpr>(Usr));
487     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
488     ASSERT_NE(ForkCI, nullptr);
489 
490     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
491     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
492     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
493     EXPECT_EQ(ForkCI->getArgOperand(1),
494               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
495     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
496   }
497 }
498 
499 TEST_F(OpenMPIRBuilderTest, ParallelNested2Inner) {
500   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
501   OpenMPIRBuilder OMPBuilder(*M);
502   OMPBuilder.initialize();
503   F->setName("func");
504   IRBuilder<> Builder(BB);
505 
506   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
507 
508   unsigned NumInnerBodiesGenerated = 0;
509   unsigned NumOuterBodiesGenerated = 0;
510   unsigned NumFinalizationPoints = 0;
511 
512   auto InnerBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
513                             BasicBlock &ContinuationIP) {
514     ++NumInnerBodiesGenerated;
515   };
516 
517   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
518                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
519     // Trivial copy (=firstprivate).
520     Builder.restoreIP(AllocaIP);
521     Type *VTy = VPtr.getType()->getPointerElementType();
522     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
523     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
524     Builder.restoreIP(CodeGenIP);
525     Builder.CreateStore(V, ReplacementValue);
526     return CodeGenIP;
527   };
528 
529   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
530 
531   auto OuterBodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
532                             BasicBlock &ContinuationIP) {
533     ++NumOuterBodiesGenerated;
534     Builder.restoreIP(CodeGenIP);
535     BasicBlock *CGBB = CodeGenIP.getBlock();
536     BasicBlock *NewBB1 = SplitBlock(CGBB, &*CodeGenIP.getPoint());
537     BasicBlock *NewBB2 = SplitBlock(NewBB1, &*NewBB1->getFirstInsertionPt());
538     CGBB->getTerminator()->eraseFromParent();
539     ;
540     NewBB1->getTerminator()->eraseFromParent();
541     ;
542 
543     IRBuilder<>::InsertPoint AfterIP1 = OMPBuilder.CreateParallel(
544         InsertPointTy(CGBB, CGBB->end()), AllocaIP, InnerBodyGenCB, PrivCB,
545         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
546 
547     Builder.restoreIP(AfterIP1);
548     Builder.CreateBr(NewBB1);
549 
550     IRBuilder<>::InsertPoint AfterIP2 = OMPBuilder.CreateParallel(
551         InsertPointTy(NewBB1, NewBB1->end()), AllocaIP, InnerBodyGenCB, PrivCB,
552         FiniCB, nullptr, nullptr, OMP_PROC_BIND_default, false);
553 
554     Builder.restoreIP(AfterIP2);
555     Builder.CreateBr(NewBB2);
556   };
557 
558   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
559                                     F->getEntryBlock().getFirstInsertionPt());
560   IRBuilder<>::InsertPoint AfterIP =
561       OMPBuilder.CreateParallel(Loc, AllocaIP, OuterBodyGenCB, PrivCB, FiniCB,
562                                 nullptr, nullptr, OMP_PROC_BIND_default, false);
563 
564   EXPECT_EQ(NumInnerBodiesGenerated, 2U);
565   EXPECT_EQ(NumOuterBodiesGenerated, 1U);
566   EXPECT_EQ(NumFinalizationPoints, 3U);
567 
568   Builder.restoreIP(AfterIP);
569   Builder.CreateRetVoid();
570 
571   OMPBuilder.finalize();
572 
573   EXPECT_EQ(M->size(), 6U);
574   for (Function &OutlinedFn : *M) {
575     if (F == &OutlinedFn || OutlinedFn.isDeclaration())
576       continue;
577     EXPECT_FALSE(verifyModule(*M, &errs()));
578     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoUnwind));
579     EXPECT_TRUE(OutlinedFn.hasFnAttribute(Attribute::NoRecurse));
580     EXPECT_TRUE(OutlinedFn.hasParamAttribute(0, Attribute::NoAlias));
581     EXPECT_TRUE(OutlinedFn.hasParamAttribute(1, Attribute::NoAlias));
582 
583     EXPECT_TRUE(OutlinedFn.hasInternalLinkage());
584     EXPECT_EQ(OutlinedFn.arg_size(), 2U);
585 
586     unsigned NumAllocas = 0;
587     for (Instruction &I : instructions(OutlinedFn))
588       NumAllocas += isa<AllocaInst>(I);
589     EXPECT_EQ(NumAllocas, 1U);
590 
591     EXPECT_EQ(OutlinedFn.getNumUses(), 1U);
592     User *Usr = OutlinedFn.user_back();
593     ASSERT_TRUE(isa<ConstantExpr>(Usr));
594     CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
595     ASSERT_NE(ForkCI, nullptr);
596 
597     EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
598     EXPECT_EQ(ForkCI->getNumArgOperands(), 3U);
599     EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
600     EXPECT_EQ(ForkCI->getArgOperand(1),
601               ConstantInt::get(Type::getInt32Ty(Ctx), 0U));
602     EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
603   }
604 }
605 
606 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
607   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
608   OpenMPIRBuilder OMPBuilder(*M);
609   OMPBuilder.initialize();
610   F->setName("func");
611   IRBuilder<> Builder(BB);
612 
613   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
614 
615   AllocaInst *PrivAI = nullptr;
616 
617   unsigned NumBodiesGenerated = 0;
618   unsigned NumPrivatizedVars = 0;
619   unsigned NumFinalizationPoints = 0;
620 
621   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
622                        BasicBlock &ContinuationIP) {
623     ++NumBodiesGenerated;
624 
625     Builder.restoreIP(AllocaIP);
626     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
627     Builder.CreateStore(F->arg_begin(), PrivAI);
628 
629     Builder.restoreIP(CodeGenIP);
630     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
631     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
632     Instruction *ThenTerm, *ElseTerm;
633     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
634                                   &ThenTerm, &ElseTerm);
635 
636     Builder.SetInsertPoint(ThenTerm);
637     Builder.CreateBr(&ContinuationIP);
638     ThenTerm->eraseFromParent();
639   };
640 
641   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
642                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
643     ++NumPrivatizedVars;
644 
645     if (!isa<AllocaInst>(VPtr)) {
646       EXPECT_EQ(&VPtr, F->arg_begin());
647       ReplacementValue = &VPtr;
648       return CodeGenIP;
649     }
650 
651     // Trivial copy (=firstprivate).
652     Builder.restoreIP(AllocaIP);
653     Type *VTy = VPtr.getType()->getPointerElementType();
654     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
655     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
656     Builder.restoreIP(CodeGenIP);
657     Builder.CreateStore(V, ReplacementValue);
658     return CodeGenIP;
659   };
660 
661   auto FiniCB = [&](InsertPointTy CodeGenIP) {
662     ++NumFinalizationPoints;
663     // No destructors.
664   };
665 
666   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
667                                     F->getEntryBlock().getFirstInsertionPt());
668   IRBuilder<>::InsertPoint AfterIP =
669       OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
670                                 Builder.CreateIsNotNull(F->arg_begin()),
671                                 nullptr, OMP_PROC_BIND_default, false);
672 
673   EXPECT_EQ(NumBodiesGenerated, 1U);
674   EXPECT_EQ(NumPrivatizedVars, 1U);
675   EXPECT_EQ(NumFinalizationPoints, 1U);
676 
677   Builder.restoreIP(AfterIP);
678   Builder.CreateRetVoid();
679   OMPBuilder.finalize();
680 
681   EXPECT_NE(PrivAI, nullptr);
682   Function *OutlinedFn = PrivAI->getFunction();
683   EXPECT_NE(F, OutlinedFn);
684   EXPECT_FALSE(verifyModule(*M, &errs()));
685 
686   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
687   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
688 
689   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
690   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
691 
692   CallInst *DirectCI = nullptr;
693   CallInst *ForkCI = nullptr;
694   for (User *Usr : OutlinedFn->users()) {
695     if (isa<CallInst>(Usr)) {
696       ASSERT_EQ(DirectCI, nullptr);
697       DirectCI = cast<CallInst>(Usr);
698     } else {
699       ASSERT_TRUE(isa<ConstantExpr>(Usr));
700       ASSERT_EQ(Usr->getNumUses(), 1U);
701       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
702       ForkCI = cast<CallInst>(Usr->user_back());
703     }
704   }
705 
706   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
707   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
708   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
709   EXPECT_EQ(ForkCI->getArgOperand(1),
710             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
711   EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
712 
713   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
714   EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
715   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
716   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
717   EXPECT_EQ(DirectCI->getArgOperand(2), F->arg_begin());
718 }
719 
720 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
721   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
722   OpenMPIRBuilder OMPBuilder(*M);
723   OMPBuilder.initialize();
724   F->setName("func");
725   IRBuilder<> Builder(BB);
726 
727   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
728 
729   unsigned NumBodiesGenerated = 0;
730   unsigned NumPrivatizedVars = 0;
731   unsigned NumFinalizationPoints = 0;
732 
733   CallInst *CheckedBarrier = nullptr;
734   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
735                        BasicBlock &ContinuationIP) {
736     ++NumBodiesGenerated;
737 
738     Builder.restoreIP(CodeGenIP);
739 
740     // Create three barriers, two cancel barriers but only one checked.
741     Function *CBFn, *BFn;
742 
743     Builder.restoreIP(
744         OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel));
745 
746     CBFn = M->getFunction("__kmpc_cancel_barrier");
747     BFn = M->getFunction("__kmpc_barrier");
748     ASSERT_NE(CBFn, nullptr);
749     ASSERT_EQ(BFn, nullptr);
750     ASSERT_EQ(CBFn->getNumUses(), 1U);
751     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
752     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
753     CheckedBarrier = cast<CallInst>(CBFn->user_back());
754 
755     Builder.restoreIP(
756         OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, true));
757     CBFn = M->getFunction("__kmpc_cancel_barrier");
758     BFn = M->getFunction("__kmpc_barrier");
759     ASSERT_NE(CBFn, nullptr);
760     ASSERT_NE(BFn, nullptr);
761     ASSERT_EQ(CBFn->getNumUses(), 1U);
762     ASSERT_EQ(BFn->getNumUses(), 1U);
763     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
764     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
765 
766     Builder.restoreIP(OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel,
767                                                false, false));
768     ASSERT_EQ(CBFn->getNumUses(), 2U);
769     ASSERT_EQ(BFn->getNumUses(), 1U);
770     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
771     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
772     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
773   };
774 
775   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V,
776                     Value *&) -> InsertPointTy {
777     ++NumPrivatizedVars;
778     llvm_unreachable("No privatization callback call expected!");
779   };
780 
781   FunctionType *FakeDestructorTy =
782       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
783                         /*isVarArg=*/false);
784   auto *FakeDestructor = Function::Create(
785       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
786 
787   auto FiniCB = [&](InsertPointTy IP) {
788     ++NumFinalizationPoints;
789     Builder.restoreIP(IP);
790     Builder.CreateCall(FakeDestructor,
791                        {Builder.getInt32(NumFinalizationPoints)});
792   };
793 
794   IRBuilder<>::InsertPoint AllocaIP(&F->getEntryBlock(),
795                                     F->getEntryBlock().getFirstInsertionPt());
796   IRBuilder<>::InsertPoint AfterIP =
797       OMPBuilder.CreateParallel(Loc, AllocaIP, BodyGenCB, PrivCB, FiniCB,
798                                 Builder.CreateIsNotNull(F->arg_begin()),
799                                 nullptr, OMP_PROC_BIND_default, true);
800 
801   EXPECT_EQ(NumBodiesGenerated, 1U);
802   EXPECT_EQ(NumPrivatizedVars, 0U);
803   EXPECT_EQ(NumFinalizationPoints, 2U);
804   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
805 
806   Builder.restoreIP(AfterIP);
807   Builder.CreateRetVoid();
808   OMPBuilder.finalize();
809 
810   EXPECT_FALSE(verifyModule(*M, &errs()));
811 
812   BasicBlock *ExitBB = nullptr;
813   for (const User *Usr : FakeDestructor->users()) {
814     const CallInst *CI = dyn_cast<CallInst>(Usr);
815     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
816     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
817     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
818     if (ExitBB)
819       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
820     else
821       ExitBB = CI->getNextNode()->getSuccessor(0);
822     ASSERT_EQ(ExitBB->size(), 1U);
823     if (!isa<ReturnInst>(ExitBB->front())) {
824       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
825       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
826       ASSERT_TRUE(isa<ReturnInst>(
827           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
828     }
829   }
830 }
831 
832 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
833   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
834   OpenMPIRBuilder OMPBuilder(*M);
835   OMPBuilder.initialize();
836   F->setName("func");
837   IRBuilder<> Builder(BB);
838 
839   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
840 
841   AllocaInst *PrivAI = nullptr;
842 
843   BasicBlock *EntryBB = nullptr;
844   BasicBlock *ExitBB = nullptr;
845   BasicBlock *ThenBB = nullptr;
846 
847   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
848                        BasicBlock &FiniBB) {
849     if (AllocaIP.isSet())
850       Builder.restoreIP(AllocaIP);
851     else
852       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
853     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
854     Builder.CreateStore(F->arg_begin(), PrivAI);
855 
856     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
857     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
858     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
859 
860     Builder.restoreIP(CodeGenIP);
861 
862     // collect some info for checks later
863     ExitBB = FiniBB.getUniqueSuccessor();
864     ThenBB = Builder.GetInsertBlock();
865     EntryBB = ThenBB->getUniquePredecessor();
866 
867     // simple instructions for body
868     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
869     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
870   };
871 
872   auto FiniCB = [&](InsertPointTy IP) {
873     BasicBlock *IPBB = IP.getBlock();
874     EXPECT_NE(IPBB->end(), IP.getPoint());
875   };
876 
877   Builder.restoreIP(OMPBuilder.CreateMaster(Builder, BodyGenCB, FiniCB));
878   Value *EntryBBTI = EntryBB->getTerminator();
879   EXPECT_NE(EntryBBTI, nullptr);
880   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
881   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
882   EXPECT_TRUE(EntryBr->isConditional());
883   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
884   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
885   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
886 
887   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
888   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
889 
890   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
891   EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
892   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
893   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
894 
895   CallInst *MasterEndCI = nullptr;
896   for (auto &FI : *ThenBB) {
897     Instruction *cur = &FI;
898     if (isa<CallInst>(cur)) {
899       MasterEndCI = cast<CallInst>(cur);
900       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
901         break;
902       MasterEndCI = nullptr;
903     }
904   }
905   EXPECT_NE(MasterEndCI, nullptr);
906   EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
907   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
908   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
909 }
910 
911 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
912   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
913   OpenMPIRBuilder OMPBuilder(*M);
914   OMPBuilder.initialize();
915   F->setName("func");
916   IRBuilder<> Builder(BB);
917 
918   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
919 
920   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
921 
922   BasicBlock *EntryBB = nullptr;
923 
924   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
925                        BasicBlock &FiniBB) {
926     // collect some info for checks later
927     EntryBB = FiniBB.getUniquePredecessor();
928 
929     // actual start for bodyCB
930     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
931     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
932     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
933     EXPECT_EQ(EntryBB, CodeGenIPBB);
934 
935     // body begin
936     Builder.restoreIP(CodeGenIP);
937     Builder.CreateStore(F->arg_begin(), PrivAI);
938     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
939     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
940   };
941 
942   auto FiniCB = [&](InsertPointTy IP) {
943     BasicBlock *IPBB = IP.getBlock();
944     EXPECT_NE(IPBB->end(), IP.getPoint());
945   };
946 
947   Builder.restoreIP(OMPBuilder.CreateCritical(Builder, BodyGenCB, FiniCB,
948                                               "testCRT", nullptr));
949 
950   Value *EntryBBTI = EntryBB->getTerminator();
951   EXPECT_EQ(EntryBBTI, nullptr);
952 
953   CallInst *CriticalEntryCI = nullptr;
954   for (auto &EI : *EntryBB) {
955     Instruction *cur = &EI;
956     if (isa<CallInst>(cur)) {
957       CriticalEntryCI = cast<CallInst>(cur);
958       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
959         break;
960       CriticalEntryCI = nullptr;
961     }
962   }
963   EXPECT_NE(CriticalEntryCI, nullptr);
964   EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
965   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
966   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
967 
968   CallInst *CriticalEndCI = nullptr;
969   for (auto &FI : *EntryBB) {
970     Instruction *cur = &FI;
971     if (isa<CallInst>(cur)) {
972       CriticalEndCI = cast<CallInst>(cur);
973       if (CriticalEndCI->getCalledFunction()->getName() ==
974           "__kmpc_end_critical")
975         break;
976       CriticalEndCI = nullptr;
977     }
978   }
979   EXPECT_NE(CriticalEndCI, nullptr);
980   EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
981   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
982   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
983   PointerType *CriticalNamePtrTy =
984       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
985   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
986   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
987 }
988 
989 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
990   OpenMPIRBuilder OMPBuilder(*M);
991   OMPBuilder.initialize();
992   F->setName("func");
993   IRBuilder<> Builder(BB);
994 
995   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
996 
997   IntegerType* Int32 = Type::getInt32Ty(M->getContext());
998   AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
999 	AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
1000 
1001   BasicBlock *EntryBB = BB;
1002 
1003   OMPBuilder.CreateCopyinClauseBlocks(Builder.saveIP(), MasterAddress, PrivAddress, Int32, /*BranchtoEnd*/true);
1004 
1005   BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
1006 
1007   EXPECT_NE(EntryBr, nullptr);
1008   EXPECT_TRUE(EntryBr->isConditional());
1009 
1010   BasicBlock* NotMasterBB = EntryBr->getSuccessor(0);
1011   BasicBlock* CopyinEnd = EntryBr->getSuccessor(1);
1012   CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
1013 
1014   EXPECT_NE(CMP, nullptr);
1015   EXPECT_NE(NotMasterBB, nullptr);
1016   EXPECT_NE(CopyinEnd, nullptr);
1017 
1018   BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
1019   EXPECT_NE(NotMasterBr, nullptr);
1020   EXPECT_FALSE(NotMasterBr->isConditional());
1021   EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
1022 }
1023 
1024 TEST_F(OpenMPIRBuilderTest, SingleDirective) {
1025   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1026   OpenMPIRBuilder OMPBuilder(*M);
1027   OMPBuilder.initialize();
1028   F->setName("func");
1029   IRBuilder<> Builder(BB);
1030 
1031   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1032 
1033   AllocaInst *PrivAI = nullptr;
1034 
1035   BasicBlock *EntryBB = nullptr;
1036   BasicBlock *ExitBB = nullptr;
1037   BasicBlock *ThenBB = nullptr;
1038 
1039   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1040                        BasicBlock &FiniBB) {
1041     if (AllocaIP.isSet())
1042       Builder.restoreIP(AllocaIP);
1043     else
1044       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1045     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1046     Builder.CreateStore(F->arg_begin(), PrivAI);
1047 
1048     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1049     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1050     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1051 
1052     Builder.restoreIP(CodeGenIP);
1053 
1054     // collect some info for checks later
1055     ExitBB = FiniBB.getUniqueSuccessor();
1056     ThenBB = Builder.GetInsertBlock();
1057     EntryBB = ThenBB->getUniquePredecessor();
1058 
1059     // simple instructions for body
1060     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
1061     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1062   };
1063 
1064   auto FiniCB = [&](InsertPointTy IP) {
1065     BasicBlock *IPBB = IP.getBlock();
1066     EXPECT_NE(IPBB->end(), IP.getPoint());
1067   };
1068 
1069   Builder.restoreIP(
1070       OMPBuilder.CreateSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
1071   Value *EntryBBTI = EntryBB->getTerminator();
1072   EXPECT_NE(EntryBBTI, nullptr);
1073   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1074   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1075   EXPECT_TRUE(EntryBr->isConditional());
1076   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1077   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1078   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1079 
1080   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1081   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1082 
1083   CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
1084   EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
1085   EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
1086   EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
1087 
1088   CallInst *SingleEndCI = nullptr;
1089   for (auto &FI : *ThenBB) {
1090     Instruction *cur = &FI;
1091     if (isa<CallInst>(cur)) {
1092       SingleEndCI = cast<CallInst>(cur);
1093       if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
1094         break;
1095       SingleEndCI = nullptr;
1096     }
1097   }
1098   EXPECT_NE(SingleEndCI, nullptr);
1099   EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
1100   EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
1101   EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
1102 }
1103 
1104 } // namespace
1105