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/OMPIRBuilder.h"
10 #include "llvm/IR/BasicBlock.h"
11 #include "llvm/IR/DIBuilder.h"
12 #include "llvm/IR/Function.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Frontend/OpenMP/OMPConstants.h"
16 #include "llvm/IR/Verifier.h"
17 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 using namespace omp;
22 
23 namespace {
24 
25 class OpenMPIRBuilderTest : public testing::Test {
26 protected:
SetUp()27   void SetUp() override {
28     M.reset(new Module("MyModule", Ctx));
29     FunctionType *FTy =
30         FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
31                           /*isVarArg=*/false);
32     F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
33     BB = BasicBlock::Create(Ctx, "", F);
34 
35     DIBuilder DIB(*M);
36     auto File = DIB.createFile("test.dbg", "/");
37     auto CU =
38         DIB.createCompileUnit(dwarf::DW_LANG_C, File, "llvm-C", true, "", 0);
39     auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
40     auto SP = DIB.createFunction(
41         CU, "foo", "", File, 1, Type, 1, DINode::FlagZero,
42         DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized);
43     F->setSubprogram(SP);
44     auto Scope = DIB.createLexicalBlockFile(SP, File, 0);
45     DIB.finalize();
46     DL = DebugLoc::get(3, 7, Scope);
47   }
48 
TearDown()49   void TearDown() override {
50     BB = nullptr;
51     M.reset();
52   }
53 
54   LLVMContext Ctx;
55   std::unique_ptr<Module> M;
56   Function *F;
57   BasicBlock *BB;
58   DebugLoc DL;
59 };
60 
TEST_F(OpenMPIRBuilderTest,CreateBarrier)61 TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
62   OpenMPIRBuilder OMPBuilder(*M);
63   OMPBuilder.initialize();
64 
65   IRBuilder<> Builder(BB);
66 
67   OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
68   EXPECT_TRUE(M->global_empty());
69   EXPECT_EQ(M->size(), 1U);
70   EXPECT_EQ(F->size(), 1U);
71   EXPECT_EQ(BB->size(), 0U);
72 
73   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
74   OMPBuilder.CreateBarrier(Loc, OMPD_for);
75   EXPECT_FALSE(M->global_empty());
76   EXPECT_EQ(M->size(), 3U);
77   EXPECT_EQ(F->size(), 1U);
78   EXPECT_EQ(BB->size(), 2U);
79 
80   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
81   EXPECT_NE(GTID, nullptr);
82   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
83   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
84   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
85   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
86 
87   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
88   EXPECT_NE(Barrier, nullptr);
89   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
90   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
91   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
92   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
93 
94   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
95 
96   Builder.CreateUnreachable();
97   EXPECT_FALSE(verifyModule(*M, &errs()));
98 }
99 
TEST_F(OpenMPIRBuilderTest,CreateCancel)100 TEST_F(OpenMPIRBuilderTest, CreateCancel) {
101   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
102   OpenMPIRBuilder OMPBuilder(*M);
103   OMPBuilder.initialize();
104 
105   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
106   new UnreachableInst(Ctx, CBB);
107   auto FiniCB = [&](InsertPointTy IP) {
108     ASSERT_NE(IP.getBlock(), nullptr);
109     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
110     BranchInst::Create(CBB, IP.getBlock());
111   };
112   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
113 
114   IRBuilder<> Builder(BB);
115 
116   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
117   auto NewIP = OMPBuilder.CreateCancel(Loc, nullptr, OMPD_parallel);
118   Builder.restoreIP(NewIP);
119   EXPECT_FALSE(M->global_empty());
120   EXPECT_EQ(M->size(), 3U);
121   EXPECT_EQ(F->size(), 4U);
122   EXPECT_EQ(BB->size(), 4U);
123 
124   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
125   EXPECT_NE(GTID, nullptr);
126   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
127   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
128   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
129   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
130 
131   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
132   EXPECT_NE(Cancel, nullptr);
133   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
134   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
135   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
136   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
137   EXPECT_EQ(Cancel->getNumUses(), 1U);
138   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
139   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
140   EXPECT_EQ(CancelBBTI->getSuccessor(0), NewIP.getBlock());
141   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
142   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
143             1U);
144   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
145             CBB);
146 
147   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
148 
149   OMPBuilder.popFinalizationCB();
150 
151   Builder.CreateUnreachable();
152   EXPECT_FALSE(verifyModule(*M, &errs()));
153 }
154 
TEST_F(OpenMPIRBuilderTest,CreateCancelIfCond)155 TEST_F(OpenMPIRBuilderTest, CreateCancelIfCond) {
156   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
157   OpenMPIRBuilder OMPBuilder(*M);
158   OMPBuilder.initialize();
159 
160   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
161   new UnreachableInst(Ctx, CBB);
162   auto FiniCB = [&](InsertPointTy IP) {
163     ASSERT_NE(IP.getBlock(), nullptr);
164     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
165     BranchInst::Create(CBB, IP.getBlock());
166   };
167   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
168 
169   IRBuilder<> Builder(BB);
170 
171   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
172   auto NewIP = OMPBuilder.CreateCancel(Loc, Builder.getTrue(), OMPD_parallel);
173   Builder.restoreIP(NewIP);
174   EXPECT_FALSE(M->global_empty());
175   EXPECT_EQ(M->size(), 3U);
176   EXPECT_EQ(F->size(), 7U);
177   EXPECT_EQ(BB->size(), 1U);
178   ASSERT_TRUE(isa<BranchInst>(BB->getTerminator()));
179   ASSERT_EQ(BB->getTerminator()->getNumSuccessors(), 2U);
180   BB = BB->getTerminator()->getSuccessor(0);
181   EXPECT_EQ(BB->size(), 4U);
182 
183 
184   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
185   EXPECT_NE(GTID, nullptr);
186   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
187   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
188   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
189   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
190 
191   CallInst *Cancel = dyn_cast<CallInst>(GTID->getNextNode());
192   EXPECT_NE(Cancel, nullptr);
193   EXPECT_EQ(Cancel->getNumArgOperands(), 3U);
194   EXPECT_EQ(Cancel->getCalledFunction()->getName(), "__kmpc_cancel");
195   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotAccessMemory());
196   EXPECT_FALSE(Cancel->getCalledFunction()->doesNotFreeMemory());
197   EXPECT_EQ(Cancel->getNumUses(), 1U);
198   Instruction *CancelBBTI = Cancel->getParent()->getTerminator();
199   EXPECT_EQ(CancelBBTI->getNumSuccessors(), 2U);
200   EXPECT_EQ(CancelBBTI->getSuccessor(0)->size(), 1U);
201   EXPECT_EQ(CancelBBTI->getSuccessor(0)->getUniqueSuccessor(), NewIP.getBlock());
202   EXPECT_EQ(CancelBBTI->getSuccessor(1)->size(), 1U);
203   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
204             1U);
205   EXPECT_EQ(CancelBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
206             CBB);
207 
208   EXPECT_EQ(cast<CallInst>(Cancel)->getArgOperand(1), GTID);
209 
210   OMPBuilder.popFinalizationCB();
211 
212   Builder.CreateUnreachable();
213   EXPECT_FALSE(verifyModule(*M, &errs()));
214 }
215 
TEST_F(OpenMPIRBuilderTest,CreateCancelBarrier)216 TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
217   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
218   OpenMPIRBuilder OMPBuilder(*M);
219   OMPBuilder.initialize();
220 
221   BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
222   new UnreachableInst(Ctx, CBB);
223   auto FiniCB = [&](InsertPointTy IP) {
224     ASSERT_NE(IP.getBlock(), nullptr);
225     ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
226     BranchInst::Create(CBB, IP.getBlock());
227   };
228   OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
229 
230   IRBuilder<> Builder(BB);
231 
232   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
233   auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for);
234   Builder.restoreIP(NewIP);
235   EXPECT_FALSE(M->global_empty());
236   EXPECT_EQ(M->size(), 3U);
237   EXPECT_EQ(F->size(), 4U);
238   EXPECT_EQ(BB->size(), 4U);
239 
240   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
241   EXPECT_NE(GTID, nullptr);
242   EXPECT_EQ(GTID->getNumArgOperands(), 1U);
243   EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
244   EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
245   EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
246 
247   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
248   EXPECT_NE(Barrier, nullptr);
249   EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
250   EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
251   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
252   EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
253   EXPECT_EQ(Barrier->getNumUses(), 1U);
254   Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
255   EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
256   EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
257   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
258   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
259             1U);
260   EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
261             CBB);
262 
263   EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
264 
265   OMPBuilder.popFinalizationCB();
266 
267   Builder.CreateUnreachable();
268   EXPECT_FALSE(verifyModule(*M, &errs()));
269 }
270 
TEST_F(OpenMPIRBuilderTest,DbgLoc)271 TEST_F(OpenMPIRBuilderTest, DbgLoc) {
272   OpenMPIRBuilder OMPBuilder(*M);
273   OMPBuilder.initialize();
274   F->setName("func");
275 
276   IRBuilder<> Builder(BB);
277 
278   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
279   OMPBuilder.CreateBarrier(Loc, OMPD_for);
280   CallInst *GTID = dyn_cast<CallInst>(&BB->front());
281   CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
282   EXPECT_EQ(GTID->getDebugLoc(), DL);
283   EXPECT_EQ(Barrier->getDebugLoc(), DL);
284   EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
285   if (!isa<GlobalVariable>(Barrier->getOperand(0)))
286     return;
287   GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
288   EXPECT_TRUE(Ident->hasInitializer());
289   if (!Ident->hasInitializer())
290     return;
291   Constant *Initializer = Ident->getInitializer();
292   EXPECT_TRUE(
293       isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
294   GlobalVariable *SrcStrGlob =
295       cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
296   if (!SrcStrGlob)
297     return;
298   EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
299   ConstantDataArray *SrcSrc =
300       dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
301   if (!SrcSrc)
302     return;
303   EXPECT_EQ(SrcSrc->getAsCString(), ";test.dbg;foo;3;7;;");
304 }
305 
TEST_F(OpenMPIRBuilderTest,ParallelSimple)306 TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
307   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
308   OpenMPIRBuilder OMPBuilder(*M);
309   OMPBuilder.initialize();
310   F->setName("func");
311   IRBuilder<> Builder(BB);
312 
313   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
314 
315   AllocaInst *PrivAI = nullptr;
316 
317   unsigned NumBodiesGenerated = 0;
318   unsigned NumPrivatizedVars = 0;
319   unsigned NumFinalizationPoints = 0;
320 
321   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
322                        BasicBlock &ContinuationIP) {
323     ++NumBodiesGenerated;
324 
325     Builder.restoreIP(AllocaIP);
326     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
327     Builder.CreateStore(F->arg_begin(), PrivAI);
328 
329     Builder.restoreIP(CodeGenIP);
330     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
331     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
332     Instruction *ThenTerm, *ElseTerm;
333     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
334                                   &ThenTerm, &ElseTerm);
335 
336     Builder.SetInsertPoint(ThenTerm);
337     Builder.CreateBr(&ContinuationIP);
338     ThenTerm->eraseFromParent();
339   };
340 
341   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
342                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
343     ++NumPrivatizedVars;
344 
345     if (!isa<AllocaInst>(VPtr)) {
346       EXPECT_EQ(&VPtr, F->arg_begin());
347       ReplacementValue = &VPtr;
348       return CodeGenIP;
349     }
350 
351     // Trivial copy (=firstprivate).
352     Builder.restoreIP(AllocaIP);
353     Type *VTy = VPtr.getType()->getPointerElementType();
354     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
355     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
356     Builder.restoreIP(CodeGenIP);
357     Builder.CreateStore(V, ReplacementValue);
358     return CodeGenIP;
359   };
360 
361   auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
362 
363   IRBuilder<>::InsertPoint AfterIP =
364       OMPBuilder.CreateParallel(Loc, BodyGenCB, PrivCB, FiniCB, nullptr,
365                                 nullptr, OMP_PROC_BIND_default, false);
366   EXPECT_EQ(NumBodiesGenerated, 1U);
367   EXPECT_EQ(NumPrivatizedVars, 1U);
368   EXPECT_EQ(NumFinalizationPoints, 1U);
369 
370   Builder.restoreIP(AfterIP);
371   Builder.CreateRetVoid();
372 
373   OMPBuilder.finalize();
374 
375   EXPECT_NE(PrivAI, nullptr);
376   Function *OutlinedFn = PrivAI->getFunction();
377   EXPECT_NE(F, OutlinedFn);
378   EXPECT_FALSE(verifyModule(*M, &errs()));
379   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoUnwind));
380   EXPECT_TRUE(OutlinedFn->hasFnAttribute(Attribute::NoRecurse));
381   EXPECT_TRUE(OutlinedFn->hasParamAttribute(0, Attribute::NoAlias));
382   EXPECT_TRUE(OutlinedFn->hasParamAttribute(1, Attribute::NoAlias));
383 
384   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
385   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
386 
387   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
388   EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
389   User *Usr = OutlinedFn->user_back();
390   ASSERT_TRUE(isa<ConstantExpr>(Usr));
391   CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
392   ASSERT_NE(ForkCI, nullptr);
393 
394   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
395   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
396   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
397   EXPECT_EQ(ForkCI->getArgOperand(1),
398             ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
399   EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
400   EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
401 }
402 
TEST_F(OpenMPIRBuilderTest,ParallelIfCond)403 TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
404   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
405   OpenMPIRBuilder OMPBuilder(*M);
406   OMPBuilder.initialize();
407   F->setName("func");
408   IRBuilder<> Builder(BB);
409 
410   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
411 
412   AllocaInst *PrivAI = nullptr;
413 
414   unsigned NumBodiesGenerated = 0;
415   unsigned NumPrivatizedVars = 0;
416   unsigned NumFinalizationPoints = 0;
417 
418   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
419                        BasicBlock &ContinuationIP) {
420     ++NumBodiesGenerated;
421 
422     Builder.restoreIP(AllocaIP);
423     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
424     Builder.CreateStore(F->arg_begin(), PrivAI);
425 
426     Builder.restoreIP(CodeGenIP);
427     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
428     Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
429     Instruction *ThenTerm, *ElseTerm;
430     SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
431                                   &ThenTerm, &ElseTerm);
432 
433     Builder.SetInsertPoint(ThenTerm);
434     Builder.CreateBr(&ContinuationIP);
435     ThenTerm->eraseFromParent();
436   };
437 
438   auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
439                     Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
440     ++NumPrivatizedVars;
441 
442     if (!isa<AllocaInst>(VPtr)) {
443       EXPECT_EQ(&VPtr, F->arg_begin());
444       ReplacementValue = &VPtr;
445       return CodeGenIP;
446     }
447 
448     // Trivial copy (=firstprivate).
449     Builder.restoreIP(AllocaIP);
450     Type *VTy = VPtr.getType()->getPointerElementType();
451     Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
452     ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
453     Builder.restoreIP(CodeGenIP);
454     Builder.CreateStore(V, ReplacementValue);
455     return CodeGenIP;
456   };
457 
458   auto FiniCB = [&](InsertPointTy CodeGenIP) {
459     ++NumFinalizationPoints;
460     // No destructors.
461   };
462 
463   IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
464       Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
465       nullptr, OMP_PROC_BIND_default, false);
466 
467   EXPECT_EQ(NumBodiesGenerated, 1U);
468   EXPECT_EQ(NumPrivatizedVars, 1U);
469   EXPECT_EQ(NumFinalizationPoints, 1U);
470 
471   Builder.restoreIP(AfterIP);
472   Builder.CreateRetVoid();
473   OMPBuilder.finalize();
474 
475   EXPECT_NE(PrivAI, nullptr);
476   Function *OutlinedFn = PrivAI->getFunction();
477   EXPECT_NE(F, OutlinedFn);
478   EXPECT_FALSE(verifyModule(*M, &errs()));
479 
480   EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
481   EXPECT_EQ(OutlinedFn->arg_size(), 3U);
482 
483   EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
484   ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
485 
486   CallInst *DirectCI = nullptr;
487   CallInst *ForkCI = nullptr;
488   for (User *Usr : OutlinedFn->users()) {
489     if (isa<CallInst>(Usr)) {
490       ASSERT_EQ(DirectCI, nullptr);
491       DirectCI = cast<CallInst>(Usr);
492     } else {
493       ASSERT_TRUE(isa<ConstantExpr>(Usr));
494       ASSERT_EQ(Usr->getNumUses(), 1U);
495       ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
496       ForkCI = cast<CallInst>(Usr->user_back());
497     }
498   }
499 
500   EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
501   EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
502   EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
503   EXPECT_EQ(ForkCI->getArgOperand(1),
504             ConstantInt::get(Type::getInt32Ty(Ctx), 1));
505   EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
506 
507   EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
508   EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
509   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
510   EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
511   EXPECT_EQ(DirectCI->getArgOperand(2), F->arg_begin());
512 }
513 
TEST_F(OpenMPIRBuilderTest,ParallelCancelBarrier)514 TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
515   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
516   OpenMPIRBuilder OMPBuilder(*M);
517   OMPBuilder.initialize();
518   F->setName("func");
519   IRBuilder<> Builder(BB);
520 
521   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
522 
523   unsigned NumBodiesGenerated = 0;
524   unsigned NumPrivatizedVars = 0;
525   unsigned NumFinalizationPoints = 0;
526 
527   CallInst *CheckedBarrier = nullptr;
528   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
529                        BasicBlock &ContinuationIP) {
530     ++NumBodiesGenerated;
531 
532     Builder.restoreIP(CodeGenIP);
533 
534     // Create three barriers, two cancel barriers but only one checked.
535     Function *CBFn, *BFn;
536 
537     Builder.restoreIP(
538         OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel));
539 
540     CBFn = M->getFunction("__kmpc_cancel_barrier");
541     BFn = M->getFunction("__kmpc_barrier");
542     ASSERT_NE(CBFn, nullptr);
543     ASSERT_EQ(BFn, nullptr);
544     ASSERT_EQ(CBFn->getNumUses(), 1U);
545     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
546     ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
547     CheckedBarrier = cast<CallInst>(CBFn->user_back());
548 
549     Builder.restoreIP(
550         OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, true));
551     CBFn = M->getFunction("__kmpc_cancel_barrier");
552     BFn = M->getFunction("__kmpc_barrier");
553     ASSERT_NE(CBFn, nullptr);
554     ASSERT_NE(BFn, nullptr);
555     ASSERT_EQ(CBFn->getNumUses(), 1U);
556     ASSERT_EQ(BFn->getNumUses(), 1U);
557     ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
558     ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
559 
560     Builder.restoreIP(OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel,
561                                                false, false));
562     ASSERT_EQ(CBFn->getNumUses(), 2U);
563     ASSERT_EQ(BFn->getNumUses(), 1U);
564     ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
565     ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
566     ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
567   };
568 
569   auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V,
570                     Value *&) -> InsertPointTy {
571     ++NumPrivatizedVars;
572     llvm_unreachable("No privatization callback call expected!");
573   };
574 
575   FunctionType *FakeDestructorTy =
576       FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
577                         /*isVarArg=*/false);
578   auto *FakeDestructor = Function::Create(
579       FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
580 
581   auto FiniCB = [&](InsertPointTy IP) {
582     ++NumFinalizationPoints;
583     Builder.restoreIP(IP);
584     Builder.CreateCall(FakeDestructor,
585                        {Builder.getInt32(NumFinalizationPoints)});
586   };
587 
588   IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
589       Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
590       nullptr, OMP_PROC_BIND_default, true);
591 
592   EXPECT_EQ(NumBodiesGenerated, 1U);
593   EXPECT_EQ(NumPrivatizedVars, 0U);
594   EXPECT_EQ(NumFinalizationPoints, 2U);
595   EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
596 
597   Builder.restoreIP(AfterIP);
598   Builder.CreateRetVoid();
599   OMPBuilder.finalize();
600 
601   EXPECT_FALSE(verifyModule(*M, &errs()));
602 
603   BasicBlock *ExitBB = nullptr;
604   for (const User *Usr : FakeDestructor->users()) {
605     const CallInst *CI = dyn_cast<CallInst>(Usr);
606     ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
607     ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
608     ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
609     if (ExitBB)
610       ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
611     else
612       ExitBB = CI->getNextNode()->getSuccessor(0);
613     ASSERT_EQ(ExitBB->size(), 1U);
614     if (!isa<ReturnInst>(ExitBB->front())) {
615       ASSERT_TRUE(isa<BranchInst>(ExitBB->front()));
616       ASSERT_EQ(cast<BranchInst>(ExitBB->front()).getNumSuccessors(), 1U);
617       ASSERT_TRUE(isa<ReturnInst>(
618           cast<BranchInst>(ExitBB->front()).getSuccessor(0)->front()));
619     }
620   }
621 }
622 
TEST_F(OpenMPIRBuilderTest,MasterDirective)623 TEST_F(OpenMPIRBuilderTest, MasterDirective) {
624   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
625   OpenMPIRBuilder OMPBuilder(*M);
626   OMPBuilder.initialize();
627   F->setName("func");
628   IRBuilder<> Builder(BB);
629 
630   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
631 
632   AllocaInst *PrivAI = nullptr;
633 
634   BasicBlock *EntryBB = nullptr;
635   BasicBlock *ExitBB = nullptr;
636   BasicBlock *ThenBB = nullptr;
637 
638   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
639                        BasicBlock &FiniBB) {
640     if (AllocaIP.isSet())
641       Builder.restoreIP(AllocaIP);
642     else
643       Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
644     PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
645     Builder.CreateStore(F->arg_begin(), PrivAI);
646 
647     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
648     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
649     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
650 
651     Builder.restoreIP(CodeGenIP);
652 
653     // collect some info for checks later
654     ExitBB = FiniBB.getUniqueSuccessor();
655     ThenBB = Builder.GetInsertBlock();
656     EntryBB = ThenBB->getUniquePredecessor();
657 
658     // simple instructions for body
659     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
660     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
661   };
662 
663   auto FiniCB = [&](InsertPointTy IP) {
664     BasicBlock *IPBB = IP.getBlock();
665     EXPECT_NE(IPBB->end(), IP.getPoint());
666   };
667 
668   Builder.restoreIP(OMPBuilder.CreateMaster(Builder, BodyGenCB, FiniCB));
669   Value *EntryBBTI = EntryBB->getTerminator();
670   EXPECT_NE(EntryBBTI, nullptr);
671   EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
672   BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
673   EXPECT_TRUE(EntryBr->isConditional());
674   EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
675   EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
676   EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
677 
678   CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
679   EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
680 
681   CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
682   EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
683   EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_master");
684   EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
685 
686   CallInst *MasterEndCI = nullptr;
687   for (auto &FI : *ThenBB) {
688     Instruction *cur = &FI;
689     if (isa<CallInst>(cur)) {
690       MasterEndCI = cast<CallInst>(cur);
691       if (MasterEndCI->getCalledFunction()->getName() == "__kmpc_end_master")
692         break;
693       MasterEndCI = nullptr;
694     }
695   }
696   EXPECT_NE(MasterEndCI, nullptr);
697   EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
698   EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
699   EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
700 }
701 
TEST_F(OpenMPIRBuilderTest,CriticalDirective)702 TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
703   using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
704   OpenMPIRBuilder OMPBuilder(*M);
705   OMPBuilder.initialize();
706   F->setName("func");
707   IRBuilder<> Builder(BB);
708 
709   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
710 
711   AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
712 
713   BasicBlock *EntryBB = nullptr;
714 
715   auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
716                        BasicBlock &FiniBB) {
717     // collect some info for checks later
718     EntryBB = FiniBB.getUniquePredecessor();
719 
720     // actual start for bodyCB
721     llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
722     llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
723     EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
724     EXPECT_EQ(EntryBB, CodeGenIPBB);
725 
726     // body begin
727     Builder.restoreIP(CodeGenIP);
728     Builder.CreateStore(F->arg_begin(), PrivAI);
729     Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
730     Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
731   };
732 
733   auto FiniCB = [&](InsertPointTy IP) {
734     BasicBlock *IPBB = IP.getBlock();
735     EXPECT_NE(IPBB->end(), IP.getPoint());
736   };
737 
738   Builder.restoreIP(OMPBuilder.CreateCritical(Builder, BodyGenCB, FiniCB,
739                                               "testCRT", nullptr));
740 
741   Value *EntryBBTI = EntryBB->getTerminator();
742   EXPECT_EQ(EntryBBTI, nullptr);
743 
744   CallInst *CriticalEntryCI = nullptr;
745   for (auto &EI : *EntryBB) {
746     Instruction *cur = &EI;
747     if (isa<CallInst>(cur)) {
748       CriticalEntryCI = cast<CallInst>(cur);
749       if (CriticalEntryCI->getCalledFunction()->getName() == "__kmpc_critical")
750         break;
751       CriticalEntryCI = nullptr;
752     }
753   }
754   EXPECT_NE(CriticalEntryCI, nullptr);
755   EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
756   EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(), "__kmpc_critical");
757   EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
758 
759   CallInst *CriticalEndCI = nullptr;
760   for (auto &FI : *EntryBB) {
761     Instruction *cur = &FI;
762     if (isa<CallInst>(cur)) {
763       CriticalEndCI = cast<CallInst>(cur);
764       if (CriticalEndCI->getCalledFunction()->getName() ==
765           "__kmpc_end_critical")
766         break;
767       CriticalEndCI = nullptr;
768     }
769   }
770   EXPECT_NE(CriticalEndCI, nullptr);
771   EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
772   EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
773   EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
774   PointerType *CriticalNamePtrTy =
775       PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
776   EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
777   EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
778 }
779 
TEST_F(OpenMPIRBuilderTest,CopyinBlocks)780 TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
781   OpenMPIRBuilder OMPBuilder(*M);
782   OMPBuilder.initialize();
783   F->setName("func");
784   IRBuilder<> Builder(BB);
785 
786   OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
787 
788   IntegerType* Int32 = Type::getInt32Ty(M->getContext());
789   AllocaInst* MasterAddress = Builder.CreateAlloca(Int32->getPointerTo());
790 	AllocaInst* PrivAddress = Builder.CreateAlloca(Int32->getPointerTo());
791 
792   BasicBlock *EntryBB = BB;
793 
794   OMPBuilder.CreateCopyinClauseBlocks(Builder.saveIP(), MasterAddress, PrivAddress, Int32, /*BranchtoEnd*/true);
795 
796   BranchInst* EntryBr = dyn_cast_or_null<BranchInst>(EntryBB->getTerminator());
797 
798   EXPECT_NE(EntryBr, nullptr);
799   EXPECT_TRUE(EntryBr->isConditional());
800 
801   BasicBlock* NotMasterBB = EntryBr->getSuccessor(0);
802   BasicBlock* CopyinEnd = EntryBr->getSuccessor(1);
803   CmpInst* CMP = dyn_cast_or_null<CmpInst>(EntryBr->getCondition());
804 
805   EXPECT_NE(CMP, nullptr);
806   EXPECT_NE(NotMasterBB, nullptr);
807   EXPECT_NE(CopyinEnd, nullptr);
808 
809   BranchInst* NotMasterBr = dyn_cast_or_null<BranchInst>(NotMasterBB->getTerminator());
810   EXPECT_NE(NotMasterBr, nullptr);
811   EXPECT_FALSE(NotMasterBr->isConditional());
812   EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
813 }
814 
815 } // namespace
816