fghanim updated this revision to Diff 237149.
fghanim added a comment.
- Adding array types to OMPKinds.def. Inlining runtime function calls
generation. reformatting with clang format
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D72304/new/
https://reviews.llvm.org/D72304
Files:
clang/lib/CodeGen/CGStmtOpenMP.cpp
llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
llvm/lib/Frontend/OpenMP/OMPConstants.cpp
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
Index: llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
===================================================================
--- llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -613,4 +613,179 @@
}
}
+TEST_F(OpenMPIRBuilderTest, MasterDirective) {
+ 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 *FinalBB = 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
+ FinalBB = &FiniBB;
+ 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.CreateMaster(Builder, BodyGenCB, FiniCB));
+ 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(), FinalBB);
+ EXPECT_EQ(FinalBB->getUniqueSuccessor(), ExitBB);
+ EXPECT_EQ(EntryBr->getSuccessor(1), ExitBB);
+
+ CmpInst *CondInst = cast<CmpInst>(EntryBr->getCondition());
+ EXPECT_TRUE(isa<CallInst>(CondInst->getOperand(0)));
+
+ CallInst *MasterEntryCI = cast<CallInst>(CondInst->getOperand(0));
+ EXPECT_EQ(MasterEntryCI->getNumArgOperands(), 2U);
+ EXPECT_EQ(MasterEntryCI->getCalledFunction()->getName(), "__kmpc_omp_master");
+ EXPECT_TRUE(isa<GlobalVariable>(MasterEntryCI->getArgOperand(0)));
+
+ CallInst *MasterEndCI = nullptr;
+ for (auto &FI : *FinalBB) {
+ Instruction *cur = &FI;
+ if (isa<CallInst>(cur)) {
+ MasterEndCI = cast<CallInst>(cur);
+ if (MasterEndCI->getCalledFunction()->getName() ==
+ "__kmpc_omp_end_master")
+ break;
+ else
+ MasterEndCI = nullptr;
+ }
+ }
+ EXPECT_NE(MasterEndCI, nullptr);
+ EXPECT_EQ(MasterEndCI->getNumArgOperands(), 2U);
+ EXPECT_TRUE(isa<GlobalVariable>(MasterEndCI->getArgOperand(0)));
+ EXPECT_EQ(MasterEndCI->getArgOperand(1), MasterEntryCI->getArgOperand(1));
+}
+
+TEST_F(OpenMPIRBuilderTest, CriticalDirective) {
+ using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
+ OpenMPIRBuilder OMPBuilder(*M);
+ OMPBuilder.initialize();
+ F->setName("func");
+ IRBuilder<> Builder(BB);
+
+ OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
+
+ AllocaInst *PrivAI = Builder.CreateAlloca(F->arg_begin()->getType());
+
+ BasicBlock *EntryBB = nullptr;
+ BasicBlock *FinalBB = nullptr;
+ BasicBlock *ExitBB = nullptr;
+
+ auto BodyGenCB = [&](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+ BasicBlock &FiniBB) {
+ // collect some info for checks later
+ FinalBB = &FiniBB;
+ ExitBB = FiniBB.getUniqueSuccessor();
+ EntryBB = FinalBB->getUniquePredecessor();
+
+ // actual start for bodyCB
+ llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+ llvm::Instruction *CodeGenIPInst = &*CodeGenIP.getPoint();
+ EXPECT_EQ(CodeGenIPBB->getTerminator(), CodeGenIPInst);
+ EXPECT_EQ(EntryBB, CodeGenIPBB);
+
+ // body begin
+ Builder.restoreIP(CodeGenIP);
+ Builder.CreateStore(F->arg_begin(), PrivAI);
+ 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.CreateCritical(Builder, BodyGenCB, FiniCB,
+ "testCRT", nullptr));
+
+ Value *EntryBBTI = EntryBB->getTerminator();
+ EXPECT_NE(EntryBBTI, nullptr);
+ EXPECT_TRUE(isa<BranchInst>(EntryBBTI));
+ BranchInst *EntryBr = cast<BranchInst>(EntryBB->getTerminator());
+ EXPECT_FALSE(EntryBr->isConditional());
+ EXPECT_EQ(EntryBB->getUniqueSuccessor(), FinalBB);
+ EXPECT_EQ(FinalBB->getUniqueSuccessor(), ExitBB);
+
+ CallInst *CriticalEntryCI = nullptr;
+ for (auto &EI : *EntryBB) {
+ Instruction *cur = &EI;
+ if (isa<CallInst>(cur)) {
+ CriticalEntryCI = cast<CallInst>(cur);
+ if (CriticalEntryCI->getCalledFunction()->getName() ==
+ "__kmpc_omp_critical")
+ break;
+ else
+ CriticalEntryCI = nullptr;
+ }
+ }
+ EXPECT_NE(CriticalEntryCI, nullptr);
+ EXPECT_EQ(CriticalEntryCI->getNumArgOperands(), 3U);
+ EXPECT_EQ(CriticalEntryCI->getCalledFunction()->getName(),
+ "__kmpc_omp_critical");
+ EXPECT_TRUE(isa<GlobalVariable>(CriticalEntryCI->getArgOperand(0)));
+
+ CallInst *CriticalEndCI = nullptr;
+ for (auto &FI : *FinalBB) {
+ Instruction *cur = &FI;
+ if (isa<CallInst>(cur)) {
+ CriticalEndCI = cast<CallInst>(cur);
+ if (CriticalEndCI->getCalledFunction()->getName() ==
+ "__kmpc_omp_end_critical")
+ break;
+ else
+ CriticalEndCI = nullptr;
+ }
+ }
+ EXPECT_NE(CriticalEndCI, nullptr);
+ EXPECT_EQ(CriticalEndCI->getNumArgOperands(), 3U);
+ EXPECT_TRUE(isa<GlobalVariable>(CriticalEndCI->getArgOperand(0)));
+ EXPECT_EQ(CriticalEndCI->getArgOperand(1), CriticalEntryCI->getArgOperand(1));
+ PointerType *CriticalNamePtrTy =
+ PointerType::getUnqual(ArrayType::get(Type::getInt32Ty(Ctx), 8));
+ EXPECT_EQ(CriticalEndCI->getArgOperand(2), CriticalEntryCI->getArgOperand(2));
+ EXPECT_EQ(CriticalEndCI->getArgOperand(2)->getType(), CriticalNamePtrTy);
+}
+
} // namespace
Index: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
===================================================================
--- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -630,3 +630,214 @@
return AfterIP;
}
+
+OpenMPIRBuilder::InsertPointTy
+OpenMPIRBuilder::CreateMaster(const LocationDescription &Loc,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB) {
+
+ if (!updateToLocation(Loc))
+ return Loc.IP;
+
+ Directive OMPD = Directive::OMPD_master;
+ Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+ Value *Ident = getOrCreateIdent(SrcLocStr);
+ Value *ThreadId = getOrCreateThreadID(Ident);
+ Value *Args[] = {Ident, ThreadId};
+
+ Function *EntryRTLFn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_master);
+ Instruction *EntryCall = Builder.CreateCall(EntryRTLFn, Args);
+
+ Function *ExitRTLFn =
+ getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_end_master);
+ Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
+
+ 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) {
+
+ if (!updateToLocation(Loc))
+ return Loc.IP;
+
+ Directive OMPD = Directive::OMPD_critical;
+ Constant *SrcLocStr = getOrCreateSrcLocStr(Loc);
+ Value *Ident = getOrCreateIdent(SrcLocStr);
+ Value *ThreadId = getOrCreateThreadID(Ident);
+ Value *LockVar = getOMPCriticalRegionLock(CriticalName);
+ llvm::Value *Args[] = {Ident, ThreadId, LockVar};
+
+ SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), std::end(Args));
+ Function *fn = nullptr;
+ if (HintInst) {
+ // Add Hint to entry Args and create call
+ EnterArgs.push_back(HintInst);
+ fn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_critical_with_hint);
+ } else {
+ fn = getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_critical);
+ }
+ Instruction *EntryCall = Builder.CreateCall(fn, EnterArgs);
+
+ Function *ExitRTLFn =
+ getOrCreateRuntimeFunction(OMPRTL___kmpc_omp_end_critical);
+ Instruction *ExitCall = Builder.CreateCall(ExitRTLFn, Args);
+
+ return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
+ /*Conditional*/ false, /*hasFinalize*/ true);
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::EmitOMPInlinedRegion(
+ omp::Directive OMPD, Instruction *EntryCall, Instruction *ExitCall,
+ BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool conditional,
+ bool hasFinalize) {
+
+ FinalizationStack.push_back({FiniCB, OMPD, /*IsCancellable*/ false});
+
+ // Create 'Critical' entry and body blocks, in preparation
+ // for conditional creation
+ BasicBlock *EntryBB = Builder.GetInsertBlock();
+ Instruction *SplitPos = EntryBB->getTerminator();
+ if (!isa_and_nonnull<BranchInst>(SplitPos))
+ SplitPos = new UnreachableInst(Builder.getContext(), EntryBB);
+ BasicBlock *ExitBB = EntryBB->splitBasicBlock(SplitPos, "omp_region.end");
+ BasicBlock *FiniBB =
+ EntryBB->splitBasicBlock(EntryBB->getTerminator(), "omp_region.finalize");
+
+ Builder.SetInsertPoint(EntryBB->getTerminator());
+ emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, conditional);
+
+ // generate body
+ BodyGenCB(/* AllocaIP */ InsertPointTy(),
+ /* CodeGenIP */ Builder.saveIP(), *FiniBB);
+
+ // emit exit call and do any needed finalization.
+ auto FinIP = InsertPointTy(FiniBB, FiniBB->getFirstInsertionPt());
+ assert(FiniBB->getTerminator()->getNumSuccessors() == 1 &&
+ FiniBB->getTerminator()->getSuccessor(0) == ExitBB &&
+ "Unexpected insertion point for finalization call!");
+ emitCommonDirectiveExit(OMPD, FinIP, ExitBB, ExitCall, /*hasFinalize*/ true);
+
+ BasicBlock *IPBB = SplitPos->getParent();
+ assert(IPBB == ExitBB && "Unexpected Insertion point location!");
+
+ if (!isa_and_nonnull<BranchInst>(SplitPos)) {
+ SplitPos->eraseFromParent();
+ }
+
+ Builder.SetInsertPoint(ExitBB);
+
+ return Builder.saveIP();
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveEntry(
+ omp::Directive omp, llvm::Value *EntryCall, BasicBlock *ExitBB,
+ bool conditional) {
+
+ OpenMPIRBuilder::InsertPointTy Contpt;
+ llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
+
+ if (conditional) {
+ llvm::Value *CallBool = Builder.CreateIsNotNull(EntryCall);
+ auto *ThenBB = BasicBlock::Create(M.getContext(), "omp_region.body");
+ auto *UI = new UnreachableInst(Builder.getContext(), ThenBB);
+
+ // Emit thenBB and set the Builder's insertion point there for
+ // body generation next. Place the block after the current block.
+ llvm::Function *CurFn = EntryBB->getParent();
+ CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB);
+
+ // Move Entry branch to end of ThenBB, and replace with conditional
+ // branch (If-stmt)
+ Instruction *EntryBBTI = EntryBB->getTerminator();
+ Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
+ EntryBBTI->removeFromParent();
+ Builder.SetInsertPoint(UI);
+ Builder.Insert(EntryBBTI);
+ UI->eraseFromParent();
+ Builder.SetInsertPoint(ThenBB->getTerminator());
+
+ // return an insertion point to ExitBB.
+ Contpt = IRBuilder<>::InsertPoint(ExitBB, ExitBB->getFirstInsertionPt());
+ } else
+ // otherwise Return an insertion point to current block
+ Contpt = Builder.saveIP();
+
+ return Contpt;
+}
+
+OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitCommonDirectiveExit(
+ omp::Directive OMPD, InsertPointTy IP, BasicBlock *ExitBB,
+ Instruction *ExitCall, bool hasFinalize) {
+
+ IRBuilder<>::InsertPointGuard IPG(Builder);
+ Builder.restoreIP(IP);
+
+ // If there is finalization to do, emit it before the exit call
+ if (hasFinalize) {
+ assert(!FinalizationStack.empty() &&
+ "Unexpected finalization stack state!");
+
+ FinalizationInfo Fi = FinalizationStack.pop_back_val();
+ assert(Fi.DK == OMPD && "Unexpected Directive for Finalization call!");
+
+ Fi.FiniCB(IP);
+
+ BasicBlock *InsertBB = IP.getBlock();
+ Instruction *InsertBBTI = InsertBB->getTerminator();
+ if (!(InsertBBTI)) {
+ Builder.SetInsertPoint(InsertBB);
+ InsertBBTI = Builder.CreateBr(ExitBB);
+ }
+
+ // set Builder IP for call creation
+ Builder.SetInsertPoint(InsertBBTI);
+ }
+
+ ExitCall->removeFromParent();
+ Builder.Insert(ExitCall);
+
+ return IRBuilder<>::InsertPoint(ExitCall->getParent(),
+ ExitCall->getIterator());
+}
+
+std::string OpenMPIRBuilder::getName(ArrayRef<StringRef> Parts,
+ StringRef FirstSeparator,
+ StringRef Separator) const {
+ SmallString<128> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ StringRef Sep = FirstSeparator;
+ for (StringRef Part : Parts) {
+ OS << Sep << Part;
+ Sep = Separator;
+ }
+ return OS.str();
+}
+
+Constant *OpenMPIRBuilder::getOrCreateOMPInternalVariable(
+ llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ Out << Name;
+ StringRef RuntimeName = Out.str();
+ auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
+ if (Elem.second) {
+ assert(Elem.second->getType()->getPointerElementType() == Ty &&
+ "OMP internal variable has different type than requested");
+ return &*Elem.second;
+ }
+
+ return Elem.second = new llvm::GlobalVariable(
+ M, Ty, /*IsConstant*/ false, llvm::GlobalValue::CommonLinkage,
+ llvm::Constant::getNullValue(Ty), Elem.first(),
+ /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal,
+ AddressSpace);
+}
+
+Value *OpenMPIRBuilder::getOMPCriticalRegionLock(StringRef CriticalName) {
+ std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
+ std::string Name = getName({Prefix, "var"}, ".", ".");
+ return getOrCreateOMPInternalVariable(KmpCriticalNameTy, Name);
+}
Index: llvm/lib/Frontend/OpenMP/OMPConstants.cpp
===================================================================
--- llvm/lib/Frontend/OpenMP/OMPConstants.cpp
+++ llvm/lib/Frontend/OpenMP/OMPConstants.cpp
@@ -42,8 +42,12 @@
/// values.
///
///{
-
+// ArrayType *llvm::omp::types::KmpCriticalNameTy = nullptr;
+// PointerType *llvm::omp::types::KmpCriticalNamePtrTy = nullptr;
#define OMP_TYPE(VarName, InitValue) Type *llvm::omp::types::VarName = nullptr;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
+ ArrayType *llvm::omp::types::VarName##Ty = nullptr; \
+ PointerType *llvm::omp::types::VarName##PtrTy = nullptr;
#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
FunctionType *llvm::omp::types::VarName = nullptr; \
PointerType *llvm::omp::types::VarName##Ptr = nullptr;
@@ -59,10 +63,16 @@
return;
LLVMContext &Ctx = M.getContext();
+ // KmpCriticalNameTy = ArrayType::get(
+ // Type::getInt32Ty(M.getContext()),/*NumElements*/ 8);
+ // KmpCriticalNamePtrTy = PointerType::getUnqual(KmpCriticalNameTy);
// Create all simple and struct types exposed by the runtime and remember
// the llvm::PointerTypes of them for easy access later.
StructType *T;
#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
+ VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
+ VarName##PtrTy = PointerType::getUnqual(VarName##Ty);
#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
VarName##Ptr = PointerType::getUnqual(VarName);
Index: llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -122,6 +122,24 @@
///}
+/// array types
+///
+///{
+
+#ifndef OMP_ARRAY_TYPE
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
+#endif
+
+#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
+ OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
+
+__OMP_ARRAY_TYPE(KmpCriticalName, Int32, 8)
+
+#undef __OMP_ARRAY_TYPE
+#undef OMP_ARRAY_TYPE
+
+///}
+
/// Struct and function types
///
///{
@@ -176,6 +194,12 @@
__OMP_RTL(omp_get_thread_num, false, Int32, )
+__OMP_RTL(__kmpc_omp_master, false, Int32, IdentPtr, Int32)
+__OMP_RTL(__kmpc_omp_end_master, false, Void, IdentPtr, Int32)
+__OMP_RTL(__kmpc_omp_critical, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy)
+__OMP_RTL(__kmpc_omp_critical_with_hint, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy, Int32)
+__OMP_RTL(__kmpc_omp_end_critical, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy)
+
#undef __OMP_RTL
#undef OMP_RTL
Index: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -243,6 +243,110 @@
/// Map to remember existing ident_t*.
DenseMap<std::pair<Constant *, uint64_t>, GlobalVariable *> IdentMap;
+
+ /// An ordered map of auto-generated variables to their unique names.
+ /// It stores variables with the following names: 1) ".gomp_critical_user_" +
+ /// <critical_section_name> + ".var" for "omp critical" directives; 2)
+ /// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
+ /// variables.
+ StringMap<AssertingVH<Constant>, BumpPtrAllocator> InternalVars;
+
+public:
+ /// Generator for '#omp master'
+ ///
+ /// \param Loc The insert and source location description.
+ /// \param BodyGenCB Callback that will generate the region code.
+ ///
+ /// \returns The insertion position *after* the master.
+ InsertPointTy CreateMaster(const LocationDescription &Loc,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB);
+
+ /// Generator for '#omp master'
+ ///
+ /// \param Loc The insert and source location description.
+ /// \param BodyGenCB Callback that will generate the region code.
+ /// \param CriticalName name of the lock used by the critical directive
+ /// \param hasHint whether there is ahint clause associated with critical
+ /// \param FiniCB Callback to finalize variable copies.
+ ///
+ /// \returns The insertion position *after* the master.
+ InsertPointTy CreateCritical(const LocationDescription &Loc,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB,
+ StringRef CriticalName, Value *HintInst);
+
+private:
+ /// Common interface for generating entry calls for OMP Directives.
+ /// if the directive has a region/body, It will set the insertion
+ /// point to the body
+ ///
+ /// \param OMPD Directive to generate entry blocks for
+ /// \param EntryCall Call to the entry OMP Runtime Function
+ /// \param ExitBB block where the region ends.
+ /// \param Conditional indicate if the entry call result will be used
+ /// to evaluate a conditional of whether a thread will execute
+ /// body code or not.
+ ///
+ /// \return The insertion position in exit block
+ InsertPointTy emitCommonDirectiveEntry(omp::Directive OMPD,
+ llvm::Value *EntryCall,
+ BasicBlock *ExitBB,
+ bool conditional = false);
+
+ /// Common interface to finalize the region
+ ///
+ /// \param OMPD Directive to generate exiting code for
+ /// \param IP Insertion point for emitting Finalization code and exit call
+ /// \param ExitBB Exit BasicBlock for OMP region
+ /// \param ExitCall Call to the ending OMP Runtime Function
+ /// \param hasFinalize indicate if the directive will require finalization
+ /// and has a finalization callback in the stack that
+ /// should be
+ /// called.
+ ///
+ /// \return The insertion position in exit block
+ InsertPointTy emitCommonDirectiveExit(omp::Directive OMPD, InsertPointTy IP,
+ BasicBlock *ExitBB,
+ Instruction *ExitCall,
+ bool hasFinalize);
+
+ /// Common Interface to generate OMP inlined regions
+ ///
+ /// \param OMPD Directive to generate inlined region for
+ /// \param EntryCall Call to the entry OMP Runtime Function
+ /// \param ExitCall Call to the ending OMP Runtime Function
+ /// \param BodyGenCB Body code generation callback.
+ /// \param FiniCB Finalization Callback. Will be called when finalizing region
+ /// \param Conditional indicate if the entry call result will be used
+ /// to evaluate a conditional of whether a thread will execute
+ /// body code or not.
+ /// \param hasFinalize indicate if the directive will require finalization
+ /// and has a finalization callback in the stack that
+ /// should be
+ /// called.
+ ///
+ /// \return The insertion point after the region
+
+ InsertPointTy EmitOMPInlinedRegion(omp::Directive OMPD,
+ Instruction *EntryCall,
+ Instruction *ExitCall,
+ BodyGenCallbackTy BodyGenCB,
+ FinalizeCallbackTy FiniCB,
+ bool conditional, bool hasFinalize);
+
+ std::string getName(ArrayRef<StringRef> Parts, StringRef FirstSeparator,
+ StringRef Separator) const;
+
+ Constant *getOrCreateOMPInternalVariable(llvm::Type *Ty,
+ const llvm::Twine &Name,
+ unsigned AddressSpace = 0);
+
+ Value *getOMPCriticalRegionLock(StringRef CriticalName);
+
+ llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
+ const llvm::Twine &Name,
+ unsigned AddressSpace);
};
} // end namespace llvm
Index: llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
===================================================================
--- llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
+++ llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
@@ -20,6 +20,7 @@
namespace llvm {
class Type;
class Module;
+class ArrayType;
class StructType;
class PointerType;
class FunctionType;
@@ -84,7 +85,14 @@
///{
namespace types {
+/// Type for kmp_critical_name[8], and related pointer type;
+// extern ArrayType *KmpCriticalNameTy;
+// extern PointerType *KmpCriticalNamePtrTy;
+
#define OMP_TYPE(VarName, InitValue) extern Type *VarName;
+#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
+ extern ArrayType *VarName##Ty; \
+ extern PointerType *VarName##PtrTy;
#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
extern FunctionType *VarName; \
extern PointerType *VarName##Ptr;
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1319,7 +1319,6 @@
llvm::SmallVectorImpl<llvm::Value *> &) {}
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
-
if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
// Check if we have any if clause associated with the directive.
llvm::Value *IfCond = nullptr;
@@ -2991,11 +2990,121 @@
}
void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
+ if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+ const Stmt *MasterRegionBodyStmt =
+ S.getInnermostCapturedStmt()->getCapturedStmt();
+ auto FiniCB = [this](InsertPointTy IP) {
+ CGBuilderTy::InsertPointGuard IPG(Builder);
+ assert(IP.getBlock()->end() != IP.getPoint() &&
+ "OpenMP IR Builder should cause terminated block!");
+
+ llvm::BasicBlock *IPBB = IP.getBlock();
+ llvm::BranchInst *IPBBTI =
+ llvm::dyn_cast<llvm::BranchInst>(IPBB->getTerminator());
+ llvm::BasicBlock *DestBB = IPBBTI->getSuccessor(0);
+
+ // erase and replace with cleanup branch.
+ IPBB->getTerminator()->eraseFromParent();
+ Builder.SetInsertPoint(IPBB);
+ CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
+ EmitBranchThroughCleanup(Dest);
+ };
+
+ auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ auto OldAllocaIP = AllocaInsertPt;
+ if (AllocaIP.isSet())
+ AllocaInsertPt = &*AllocaIP.getPoint();
+ auto OldReturnBlock = ReturnBlock;
+ ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
+
+ llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+ if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
+ CodeGenIPBBTI->eraseFromParent();
+
+ Builder.SetInsertPoint(CodeGenIPBB);
+
+ EmitStmt(MasterRegionBodyStmt);
+
+ Builder.CreateBr(&FiniBB);
+
+ AllocaInsertPt = OldAllocaIP;
+ ReturnBlock = OldReturnBlock;
+ };
+
+ Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB));
+
+ return;
+ }
OMPLexicalScope Scope(*this, S, OMPD_unknown);
emitMaster(*this, S);
}
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
+ if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+ const Stmt *CriticalRegionBodyStmt =
+ S.getInnermostCapturedStmt()->getCapturedStmt();
+ const Expr *Hint = nullptr;
+ if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
+ Hint = HintClause->getHint();
+
+ // TODO: Fix the type when everything about typing is final.
+ llvm::Value *HintInst =
+ (!Hint)
+ ? nullptr
+ : Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
+
+ auto FiniCB = [this](InsertPointTy IP) {
+ CGBuilderTy::InsertPointGuard IPG(Builder);
+ assert(IP.getBlock()->end() != IP.getPoint() &&
+ "OpenMP IR Builder should cause terminated block!");
+ llvm::BasicBlock *IPBB = IP.getBlock();
+ llvm::BranchInst *IPBBTI =
+ llvm::dyn_cast<llvm::BranchInst>(IPBB->getTerminator());
+ llvm::BasicBlock *DestBB = IPBBTI->getSuccessor(0);
+
+ // erase and replace with cleanup branch.
+ IPBB->getTerminator()->eraseFromParent();
+ Builder.SetInsertPoint(IPBB);
+ CodeGenFunction::JumpDest Dest = getJumpDestInCurrentScope(DestBB);
+ EmitBranchThroughCleanup(Dest);
+ };
+
+ auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ auto OldAllocaIP = AllocaInsertPt;
+ if (AllocaIP.isSet())
+ AllocaInsertPt = &*AllocaIP.getPoint();
+ auto OldReturnBlock = ReturnBlock;
+ ReturnBlock = getJumpDestInCurrentScope(&FiniBB);
+
+ llvm::BasicBlock *CodeGenIPBB = CodeGenIP.getBlock();
+ if (llvm::Instruction *CodeGenIPBBTI = CodeGenIPBB->getTerminator())
+ CodeGenIPBBTI->eraseFromParent();
+
+ Builder.SetInsertPoint(CodeGenIPBB);
+
+ EmitStmt(CriticalRegionBodyStmt);
+
+ Builder.CreateBr(&FiniBB);
+
+ AllocaInsertPt = OldAllocaIP;
+ ReturnBlock = OldReturnBlock;
+ };
+
+ Builder.restoreIP(OMPBuilder->CreateCritical(
+ Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(),
+ HintInst));
+
+ return;
+ }
+
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits