summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h54
-rw-r--r--llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp18
-rw-r--r--llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp19
3 files changed, 75 insertions, 16 deletions
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a8cb3dfb39a..933b0a2ceec 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -37,12 +37,44 @@ public:
/// Add attributes known for \p FnID to \p Fn.
void addAttributes(omp::RuntimeFunction FnID, Function &Fn);
- /// Set the cancellation block to \p CBB.
- void setCancellationBlock(BasicBlock *CBB) { CancellationBlock = CBB; }
-
/// Type used throughout for insertion points.
using InsertPointTy = IRBuilder<>::InsertPoint;
+ /// Callback type for variable finalization (think destructors).
+ ///
+ /// \param CodeGenIP is the insertion point at which the finalization code
+ /// should be placed.
+ ///
+ /// A finalize callback knows about all objects that need finalization, e.g.
+ /// destruction, when the scope of the currently generated construct is left
+ /// at the time, and location, the callback is invoked.
+ using FinalizeCallbackTy = std::function<void(InsertPointTy /* CodeGenIP */)>;
+
+ struct FinalizationInfo {
+ /// The finalization callback provided by the last in-flight invocation of
+ /// CreateXXXX for the directive of kind DK.
+ FinalizeCallbackTy FiniCB;
+
+ /// The directive kind of the innermost directive that has an associated
+ /// region which might require finalization when it is left.
+ omp::Directive DK;
+
+ /// Flag to indicate if the directive is cancellable.
+ bool IsCancellable;
+ };
+
+ /// Push a finalization callback on the finalization stack.
+ ///
+ /// NOTE: Temporary solution until Clang CG is gone.
+ void pushFinalizationCB(const FinalizationInfo &FI) {
+ FinalizationStack.push_back(FI);
+ }
+
+ /// Pop the last finalization callback from the finalization stack.
+ ///
+ /// NOTE: Temporary solution until Clang CG is gone.
+ void popFinalizationCB() { FinalizationStack.pop_back(); }
+
/// Description of a LLVM-IR insertion point (IP) and a debug/source location
/// (filename, line, column, ...).
struct LocationDescription {
@@ -112,6 +144,19 @@ private:
omp::Directive DK, bool ForceSimpleCall,
bool CheckCancelFlag);
+ /// The finalization stack made up of finalize callbacks currently in-flight,
+ /// wrapped into FinalizationInfo objects that reference also the finalization
+ /// target block and the kind of cancellable directive.
+ SmallVector<FinalizationInfo, 8> FinalizationStack;
+
+ /// Return true if the last entry in the finalization stack is of kind \p DK
+ /// and cancellable.
+ bool isLastFinalizationInfoCancellable(omp::Directive DK) {
+ return !FinalizationStack.empty() &&
+ FinalizationStack.back().IsCancellable &&
+ FinalizationStack.back().DK == DK;
+ }
+
/// Return the current thread ID.
///
/// \param Ident The ident (ident_t*) describing the query origin.
@@ -123,9 +168,6 @@ private:
/// The LLVM-IR Builder used to create IR.
IRBuilder<> Builder;
- /// TODO: Stub for a cancellation block stack.
- BasicBlock *CancellationBlock = nullptr;
-
/// Map to remember source location strings
StringMap<Constant *> SrcLocStrMap;
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 13733394b07..4c173e032e8 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -205,7 +205,8 @@ OpenMPIRBuilder::emitBarrierImpl(const LocationDescription &Loc, Directive Kind,
// If we are in a cancellable parallel region, barriers are cancellation
// points.
// TODO: Check why we would force simple calls or to ignore the cancel flag.
- bool UseCancelBarrier = !ForceSimpleCall && CancellationBlock;
+ bool UseCancelBarrier =
+ !ForceSimpleCall && isLastFinalizationInfoCancellable(OMPD_parallel);
Value *Result = Builder.CreateCall(
getOrCreateRuntimeFunction(UseCancelBarrier ? OMPRTL___kmpc_cancel_barrier
@@ -217,19 +218,22 @@ OpenMPIRBuilder::emitBarrierImpl(const LocationDescription &Loc, Directive Kind,
BasicBlock *BB = Builder.GetInsertBlock();
BasicBlock *NonCancellationBlock = BasicBlock::Create(
BB->getContext(), BB->getName() + ".cont", BB->getParent());
+ BasicBlock *CancellationBlock = BasicBlock::Create(
+ BB->getContext(), BB->getName() + ".cncl", BB->getParent());
// Jump to them based on the return value.
Value *Cmp = Builder.CreateIsNull(Result);
Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
/* TODO weight */ nullptr, nullptr);
- Builder.SetInsertPoint(NonCancellationBlock);
- assert(CancellationBlock->getParent() == BB->getParent() &&
- "Unexpected cancellation block parent!");
+ // From the cancellation block we finalize all variables and go to the
+ // post finalization block that is known to the FiniCB callback.
+ Builder.SetInsertPoint(CancellationBlock);
+ auto &FI = FinalizationStack.back();
+ FI.FiniCB(Builder.saveIP());
- // TODO: This is a workaround for now, we always reset the cancellation
- // block until we manage it ourselves here.
- CancellationBlock = nullptr;
+ // The continuation block is where code generation continues.
+ Builder.SetInsertPoint(NonCancellationBlock);
}
return Builder.saveIP();
diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index 3c960c431b5..39dd83232d9 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -104,7 +104,15 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
BasicBlock *CBB = BasicBlock::Create(Ctx, "", F);
new UnreachableInst(Ctx, CBB);
- OMPBuilder.setCancellationBlock(CBB);
+ auto FiniCB = [CBB](llvm::OpenMPIRBuilder::InsertPointTy IP) {
+ assert(IP.getBlock()->end() == IP.getPoint() &&
+ "Clang CG should cause non-terminated block!");
+ BranchInst::Create(CBB, IP.getBlock());
+ };
+ // Emulate an outer parallel.
+ llvm::OpenMPIRBuilder::FinalizationInfo FI(
+ {FiniCB, OMPD_parallel, /* HasCancel */ true});
+ OMPBuilder.pushFinalizationCB(std::move(FI));
IRBuilder<> Builder(BB);
@@ -113,7 +121,7 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
Builder.restoreIP(NewIP);
EXPECT_FALSE(M->global_empty());
EXPECT_EQ(M->size(), 3U);
- EXPECT_EQ(F->size(), 3U);
+ EXPECT_EQ(F->size(), 4U);
EXPECT_EQ(BB->size(), 4U);
CallInst *GTID = dyn_cast<CallInst>(&BB->front());
@@ -133,10 +141,15 @@ TEST_F(OpenMPIRBuilderTest, CreateCancelBarrier) {
Instruction *BarrierBBTI = Barrier->getParent()->getTerminator();
EXPECT_EQ(BarrierBBTI->getNumSuccessors(), 2U);
EXPECT_EQ(BarrierBBTI->getSuccessor(0), NewIP.getBlock());
- EXPECT_EQ(BarrierBBTI->getSuccessor(1), CBB);
+ EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getNumSuccessors(),
+ 1U);
+ EXPECT_EQ(BarrierBBTI->getSuccessor(1)->getTerminator()->getSuccessor(0),
+ CBB);
EXPECT_EQ(cast<CallInst>(Barrier)->getArgOperand(1), GTID);
+ OMPBuilder.popFinalizationCB();
+
Builder.CreateUnreachable();
EXPECT_FALSE(verifyModule(*M));
}
OpenPOWER on IntegriCloud