blob: 13e93446d45f22d580efa8096980c68cb12e93bf [file] [log] [blame]
Johannes Doerfertd23c6142019-11-05 18:57:44 -06001//===- 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"
Johannes Doerferte4add9722019-12-25 16:59:38 -060017#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Johannes Doerfertd23c6142019-11-05 18:57:44 -060018#include "gtest/gtest.h"
19
20using namespace llvm;
21using namespace omp;
22using namespace types;
23
24namespace {
25
26class OpenMPIRBuilderTest : public testing::Test {
27protected:
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 uninitializeTypes();
54 }
55
56 LLVMContext Ctx;
57 std::unique_ptr<Module> M;
58 Function *F;
59 BasicBlock *BB;
60 DebugLoc DL;
61};
62
63TEST_F(OpenMPIRBuilderTest, CreateBarrier) {
64 OpenMPIRBuilder OMPBuilder(*M);
65 OMPBuilder.initialize();
66
67 IRBuilder<> Builder(BB);
68
69 OMPBuilder.CreateBarrier({IRBuilder<>::InsertPoint()}, OMPD_for);
70 EXPECT_TRUE(M->global_empty());
71 EXPECT_EQ(M->size(), 1U);
72 EXPECT_EQ(F->size(), 1U);
73 EXPECT_EQ(BB->size(), 0U);
74
75 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
76 OMPBuilder.CreateBarrier(Loc, OMPD_for);
77 EXPECT_FALSE(M->global_empty());
78 EXPECT_EQ(M->size(), 3U);
79 EXPECT_EQ(F->size(), 1U);
80 EXPECT_EQ(BB->size(), 2U);
81
82 CallInst *GTID = dyn_cast<CallInst>(&BB->front());
83 EXPECT_NE(GTID, nullptr);
84 EXPECT_EQ(GTID->getNumArgOperands(), 1U);
85 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
86 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
87 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
88
89 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
90 EXPECT_NE(Barrier, nullptr);
91 EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
92 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_barrier");
93 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
94 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
95
96 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
97
98 Builder.CreateUnreachable();
99 EXPECT_FALSE(verifyModule(*M));
100}
101
102TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
Johannes Doerferte4add9722019-12-25 16:59:38 -0600103 using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600104 OpenMPIRBuilder OMPBuilder(*M);
105 OMPBuilder.initialize();
106
107 BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
108 new UnreachableInst(Ctx, CBB);
Johannes Doerferte4add9722019-12-25 16:59:38 -0600109 auto FiniCB = [&](InsertPointTy IP) {
110 ASSERT_NE(IP.getBlock(), nullptr);
111 ASSERT_EQ(IP.getBlock()->end(), IP.getPoint());
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -0600112 BranchInst::Create(CBB, IP.getBlock());
113 };
Johannes Doerferte4add9722019-12-25 16:59:38 -0600114 OMPBuilder.pushFinalizationCB({FiniCB, OMPD_parallel, true});
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600115
116 IRBuilder<> Builder(BB);
117
118 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP()});
119 auto NewIP = OMPBuilder.CreateBarrier(Loc, OMPD_for);
120 Builder.restoreIP(NewIP);
121 EXPECT_FALSE(M->global_empty());
122 EXPECT_EQ(M->size(), 3U);
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -0600123 EXPECT_EQ(F->size(), 4U);
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600124 EXPECT_EQ(BB->size(), 4U);
125
126 CallInst *GTID = dyn_cast<CallInst>(&BB->front());
127 EXPECT_NE(GTID, nullptr);
128 EXPECT_EQ(GTID->getNumArgOperands(), 1U);
129 EXPECT_EQ(GTID->getCalledFunction()->getName(), "__kmpc_global_thread_num");
130 EXPECT_FALSE(GTID->getCalledFunction()->doesNotAccessMemory());
131 EXPECT_FALSE(GTID->getCalledFunction()->doesNotFreeMemory());
132
133 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
134 EXPECT_NE(Barrier, nullptr);
135 EXPECT_EQ(Barrier->getNumArgOperands(), 2U);
136 EXPECT_EQ(Barrier->getCalledFunction()->getName(), "__kmpc_cancel_barrier");
137 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotAccessMemory());
138 EXPECT_FALSE(Barrier->getCalledFunction()->doesNotFreeMemory());
139 EXPECT_EQ(Barrier->getNumUses(), 1U);
140 Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
141 EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
142 EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
Johannes Doerferte4add9722019-12-25 16:59:38 -0600143 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->size(), 1U);
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -0600144 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
145 1U);
146 EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
147 CBB);
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600148
149 EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
150
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -0600151 OMPBuilder.popFinalizationCB();
152
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600153 Builder.CreateUnreachable();
154 EXPECT_FALSE(verifyModule(*M));
155}
156
157TEST_F(OpenMPIRBuilderTest, DbgLoc) {
158 OpenMPIRBuilder OMPBuilder(*M);
159 OMPBuilder.initialize();
160 F->setName("func");
161
162 IRBuilder<> Builder(BB);
163
164 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
165 OMPBuilder.CreateBarrier(Loc, OMPD_for);
166 CallInst *GTID = dyn_cast<CallInst>(&BB->front());
167 CallInst *Barrier = dyn_cast<CallInst>(GTID->getNextNode());
168 EXPECT_EQ(GTID->getDebugLoc(), DL);
169 EXPECT_EQ(Barrier->getDebugLoc(), DL);
170 EXPECT_TRUE(isa<GlobalVariable>(Barrier->getOperand(0)));
171 if (!isa<GlobalVariable>(Barrier->getOperand(0)))
172 return;
173 GlobalVariable *Ident = cast<GlobalVariable>(Barrier->getOperand(0));
174 EXPECT_TRUE(Ident->hasInitializer());
175 if (!Ident->hasInitializer())
176 return;
177 Constant *Initializer = Ident->getInitializer();
178 EXPECT_TRUE(
179 isa<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts()));
180 GlobalVariable *SrcStrGlob =
181 cast<GlobalVariable>(Initializer->getOperand(4)->stripPointerCasts());
182 if (!SrcStrGlob)
183 return;
184 EXPECT_TRUE(isa<ConstantDataArray>(SrcStrGlob->getInitializer()));
185 ConstantDataArray *SrcSrc =
186 dyn_cast<ConstantDataArray>(SrcStrGlob->getInitializer());
187 if (!SrcSrc)
188 return;
189 EXPECT_EQ(SrcSrc->getAsCString(), ";test.dbg;foo;3;7;;");
190}
Johannes Doerferte4add9722019-12-25 16:59:38 -0600191
192TEST_F(OpenMPIRBuilderTest, ParallelSimple) {
193 using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
194 OpenMPIRBuilder OMPBuilder(*M);
195 OMPBuilder.initialize();
196 F->setName("func");
197 IRBuilder<> Builder(BB);
198
199 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
200
201 AllocaInst *PrivAI = nullptr;
202
203 unsigned NumBodiesGenerated = 0;
204 unsigned NumPrivatizedVars = 0;
205 unsigned NumFinalizationPoints = 0;
206
207 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
208 BasicBlock &ContinuationIP) {
209 ++NumBodiesGenerated;
210
211 Builder.restoreIP(AllocaIP);
212 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
213 Builder.CreateStore(F->arg_begin(), PrivAI);
214
215 Builder.restoreIP(CodeGenIP);
216 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
217 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
218 Instruction *ThenTerm, *ElseTerm;
219 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
220 &ThenTerm, &ElseTerm);
221
222 Builder.SetInsertPoint(ThenTerm);
223 Builder.CreateBr(&ContinuationIP);
224 ThenTerm->eraseFromParent();
225 };
226
227 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
228 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
229 ++NumPrivatizedVars;
230
231 if (!isa<AllocaInst>(VPtr)) {
232 EXPECT_EQ(&VPtr, F->arg_begin());
233 ReplacementValue = &VPtr;
234 return CodeGenIP;
235 }
236
237 // Trivial copy (=firstprivate).
238 Builder.restoreIP(AllocaIP);
239 Type *VTy = VPtr.getType()->getPointerElementType();
240 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
241 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
242 Builder.restoreIP(CodeGenIP);
243 Builder.CreateStore(V, ReplacementValue);
244 return CodeGenIP;
245 };
246
247 auto FiniCB = [&](InsertPointTy CodeGenIP) { ++NumFinalizationPoints; };
248
249 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
250 Loc, BodyGenCB, PrivCB, FiniCB, nullptr, nullptr, OMP_PB_default, false);
251
252 EXPECT_EQ(NumBodiesGenerated, 1U);
253 EXPECT_EQ(NumPrivatizedVars, 1U);
254 EXPECT_EQ(NumFinalizationPoints, 1U);
255
256 Builder.restoreIP(AfterIP);
257 Builder.CreateRetVoid();
258
259 EXPECT_NE(PrivAI, nullptr);
260 Function *OutlinedFn = PrivAI->getFunction();
261 EXPECT_NE(F, OutlinedFn);
262 EXPECT_FALSE(verifyModule(*M));
263
264 EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
265 EXPECT_EQ(OutlinedFn->arg_size(), 3U);
266
267 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
268 EXPECT_EQ(OutlinedFn->getNumUses(), 1U);
269 User *Usr = OutlinedFn->user_back();
270 ASSERT_TRUE(isa<ConstantExpr>(Usr));
271 CallInst *ForkCI = dyn_cast<CallInst>(Usr->user_back());
272 ASSERT_NE(ForkCI, nullptr);
273
274 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
275 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
276 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
277 EXPECT_EQ(ForkCI->getArgOperand(1),
278 ConstantInt::get(Type::getInt32Ty(Ctx), 1U));
279 EXPECT_EQ(ForkCI->getArgOperand(2), Usr);
280 EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
281}
282
283TEST_F(OpenMPIRBuilderTest, ParallelIfCond) {
284 using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
285 OpenMPIRBuilder OMPBuilder(*M);
286 OMPBuilder.initialize();
287 F->setName("func");
288 IRBuilder<> Builder(BB);
289
290 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
291
292 AllocaInst *PrivAI = nullptr;
293
294 unsigned NumBodiesGenerated = 0;
295 unsigned NumPrivatizedVars = 0;
296 unsigned NumFinalizationPoints = 0;
297
298 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
299 BasicBlock &ContinuationIP) {
300 ++NumBodiesGenerated;
301
302 Builder.restoreIP(AllocaIP);
303 PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
304 Builder.CreateStore(F->arg_begin(), PrivAI);
305
306 Builder.restoreIP(CodeGenIP);
307 Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
308 Value *Cmp = Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
309 Instruction *ThenTerm, *ElseTerm;
310 SplitBlockAndInsertIfThenElse(Cmp, CodeGenIP.getBlock()->getTerminator(),
311 &ThenTerm, &ElseTerm);
312
313 Builder.SetInsertPoint(ThenTerm);
314 Builder.CreateBr(&ContinuationIP);
315 ThenTerm->eraseFromParent();
316 };
317
318 auto PrivCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
319 Value &VPtr, Value *&ReplacementValue) -> InsertPointTy {
320 ++NumPrivatizedVars;
321
322 if (!isa<AllocaInst>(VPtr)) {
323 EXPECT_EQ(&VPtr, F->arg_begin());
324 ReplacementValue = &VPtr;
325 return CodeGenIP;
326 }
327
328 // Trivial copy (=firstprivate).
329 Builder.restoreIP(AllocaIP);
330 Type *VTy = VPtr.getType()->getPointerElementType();
331 Value *V = Builder.CreateLoad(VTy, &VPtr, VPtr.getName() + ".reload");
332 ReplacementValue = Builder.CreateAlloca(VTy, 0, VPtr.getName() + ".copy");
333 Builder.restoreIP(CodeGenIP);
334 Builder.CreateStore(V, ReplacementValue);
335 return CodeGenIP;
336 };
337
338 auto FiniCB = [&](InsertPointTy CodeGenIP) {
339 ++NumFinalizationPoints;
340 // No destructors.
341 };
342
343 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
344 Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
345 nullptr, OMP_PB_default, false);
346
347 EXPECT_EQ(NumBodiesGenerated, 1U);
348 EXPECT_EQ(NumPrivatizedVars, 1U);
349 EXPECT_EQ(NumFinalizationPoints, 1U);
350
351 Builder.restoreIP(AfterIP);
352 Builder.CreateRetVoid();
353
354 EXPECT_NE(PrivAI, nullptr);
355 Function *OutlinedFn = PrivAI->getFunction();
356 EXPECT_NE(F, OutlinedFn);
357 EXPECT_FALSE(verifyModule(*M, &errs()));
358
359 EXPECT_TRUE(OutlinedFn->hasInternalLinkage());
360 EXPECT_EQ(OutlinedFn->arg_size(), 3U);
361
362 EXPECT_EQ(&OutlinedFn->getEntryBlock(), PrivAI->getParent());
363 ASSERT_EQ(OutlinedFn->getNumUses(), 2U);
364
365 CallInst *DirectCI = nullptr;
366 CallInst *ForkCI = nullptr;
367 for (User *Usr : OutlinedFn->users()) {
368 if (isa<CallInst>(Usr)) {
369 ASSERT_EQ(DirectCI, nullptr);
370 DirectCI = cast<CallInst>(Usr);
371 } else {
372 ASSERT_TRUE(isa<ConstantExpr>(Usr));
373 ASSERT_EQ(Usr->getNumUses(), 1U);
374 ASSERT_TRUE(isa<CallInst>(Usr->user_back()));
375 ForkCI = cast<CallInst>(Usr->user_back());
376 }
377 }
378
379 EXPECT_EQ(ForkCI->getCalledFunction()->getName(), "__kmpc_fork_call");
380 EXPECT_EQ(ForkCI->getNumArgOperands(), 4U);
381 EXPECT_TRUE(isa<GlobalVariable>(ForkCI->getArgOperand(0)));
382 EXPECT_EQ(ForkCI->getArgOperand(1),
383 ConstantInt::get(Type::getInt32Ty(Ctx), 1));
384 EXPECT_EQ(ForkCI->getArgOperand(3), F->arg_begin());
385
386 EXPECT_EQ(DirectCI->getCalledFunction(), OutlinedFn);
387 EXPECT_EQ(DirectCI->getNumArgOperands(), 3U);
388 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(0)));
389 EXPECT_TRUE(isa<AllocaInst>(DirectCI->getArgOperand(1)));
390 EXPECT_EQ(DirectCI->getArgOperand(2), F->arg_begin());
391}
392
393TEST_F(OpenMPIRBuilderTest, ParallelCancelBarrier) {
394 using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
395 OpenMPIRBuilder OMPBuilder(*M);
396 OMPBuilder.initialize();
397 F->setName("func");
398 IRBuilder<> Builder(BB);
399
400 OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
401
402 unsigned NumBodiesGenerated = 0;
403 unsigned NumPrivatizedVars = 0;
404 unsigned NumFinalizationPoints = 0;
405
406 CallInst *CheckedBarrier = nullptr;
407 auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
408 BasicBlock &ContinuationIP) {
409 ++NumBodiesGenerated;
410
411 Builder.restoreIP(CodeGenIP);
412
413 // Create three barriers, two cancel barriers but only one checked.
414 Function *CBFn, *BFn;
415
416 Builder.restoreIP(
417 OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel));
418
419 CBFn = M->getFunction("__kmpc_cancel_barrier");
420 BFn = M->getFunction("__kmpc_barrier");
421 ASSERT_NE(CBFn, nullptr);
422 ASSERT_EQ(BFn, nullptr);
423 ASSERT_EQ(CBFn->getNumUses(), 1U);
424 ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
425 ASSERT_EQ(CBFn->user_back()->getNumUses(), 1U);
426 CheckedBarrier = cast<CallInst>(CBFn->user_back());
427
428 Builder.restoreIP(
429 OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel, true));
430 CBFn = M->getFunction("__kmpc_cancel_barrier");
431 BFn = M->getFunction("__kmpc_barrier");
432 ASSERT_NE(CBFn, nullptr);
433 ASSERT_NE(BFn, nullptr);
434 ASSERT_EQ(CBFn->getNumUses(), 1U);
435 ASSERT_EQ(BFn->getNumUses(), 1U);
436 ASSERT_TRUE(isa<CallInst>(BFn->user_back()));
437 ASSERT_EQ(BFn->user_back()->getNumUses(), 0U);
438
439 Builder.restoreIP(OMPBuilder.CreateBarrier(Builder.saveIP(), OMPD_parallel,
440 false, false));
441 ASSERT_EQ(CBFn->getNumUses(), 2U);
442 ASSERT_EQ(BFn->getNumUses(), 1U);
443 ASSERT_TRUE(CBFn->user_back() != CheckedBarrier);
444 ASSERT_TRUE(isa<CallInst>(CBFn->user_back()));
445 ASSERT_EQ(CBFn->user_back()->getNumUses(), 0U);
446 };
447
448 auto PrivCB = [&](InsertPointTy, InsertPointTy, Value &V,
449 Value *&) -> InsertPointTy {
450 ++NumPrivatizedVars;
451 llvm_unreachable("No privatization callback call expected!");
452 };
453
454 FunctionType *FakeDestructorTy =
455 FunctionType::get(Type::getVoidTy(Ctx), {Type::getInt32Ty(Ctx)},
456 /*isVarArg=*/false);
457 auto *FakeDestructor = Function::Create(
458 FakeDestructorTy, Function::ExternalLinkage, "fakeDestructor", M.get());
459
460 auto FiniCB = [&](InsertPointTy IP) {
461 ++NumFinalizationPoints;
462 Builder.restoreIP(IP);
463 Builder.CreateCall(FakeDestructor,
464 {Builder.getInt32(NumFinalizationPoints)});
465 };
466
467 IRBuilder<>::InsertPoint AfterIP = OMPBuilder.CreateParallel(
468 Loc, BodyGenCB, PrivCB, FiniCB, Builder.CreateIsNotNull(F->arg_begin()),
469 nullptr, OMP_PB_default, true);
470
471 EXPECT_EQ(NumBodiesGenerated, 1U);
472 EXPECT_EQ(NumPrivatizedVars, 0U);
473 EXPECT_EQ(NumFinalizationPoints, 2U);
474 EXPECT_EQ(FakeDestructor->getNumUses(), 2U);
475
476 Builder.restoreIP(AfterIP);
477 Builder.CreateRetVoid();
478
479 EXPECT_FALSE(verifyModule(*M, &errs()));
480
481 BasicBlock *ExitBB = nullptr;
482 for (const User *Usr : FakeDestructor->users()) {
483 const CallInst *CI = dyn_cast<CallInst>(Usr);
484 ASSERT_EQ(CI->getCalledFunction(), FakeDestructor);
485 ASSERT_TRUE(isa<BranchInst>(CI->getNextNode()));
486 ASSERT_EQ(CI->getNextNode()->getNumSuccessors(), 1U);
487 if (ExitBB)
488 ASSERT_EQ(CI->getNextNode()->getSuccessor(0), ExitBB);
489 else
490 ExitBB = CI->getNextNode()->getSuccessor(0);
491 ASSERT_EQ(ExitBB->size(), 1U);
492 ASSERT_TRUE(isa<ReturnInst>(ExitBB->front()));
493 }
494}
495
Johannes Doerfertd23c6142019-11-05 18:57:44 -0600496} // namespace