@@ -3327,8 +3327,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirective) {
33273327 EXPECT_NE (IPBB->end (), IP.getPoint ());
33283328 };
33293329
3330- Builder.restoreIP (OMPBuilder. createSingle (
3331- Builder, BodyGenCB, FiniCB, /* IsNowait*/ false , /* DidIt */ nullptr ));
3330+ Builder.restoreIP (
3331+ OMPBuilder. createSingle ( Builder, BodyGenCB, FiniCB, /* IsNowait*/ false ));
33323332 Value *EntryBBTI = EntryBB->getTerminator ();
33333333 EXPECT_NE (EntryBBTI, nullptr );
33343334 EXPECT_TRUE (isa<BranchInst>(EntryBBTI));
@@ -3417,8 +3417,8 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveNowait) {
34173417 EXPECT_NE (IPBB->end (), IP.getPoint ());
34183418 };
34193419
3420- Builder.restoreIP (OMPBuilder. createSingle (
3421- Builder, BodyGenCB, FiniCB, /* IsNowait*/ true , /* DidIt */ nullptr ));
3420+ Builder.restoreIP (
3421+ OMPBuilder. createSingle ( Builder, BodyGenCB, FiniCB, /* IsNowait*/ true ));
34223422 Value *EntryBBTI = EntryBB->getTerminator ();
34233423 EXPECT_NE (EntryBBTI, nullptr );
34243424 EXPECT_TRUE (isa<BranchInst>(EntryBBTI));
@@ -3464,6 +3464,151 @@ TEST_F(OpenMPIRBuilderTest, SingleDirectiveNowait) {
34643464 EXPECT_EQ (ExitBarrier, nullptr );
34653465}
34663466
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+
34673612TEST_F (OpenMPIRBuilderTest, OMPAtomicReadFlt) {
34683613 OpenMPIRBuilder OMPBuilder (*M);
34693614 OMPBuilder.initialize ();
0 commit comments