diff options
author | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2023-01-06 16:34:48 +0800 |
---|---|---|
committer | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2023-01-06 16:38:07 +0800 |
commit | 65e339886989a995c196a6413e8e919a20cc738c (patch) | |
tree | ac656cb89c18f6abf99c9d91ae9966d7f70862db /llvm/lib/Transforms | |
parent | d6acd0196b3378bdeb5193053e290d7194c4f72d (diff) | |
download | llvm-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.cpp | 73 |
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. |