aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroFrame.cpp73
1 files changed, 34 insertions, 39 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index ce350a0..b650d4b 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -2606,34 +2606,32 @@ static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape,
}
}
-static void collectFrameAllocas(Function &F, coro::Shape &Shape,
- const SuspendCrossingInfo &Checker,
- SmallVectorImpl<AllocaInfo> &Allocas) {
- const DominatorTree DT(F);
- for (Instruction &I : instructions(F)) {
- auto *AI = dyn_cast<AllocaInst>(&I);
- if (!AI)
- continue;
- // The PromiseAlloca will be specially handled since it needs to be in a
- // fixed position in the frame.
- if (AI == Shape.SwitchLowering.PromiseAlloca) {
- continue;
- }
- // 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,
- ShouldUseLifetimeStartInfo};
- Visitor.visitPtr(*AI);
- if (!Visitor.getShouldLiveOnFrame())
- continue;
- Allocas.emplace_back(AI, Visitor.getAliasesCopy(),
- Visitor.getMayWriteBeforeCoroBegin());
- }
+static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape,
+ const SuspendCrossingInfo &Checker,
+ SmallVectorImpl<AllocaInfo> &Allocas,
+ const DominatorTree &DT) {
+ if (Shape.CoroSuspends.empty())
+ return;
+
+ // The PromiseAlloca will be specially handled since it needs to be in a
+ // fixed position in the frame.
+ if (AI == Shape.SwitchLowering.PromiseAlloca)
+ return;
+
+ // 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{AI->getModule()->getDataLayout(), DT,
+ *Shape.CoroBegin, Checker,
+ ShouldUseLifetimeStartInfo};
+ Visitor.visitPtr(*AI);
+ if (!Visitor.getShouldLiveOnFrame())
+ return;
+ Allocas.emplace_back(AI, Visitor.getAliasesCopy(),
+ Visitor.getMayWriteBeforeCoroBegin());
}
void coro::salvageDebugInfo(
@@ -2786,6 +2784,8 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
SpillInfo Spills;
for (int Repeat = 0; Repeat < 4; ++Repeat) {
// See if there are materializable instructions across suspend points.
+ // FIXME: We can use a worklist to track the possible materialize
+ // instructions instead of iterating the whole function again and again.
for (Instruction &I : instructions(F))
if (materializable(I)) {
for (User *U : I.users())
@@ -2808,28 +2808,19 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
Shape.ABI != coro::ABI::RetconOnce)
sinkLifetimeStartMarkers(F, Shape, Checker);
- if (Shape.ABI == coro::ABI::Switch || !Shape.CoroSuspends.empty())
- collectFrameAllocas(F, Shape, Checker, FrameData.Allocas);
- LLVM_DEBUG(dumpAllocas(FrameData.Allocas));
-
// Collect the spills for arguments and other not-materializable values.
for (Argument &A : F.args())
for (User *U : A.users())
if (Checker.isDefinitionAcrossSuspend(A, U))
FrameData.Spills[&A].push_back(cast<Instruction>(U));
+ const DominatorTree DT(F);
for (Instruction &I : instructions(F)) {
// Values returned from coroutine structure intrinsics should not be part
// of the Coroutine Frame.
if (isCoroutineStructureIntrinsic(I) || &I == Shape.CoroBegin)
continue;
- // The Coroutine Promise always included into coroutine frame, no need to
- // check for suspend crossing.
- if (Shape.ABI == coro::ABI::Switch &&
- Shape.SwitchLowering.PromiseAlloca == &I)
- continue;
-
// Handle alloca.alloc specially here.
if (auto AI = dyn_cast<CoroAllocaAllocInst>(&I)) {
// Check whether the alloca's lifetime is bounded by suspend points.
@@ -2856,8 +2847,10 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
if (isa<CoroAllocaGetInst>(I))
continue;
- if (isa<AllocaInst>(I))
+ if (auto *AI = dyn_cast<AllocaInst>(&I)) {
+ collectFrameAlloca(AI, Shape, Checker, FrameData.Allocas, DT);
continue;
+ }
for (User *U : I.users())
if (Checker.isDefinitionAcrossSuspend(I, U)) {
@@ -2869,6 +2862,8 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
}
}
+ LLVM_DEBUG(dumpAllocas(FrameData.Allocas));
+
// We don't want the layout of coroutine frame to be affected
// by debug information. So we only choose to salvage DbgValueInst for
// whose value is already in the frame.