aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2023-01-06 16:34:48 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2023-01-06 16:38:07 +0800
commit65e339886989a995c196a6413e8e919a20cc738c (patch)
treeac656cb89c18f6abf99c9d91ae9966d7f70862db /llvm/lib/Transforms
parentd6acd0196b3378bdeb5193053e290d7194c4f72d (diff)
downloadllvm-65e339886989a995c196a6413e8e919a20cc738c.zip
llvm-65e339886989a995c196a6413e8e919a20cc738c.tar.gz
llvm-65e339886989a995c196a6413e8e919a20cc738c.tar.bz2
[NFC] [Coroutines] Move collectFrameAlloca to decrease the times to iterate the function
Previously in collectFrameAllocas, we will iterate every instruction in the Function and we will iterate the function again later. It is redundnt.
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.