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