@@ -3327,8 +3327,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirective) {
3327
3327
EXPECT_NE (IPBB->end (), IP.getPoint ());
3328
3328
};
3329
3329
3330
- Builder.restoreIP (OMPBuilder. createSingle (
3331
- Builder, BodyGenCB, FiniCB, /* IsNowait*/ false , /* DidIt */ nullptr ));
3330
+ Builder.restoreIP (
3331
+ OMPBuilder. createSingle ( Builder, BodyGenCB, FiniCB, /* IsNowait*/ false ));
3332
3332
Value *EntryBBTI = EntryBB->getTerminator ();
3333
3333
EXPECT_NE (EntryBBTI, nullptr );
3334
3334
EXPECT_TRUE (isa<BranchInst>(EntryBBTI));
@@ -3417,8 +3417,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveNowait) {
3417
3417
EXPECT_NE (IPBB->end (), IP.getPoint ());
3418
3418
};
3419
3419
3420
- Builder.restoreIP (OMPBuilder. createSingle (
3421
- Builder, BodyGenCB, FiniCB, /* IsNowait*/ true , /* DidIt */ nullptr ));
3420
+ Builder.restoreIP (
3421
+ OMPBuilder. createSingle ( Builder, BodyGenCB, FiniCB, /* IsNowait*/ true ));
3422
3422
Value *EntryBBTI = EntryBB->getTerminator ();
3423
3423
EXPECT_NE (EntryBBTI, nullptr );
3424
3424
EXPECT_TRUE (isa<BranchInst>(EntryBBTI));
@@ -3464,6 +3464,151 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveNowait) {
3464
3464
EXPECT_EQ (ExitBarrier, nullptr );
3465
3465
}
3466
3466
3467
+ // Helper class to check each instruction of a BB.
3468
+ class BBInstIter {
3469
+ BasicBlock *BB;
3470
+ BasicBlock::iterator BBI;
3471
+
3472
+ public:
3473
+ BBInstIter (BasicBlock *BB) : BB(BB), BBI(BB->begin ()) {}
3474
+
3475
+ bool hasNext () const { return BBI != BB->end (); }
3476
+
3477
+ template <typename InstTy> InstTy *next () {
3478
+ if (!hasNext ())
3479
+ return nullptr ;
3480
+ Instruction *Cur = &*BBI++;
3481
+ if (!isa<InstTy>(Cur))
3482
+ return nullptr ;
3483
+ return cast<InstTy>(Cur);
3484
+ }
3485
+ };
3486
+
3487
+ TEST_F (OpenMPIRBuilderTest, SingleDirectiveCopyPrivate) {
3488
+ using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
3489
+ OpenMPIRBuilder OMPBuilder (*M);
3490
+ OMPBuilder.initialize ();
3491
+ F->setName (" func" );
3492
+ IRBuilder<> Builder (BB);
3493
+
3494
+ OpenMPIRBuilder::LocationDescription Loc ({Builder.saveIP (), DL});
3495
+
3496
+ AllocaInst *PrivAI = nullptr ;
3497
+
3498
+ BasicBlock *EntryBB = nullptr ;
3499
+ BasicBlock *ThenBB = nullptr ;
3500
+
3501
+ Value *CPVar = Builder.CreateAlloca (F->arg_begin ()->getType ());
3502
+ Builder.CreateStore (F->arg_begin (), CPVar);
3503
+
3504
+ FunctionType *CopyFuncTy = FunctionType::get (
3505
+ Builder.getVoidTy (), {Builder.getPtrTy (), Builder.getPtrTy ()}, false );
3506
+ Function *CopyFunc =
3507
+ Function::Create (CopyFuncTy, Function::PrivateLinkage, " copy_var" , *M);
3508
+
3509
+ auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP) {
3510
+ if (AllocaIP.isSet ())
3511
+ Builder.restoreIP (AllocaIP);
3512
+ else
3513
+ Builder.SetInsertPoint (&*(F->getEntryBlock ().getFirstInsertionPt ()));
3514
+ PrivAI = Builder.CreateAlloca (F->arg_begin ()->getType ());
3515
+ Builder.CreateStore (F->arg_begin (), PrivAI);
3516
+
3517
+ llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock ();
3518
+ llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint ();
3519
+ EXPECT_EQ (CodeGenIPBB->getTerminator (), CodeGenIPInst);
3520
+
3521
+ Builder.restoreIP (CodeGenIP);
3522
+
3523
+ // collect some info for checks later
3524
+ ThenBB = Builder.GetInsertBlock ();
3525
+ EntryBB = ThenBB->getUniquePredecessor ();
3526
+
3527
+ // simple instructions for body
3528
+ Value *PrivLoad =
3529
+ Builder.CreateLoad (PrivAI->getAllocatedType (), PrivAI, " local.use" );
3530
+ Builder.CreateICmpNE (F->arg_begin (), PrivLoad);
3531
+ };
3532
+
3533
+ auto FiniCB = [&](InsertPointTy IP) {
3534
+ BasicBlock *IPBB = IP.getBlock ();
3535
+ // IP must be before the unconditional branch to ExitBB
3536
+ EXPECT_NE (IPBB->end (), IP.getPoint ());
3537
+ };
3538
+
3539
+ Builder.restoreIP (OMPBuilder.createSingle (Builder, BodyGenCB, FiniCB,
3540
+ /* IsNowait*/ false , {CPVar},
3541
+ {CopyFunc}));
3542
+ Value *EntryBBTI = EntryBB->getTerminator ();
3543
+ EXPECT_NE (EntryBBTI, nullptr );
3544
+ EXPECT_TRUE (isa<BranchInst>(EntryBBTI));
3545
+ BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator ());
3546
+ EXPECT_TRUE (EntryBr->isConditional ());
3547
+ EXPECT_EQ (EntryBr->getSuccessor (0 ), ThenBB);
3548
+ BasicBlock *ExitBB = ThenBB->getUniqueSuccessor ();
3549
+ EXPECT_EQ (EntryBr->getSuccessor (1 ), ExitBB);
3550
+
3551
+ CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition ());
3552
+ EXPECT_TRUE (isa<CallInst>(CondInst->getOperand (0 )));
3553
+
3554
+ CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand (0 ));
3555
+ EXPECT_EQ (SingleEntryCI->arg_size (), 2U );
3556
+ EXPECT_EQ (SingleEntryCI->getCalledFunction ()->getName (), " __kmpc_single" );
3557
+ EXPECT_TRUE (isa<GlobalVariable>(SingleEntryCI->getArgOperand (0 )));
3558
+
3559
+ // check ThenBB
3560
+ BBInstIter ThenBBI (ThenBB);
3561
+ // load PrivAI
3562
+ auto *PrivLI = ThenBBI.next <LoadInst>();
3563
+ EXPECT_NE (PrivLI, nullptr );
3564
+ EXPECT_EQ (PrivLI->getPointerOperand (), PrivAI);
3565
+ // icmp
3566
+ EXPECT_TRUE (ThenBBI.next <ICmpInst>());
3567
+ // store 1, DidIt
3568
+ auto *DidItSI = ThenBBI.next <StoreInst>();
3569
+ EXPECT_NE (DidItSI, nullptr );
3570
+ EXPECT_EQ (DidItSI->getValueOperand (),
3571
+ ConstantInt::get (Type::getInt32Ty (Ctx), 1 ));
3572
+ Value *DidIt = DidItSI->getPointerOperand ();
3573
+ // call __kmpc_end_single
3574
+ auto *SingleEndCI = ThenBBI.next <CallInst>();
3575
+ EXPECT_NE (SingleEndCI, nullptr );
3576
+ EXPECT_EQ (SingleEndCI->getCalledFunction ()->getName (), " __kmpc_end_single" );
3577
+ EXPECT_EQ (SingleEndCI->arg_size (), 2U );
3578
+ EXPECT_TRUE (isa<GlobalVariable>(SingleEndCI->getArgOperand (0 )));
3579
+ EXPECT_EQ (SingleEndCI->getArgOperand (1 ), SingleEntryCI->getArgOperand (1 ));
3580
+ // br ExitBB
3581
+ auto *ExitBBBI = ThenBBI.next <BranchInst>();
3582
+ EXPECT_NE (ExitBBBI, nullptr );
3583
+ EXPECT_TRUE (ExitBBBI->isUnconditional ());
3584
+ EXPECT_EQ (ExitBBBI->getOperand (0 ), ExitBB);
3585
+ EXPECT_FALSE (ThenBBI.hasNext ());
3586
+
3587
+ // check ExitBB
3588
+ BBInstIter ExitBBI (ExitBB);
3589
+ // call __kmpc_global_thread_num
3590
+ auto *ThreadNumCI = ExitBBI.next <CallInst>();
3591
+ EXPECT_NE (ThreadNumCI, nullptr );
3592
+ EXPECT_EQ (ThreadNumCI->getCalledFunction ()->getName (),
3593
+ " __kmpc_global_thread_num" );
3594
+ // load DidIt
3595
+ auto *DidItLI = ExitBBI.next <LoadInst>();
3596
+ EXPECT_NE (DidItLI, nullptr );
3597
+ EXPECT_EQ (DidItLI->getPointerOperand (), DidIt);
3598
+ // call __kmpc_copyprivate
3599
+ auto *CopyPrivateCI = ExitBBI.next <CallInst>();
3600
+ EXPECT_NE (CopyPrivateCI, nullptr );
3601
+ EXPECT_EQ (CopyPrivateCI->arg_size (), 6U );
3602
+ EXPECT_TRUE (isa<AllocaInst>(CopyPrivateCI->getArgOperand (3 )));
3603
+ EXPECT_EQ (CopyPrivateCI->getArgOperand (3 ), CPVar);
3604
+ EXPECT_TRUE (isa<Function>(CopyPrivateCI->getArgOperand (4 )));
3605
+ EXPECT_EQ (CopyPrivateCI->getArgOperand (4 ), CopyFunc);
3606
+ EXPECT_TRUE (isa<LoadInst>(CopyPrivateCI->getArgOperand (5 )));
3607
+ DidItLI = cast<LoadInst>(CopyPrivateCI->getArgOperand (5 ));
3608
+ EXPECT_EQ (DidItLI->getOperand (0 ), DidIt);
3609
+ EXPECT_FALSE (ExitBBI.hasNext ());
3610
+ }
3611
+
3467
3612
TEST_F (OpenMPIRBuilderTest, OMPAtomicReadFlt) {
3468
3613
OpenMPIRBuilder OMPBuilder (*M);
3469
3614
OMPBuilder.initialize ();
0 commit comments