Skip to content

Commit aaa93a6

Browse files
committed
[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
1 parent 12b4df9 commit aaa93a6

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,32 @@ class OpenMPIRBuilder {
318318
StringMap<AssertingVH<Constant>, BumpPtrAllocator> InternalVars;
319319

320320
public:
321+
/// Generator for __kmpc_copyprivate
322+
///
323+
/// \param Loc The source location description.
324+
/// \param BufSize Number of elements in the buffer.
325+
/// \param CpyBuf List of pointers to data to be copied.
326+
/// \param CpyFn function to call for copying data.
327+
/// \param DidIt flag variable; 1 for 'single' thread, 0 otherwise.
328+
///
329+
/// \return The insertion position *after* the CopyPrivate call.
330+
331+
InsertPointTy CreateCopyPrivate(const LocationDescription &Loc,
332+
llvm::Value *BufSize, llvm::Value *CpyBuf,
333+
llvm::Value *CpyFn, llvm::Value *DidIt);
334+
335+
/// Generator for '#omp single'
336+
///
337+
/// \param Loc The source location description.
338+
/// \param BodyGenCB Callback that will generate the region code.
339+
/// \param FiniCB Callback to finalize variable copies.
340+
/// \param DidIt Local variable used as a flag to indicate 'single' thread
341+
///
342+
/// \returns The insertion position *after* the single call.
343+
InsertPointTy CreateSingle(const LocationDescription &Loc,
344+
BodyGenCallbackTy BodyGenCB,
345+
FinalizeCallbackTy FiniCB, llvm::Value *DidIt);
346+
321347
/// Generator for '#omp master'
322348
///
323349
/// \param Loc The insert and source location description.

llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,62 @@ OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc,
804804
/*Conditional*/ true, /*hasFinalize*/ true);
805805
}
806806

807+
OpenMPIRBuilder::InsertPointTy
808+
OpenMPIRBuilder::CreateCopyPrivate(const LocationDescription &Loc,
809+
llvm::Value *BufSize, llvm::Value *CpyBuf,
810+
llvm::Value *CpyFn, llvm::Value *DidIt) {
811+
if (!updateToLocation(Loc))
812+
return Loc.IP;
813+
814+
Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
815+
Value *Ident = getOrCreateIdent(SrcLocStr);
816+
Value *ThreadId = getOrCreateThreadID(Ident);
817+
818+
llvm::Value *DidItLD = Builder.CreateLoad(DidIt);
819+
820+
Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
821+
822+
Function *Fn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_copyprivate);
823+
Builder.CreateCall(Fn, Args);
824+
825+
return Builder.saveIP();
826+
}
827+
828+
OpenMPIRBuilder::InsertPointTy
829+
OpenMPIRBuilder::CreateSingle(const LocationDescription &Loc,
830+
BodyGenCallbackTy BodyGenCB,
831+
FinalizeCallbackTy FiniCB, llvm::Value *DidIt) {
832+
833+
if (!updateToLocation(Loc))
834+
return Loc.IP;
835+
836+
// If needed (i.e. not null), initialize `DidIt` with 0
837+
if (DidIt) {
838+
Builder.CreateStore(Builder.getInt32(0), DidIt);
839+
}
840+
841+
Directive OMPD = Directive::OMPD_single;
842+
Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
843+
Value *Ident = getOrCreateIdent(SrcLocStr);
844+
Value *ThreadId = getOrCreateThreadID(Ident);
845+
Value *Args[] = {Ident, ThreadId};
846+
847+
Function *EntryRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_single);
848+
Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args);
849+
850+
Function *ExitRTLFn = getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_end_single);
851+
Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
852+
853+
// generates the following:
854+
// if (__kmpc_single()) {
855+
// .... single region ...
856+
// __kmpc_end_single
857+
// }
858+
859+
return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
860+
/*Conditional*/ true, /*hasFinalize*/ true);
861+
}
862+
807863
OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::CreateCritical(
808864
const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB,
809865
FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst) {

llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,4 +1021,84 @@ TEST_F(OpenMPIRBuilderTest, CopyinBlocks) {
10211021
EXPECT_EQ(CopyinEnd,NotMasterBr->getSuccessor(0));
10221022
}
10231023

1024+
TEST_F(OpenMPIRBuilderTest, SingleDirective) {
1025+
using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
1026+
OpenMPIRBuilder OMPBuilder(*M);
1027+
OMPBuilder.initialize();
1028+
F->setName("func");
1029+
IRBuilder<> Builder(BB);
1030+
1031+
OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
1032+
1033+
AllocaInst *PrivAI = nullptr;
1034+
1035+
BasicBlock *EntryBB = nullptr;
1036+
BasicBlock *ExitBB = nullptr;
1037+
BasicBlock *ThenBB = nullptr;
1038+
1039+
auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1040+
BasicBlock &FiniBB) {
1041+
if (AllocaIP.isSet())
1042+
Builder.restoreIP(AllocaIP);
1043+
else
1044+
Builder.SetInsertPoint(&*(F->getEntryBlock().getFirstInsertionPt()));
1045+
PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
1046+
Builder.CreateStore(F->arg_begin(), PrivAI);
1047+
1048+
llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
1049+
llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
1050+
EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
1051+
1052+
Builder.restoreIP(CodeGenIP);
1053+
1054+
// collect some info for checks later
1055+
ExitBB = FiniBB.getUniqueSuccessor();
1056+
ThenBB = Builder.GetInsertBlock();
1057+
EntryBB = ThenBB->getUniquePredecessor();
1058+
1059+
// simple instructions for body
1060+
Value *PrivLoad = Builder.CreateLoad(PrivAI, "local.use");
1061+
Builder.CreateICmpNE(F->arg_begin(), PrivLoad);
1062+
};
1063+
1064+
auto FiniCB = [&](InsertPointTy IP) {
1065+
BasicBlock *IPBB = IP.getBlock();
1066+
EXPECT_NE(IPBB->end(), IP.getPoint());
1067+
};
1068+
1069+
Builder.restoreIP(
1070+
OMPBuilder.CreateSingle(Builder, BodyGenCB, FiniCB, /*DidIt*/ nullptr));
1071+
Value *EntryBBTI = EntryBB->getTerminator();
1072+
EXPECT_NE(EntryBBTI, nullptr);
1073+
EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
1074+
BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
1075+
EXPECT_TRUE(EntryBr->isConditional());
1076+
EXPECT_EQ(EntryBr->getSuccessor(0), ThenBB);
1077+
EXPECT_EQ(ThenBB->getUniqueSuccessor(), ExitBB);
1078+
EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
1079+
1080+
CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
1081+
EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
1082+
1083+
CallInst *SingleEntryCI = cast<CallInst>(CondInst->getOperand(0));
1084+
EXPECT_EQ(SingleEntryCI->getNumArgOperands(), 2U);
1085+
EXPECT_EQ(SingleEntryCI->getCalledFunction()->getName(), "__kmpc_single");
1086+
EXPECT_TRUE(isa<GlobalVariable>(SingleEntryCI->getArgOperand(0)));
1087+
1088+
CallInst *SingleEndCI = nullptr;
1089+
for (auto &FI : *ThenBB) {
1090+
Instruction *cur = &FI;
1091+
if (isa<CallInst>(cur)) {
1092+
SingleEndCI = cast<CallInst>(cur);
1093+
if (SingleEndCI->getCalledFunction()->getName() == "__kmpc_end_single")
1094+
break;
1095+
SingleEndCI = nullptr;
1096+
}
1097+
}
1098+
EXPECT_NE(SingleEndCI, nullptr);
1099+
EXPECT_EQ(SingleEndCI->getNumArgOperands(), 2U);
1100+
EXPECT_TRUE(isa<GlobalVariable>(SingleEndCI->getArgOperand(0)));
1101+
EXPECT_EQ(SingleEndCI->getArgOperand(1), SingleEntryCI->getArgOperand(1));
1102+
}
1103+
10241104
} // namespace

0 commit comments

Comments
 (0)