diff options
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. |