aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-12-25 22:30:44 +0000
commit77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (patch)
tree5c0eb39553003b9c75a901af6bc4ddabd6f2f28c /llvm/lib/Transforms/Coroutines/CoroFrame.cpp
parentf65dcba83ce5035ab88a85fe17628b447eb56e1b (diff)
Diffstat (limited to 'llvm/lib/Transforms/Coroutines/CoroFrame.cpp')
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroFrame.cpp33
1 files changed, 26 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index ac3d078714ce..a0d12865bd3a 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -1237,8 +1237,10 @@ namespace {
struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
using Base = PtrUseVisitor<AllocaUseVisitor>;
AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT,
- const CoroBeginInst &CB, const SuspendCrossingInfo &Checker)
- : PtrUseVisitor(DL), DT(DT), CoroBegin(CB), Checker(Checker) {}
+ const CoroBeginInst &CB, const SuspendCrossingInfo &Checker,
+ bool ShouldUseLifetimeStartInfo)
+ : PtrUseVisitor(DL), DT(DT), CoroBegin(CB), Checker(Checker),
+ ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {}
void visit(Instruction &I) {
Users.insert(&I);
@@ -1390,6 +1392,7 @@ private:
SmallPtrSet<Instruction *, 4> Users{};
SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{};
bool MayWriteBeforeCoroBegin{false};
+ bool ShouldUseLifetimeStartInfo{true};
mutable llvm::Optional<bool> ShouldLiveOnFrame{};
@@ -1398,7 +1401,7 @@ private:
// more precise. We look at every pair of lifetime.start intrinsic and
// every basic block that uses the pointer to see if they cross suspension
// points. The uses cover both direct uses as well as indirect uses.
- if (!LifetimeStarts.empty()) {
+ if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) {
for (auto *I : Users)
for (auto *S : LifetimeStarts)
if (Checker.isDefinitionAcrossSuspend(*S, I))
@@ -2484,8 +2487,15 @@ static void collectFrameAllocas(Function &F, coro::Shape &Shape,
continue;
}
DominatorTree DT(F);
+ // The code that uses lifetime.start intrinsic does not work for functions
+ // with loops without exit. Disable it on ABIs we know to generate such
+ // code.
+ bool ShouldUseLifetimeStartInfo =
+ (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon &&
+ Shape.ABI != coro::ABI::RetconOnce);
AllocaUseVisitor Visitor{F.getParent()->getDataLayout(), DT,
- *Shape.CoroBegin, Checker};
+ *Shape.CoroBegin, Checker,
+ ShouldUseLifetimeStartInfo};
Visitor.visitPtr(*AI);
if (!Visitor.getShouldLiveOnFrame())
continue;
@@ -2572,9 +2582,15 @@ void coro::salvageDebugInfo(
DVI->setExpression(Expr);
/// It makes no sense to move the dbg.value intrinsic.
if (!isa<DbgValueInst>(DVI)) {
- if (auto *InsertPt = dyn_cast<Instruction>(Storage))
+ if (auto *II = dyn_cast<InvokeInst>(Storage))
+ DVI->moveBefore(II->getNormalDest()->getFirstNonPHI());
+ else if (auto *CBI = dyn_cast<CallBrInst>(Storage))
+ DVI->moveBefore(CBI->getDefaultDest()->getFirstNonPHI());
+ else if (auto *InsertPt = dyn_cast<Instruction>(Storage)) {
+ assert(!InsertPt->isTerminator() &&
+ "Unimaged terminator that could return a storage.");
DVI->moveAfter(InsertPt);
- else if (isa<Argument>(Storage))
+ } else if (isa<Argument>(Storage))
DVI->moveAfter(F->getEntryBlock().getFirstNonPHI());
}
}
@@ -2664,7 +2680,10 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
}
}
- sinkLifetimeStartMarkers(F, Shape, Checker);
+ if (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon &&
+ Shape.ABI != coro::ABI::RetconOnce)
+ sinkLifetimeStartMarkers(F, Shape, Checker);
+
if (Shape.ABI != coro::ABI::Async || !Shape.CoroSuspends.empty())
collectFrameAllocas(F, Shape, Checker, FrameData.Allocas);
LLVM_DEBUG(dumpAllocas(FrameData.Allocas));