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