[llvm] aaa93a6 - [OpenMP][OMPBuilder] Adding support for `omp single`
Fady Ghanim via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 15 22:56:41 PDT 2020
Author: Fady Ghanim
Date: 2020-08-16T01:15:16-04:00
New Revision: aaa93a681bd89bce0acb6ee9968f02e98005f6b6
URL: https://github.com/llvm/llvm-project/commit/aaa93a681bd89bce0acb6ee9968f02e98005f6b6
DIFF: https://github.com/llvm/llvm-project/commit/aaa93a681bd89bce0acb6ee9968f02e98005f6b6.diff
LOG: [OpenMP][OMPBuilder] Adding support for `omp single`
This adds support for generating `omp single`, and necessary calls for
`copyprivate` clause.
Differential Revision: https://reviews.llvm.org/D85617
Added:
Modified:
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 6d8bbbe1cf77..3228c1bd538b 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -318,6 +318,32 @@ class OpenMPIRBuilder {
StringMap<AssertingVH<Constant>, BumpPtrAllocator> InternalVars;
public:
+ /// Generator for __kmpc_copyprivate
+ ///
+ /// \param Loc The source location description.
+ /// \param BufSize Number of elements in the buffer.
+ /// \param CpyBuf List of pointers to data to be copied.
+ /// \param CpyFn function to call for copying data.
+ /// \param DidIt flag variable; 1 for 'single' thread, 0 otherwise.
+ ///
+ /// \return The insertion position *after* the CopyPrivate call.
+
+ InsertPointTy CreateCopyPrivate(const LocationDescription &Loc,
+ llvm::Value *BufSize, llvm::Value *CpyBuf,
+ llvm::Value *CpyFn, llvm::Value *DidIt);
+
+ /// Generator for '#omp single'
+ ///
+ /// \param Loc The source location description.
+ /// \param BodyGenCB Callback that will generate the region code.
+ /// \param FiniCB Callback to finalize variable copies.
+ /// \param DidIt Local variable used as a flag to indicate 'single' thread
+ ///
+ /// \returns The insertion position *after* the single call.
+ InsertPointTy CreateSingle(const LocationDescription &Loc,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB, llvm::Value *DidIt);
+
/// Generator for '#omp master'
///
/// \param Loc The insert and source location description.
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index c80a5bbb2401..f5b7e4ebd439 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -804,6 +804,62 @@ OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc,
/*Conditional*/ true, /*hasFinalize*/ true);
}
+OpenMPIRBuilder::InsertPointTy
+OpenMPIRBuilder::CreateCopyPrivate(const LocationDescription &Loc,
+ llvm::Value *BufSize, llvm::Value *CpyBuf,
+ llvm::Value *CpyFn, llvm::Value *DidIt) {
+ if (!updateToLocation(Loc))
+ return Loc.IP;
+
+ Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+ Value *Ident = getOrCreateIdent(SrcLocStr);
+ Value *ThreadId = getOrCreateThreadID(Ident);
+
+ llvm::Value *DidItLD = Builder.CreateLoad(DidIt);
+
+ Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
+
+ Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_copyprivate);
+ Builder.CreateCall(Fn, Args);
+
+ return Builder.saveIP();
+}
+
+OpenMPIRBuilder::InsertPointTy
+OpenMPIRBuilder::CreateSingle(const LocationDescription &Loc,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB, llvm::Value *DidIt) {
+
+ if (!updateToLocation(Loc))
+ return Loc.IP;
+
+ // If needed (i.e. not null), initialize `DidIt` with 0
+ if (DidIt) {
+ Builder.CreateStore(Builder.getInt32(0), DidIt);
+ }
+
+ Directive OMPD = Directive::OMPD_single;
+ Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+ Value *Ident = getOrCreateIdent(SrcLocStr);
+ Value *ThreadId = getOrCreateThreadID(Ident);
+ Value *Args[] = {Ident, ThreadId};
+
+ Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_single);
+ Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args);
+
+ Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_single);
+ Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
+
+ // generates the following:
+ // if (__kmpc_single()) {
+ // .... single region ...
+ // __kmpc_end_single
+ // }
+
+ return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
+ /*Conditional*/ true, /*hasFinalize*/ true);
+}
+
OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCritical(
const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB,
FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) {
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index d671e65f8f49..95f52a9a24c3 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -1021,4 +1021,84 @@ TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
}
+TEST_F(OpenMPIRBuilderTest, SingleDirective) {
+ using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
+ OpenMPIRBuilder OMPBuilder(*M);
+ OMPBuilder.initialize();
+ F->setName("func");
+ IRBuilder<> Builder(BB);
+
+ OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
+
+ AllocaInst *PrivAI = nullptr;
+
+ BasicBlock *EntryBB = nullptr;
+ BasicBlock *ExitBB = nullptr;
+ BasicBlock *ThenBB = nullptr;
+
+ auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+ BasicBlock &FiniBB) {
+ if (AllocaIP.isSet())
+ Builder.restoreIP(AllocaIP);
+ else
+ Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
+ PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
+ Builder.CreateStore(F->arg_begin(), PrivAI);
+
+ llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+ llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
+ EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
+
+ Builder.restoreIP(CodeGenIP);
+
+ // collect some info for checks later
+ ExitBB = FiniBB.getUniqueSuccessor();
+ ThenBB = Builder.GetInsertBlock();
+ EntryBB = ThenBB->getUniquePredecessor();
+
+ // simple instructions for body
+ Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
+ Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
+ };
+
+ auto FiniCB = [&](InsertPointTy IP) {
+ BasicBlock *IPBB = IP.getBlock();
+ EXPECT_NE(IPBB->end(), IP.getPoint());
+ };
+
+ Builder.restoreIP(
+ OMPBuilder.CreateSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
+ Value *EntryBBTI = EntryBB->getTerminator();
+ EXPECT_NE(EntryBBTI, nullptr);
+ EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
+ BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
+ EXPECT_TRUE(EntryBr->isConditional());
+ EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
+ EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
+ EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
+
+ CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
+ EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
+
+ CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
+ EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
+ EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
+ EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
+
+ CallInst *SingleEndCI = nullptr;
+ for (auto &FI : *ThenBB) {
+ Instruction *cur = &FI;
+ if (isa<CallInst>(cur)) {
+ SingleEndCI = cast<CallInst>(cur);
+ if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
+ break;
+ SingleEndCI = nullptr;
+ }
+ }
+ EXPECT_NE(SingleEndCI, nullptr);
+ EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
+ EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
+ EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
+}
+
} // namespace
More information about the llvm-commits
mailing list