1919// ===----------------------------------------------------------------------===//
2020
2121#include " llvm/Transforms/Coroutines/CoroSplit.h"
22- #include " ABI.h"
2322#include " CoroInstr.h"
2423#include " CoroInternal.h"
25- #include " MaterializationUtils.h"
2624#include " llvm/ADT/DenseMap.h"
2725#include " llvm/ADT/PriorityWorklist.h"
2826#include " llvm/ADT/SmallPtrSet.h"
@@ -1781,9 +1779,9 @@ CallInst *coro::createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
17811779 return TailCall;
17821780}
17831781
1784- void coro::AsyncABI::splitCoroutine (Function &F, coro::Shape &Shape,
1785- SmallVectorImpl<Function *> &Clones,
1786- TargetTransformInfo &TTI) {
1782+ static void splitAsyncCoroutine (Function &F, coro::Shape &Shape,
1783+ SmallVectorImpl<Function *> &Clones,
1784+ TargetTransformInfo &TTI) {
17871785 assert (Shape.ABI == coro::ABI::Async);
17881786 assert (Clones.empty ());
17891787 // Reset various things that the optimizer might have decided it
@@ -1876,9 +1874,9 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
18761874 }
18771875}
18781876
1879- void coro::AnyRetconABI::splitCoroutine (Function &F, coro::Shape &Shape,
1880- SmallVectorImpl<Function *> &Clones,
1881- TargetTransformInfo &TTI) {
1877+ static void splitRetconCoroutine (Function &F, coro::Shape &Shape,
1878+ SmallVectorImpl<Function *> &Clones,
1879+ TargetTransformInfo &TTI) {
18821880 assert (Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
18831881 assert (Clones.empty ());
18841882
@@ -2046,27 +2044,26 @@ static bool hasSafeElideCaller(Function &F) {
20462044 return false ;
20472045}
20482046
2049- void coro::SwitchABI::splitCoroutine (Function &F, coro::Shape &Shape,
2050- SmallVectorImpl<Function *> &Clones,
2051- TargetTransformInfo &TTI) {
2052- SwitchCoroutineSplitter::split (F, Shape, Clones, TTI);
2053- }
2054-
2055- static void doSplitCoroutine (Function &F, SmallVectorImpl<Function *> &Clones,
2056- coro::BaseABI &ABI, TargetTransformInfo &TTI) {
2047+ static coro::Shape
2048+ splitCoroutine (Function &F, SmallVectorImpl<Function *> &Clones,
2049+ TargetTransformInfo &TTI, bool OptimizeFrame,
2050+ std::function<bool (Instruction &)> MaterializableCallback) {
20572051 PrettyStackTraceFunction prettyStackTrace (F);
20582052
2059- auto &Shape = ABI.Shape ;
2060- assert (Shape.CoroBegin );
2053+ // The suspend-crossing algorithm in buildCoroutineFrame get tripped
2054+ // up by uses in unreachable blocks, so remove them as a first pass.
2055+ removeUnreachableBlocks (F);
2056+
2057+ coro::Shape Shape (F, OptimizeFrame);
2058+ if (!Shape.CoroBegin )
2059+ return Shape;
20612060
20622061 lowerAwaitSuspends (F, Shape);
20632062
20642063 simplifySuspendPoints (Shape);
2065-
20662064 normalizeCoroutine (F, Shape, TTI);
2067- ABI. buildCoroutineFrame ();
2065+ buildCoroutineFrame (F, Shape, MaterializableCallback );
20682066 replaceFrameSizeAndAlignment (Shape);
2069-
20702067 bool isNoSuspendCoroutine = Shape.CoroSuspends .empty ();
20712068
20722069 bool shouldCreateNoAllocVariant = !isNoSuspendCoroutine &&
@@ -2078,7 +2075,18 @@ static void doSplitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
20782075 if (isNoSuspendCoroutine) {
20792076 handleNoSuspendCoroutine (Shape);
20802077 } else {
2081- ABI.splitCoroutine (F, Shape, Clones, TTI);
2078+ switch (Shape.ABI ) {
2079+ case coro::ABI::Switch:
2080+ SwitchCoroutineSplitter::split (F, Shape, Clones, TTI);
2081+ break ;
2082+ case coro::ABI::Async:
2083+ splitAsyncCoroutine (F, Shape, Clones, TTI);
2084+ break ;
2085+ case coro::ABI::Retcon:
2086+ case coro::ABI::RetconOnce:
2087+ splitRetconCoroutine (F, Shape, Clones, TTI);
2088+ break ;
2089+ }
20822090 }
20832091
20842092 // Replace all the swifterror operations in the original function.
@@ -2099,6 +2107,8 @@ static void doSplitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
20992107
21002108 if (shouldCreateNoAllocVariant)
21012109 SwitchCoroutineSplitter::createNoAllocVariant (F, Shape, Clones);
2110+
2111+ return Shape;
21022112}
21032113
21042114static LazyCallGraph::SCC &updateCallGraphAfterCoroutineSplit (
@@ -2197,44 +2207,8 @@ static void addPrepareFunction(const Module &M,
21972207 Fns.push_back (PrepareFn);
21982208}
21992209
2200- static std::unique_ptr<coro::BaseABI>
2201- CreateNewABI (Function &F, coro::Shape &S,
2202- std::function<bool (Instruction &)> IsMatCallback) {
2203- switch (S.ABI ) {
2204- case coro::ABI::Switch:
2205- return std::unique_ptr<coro::BaseABI>(
2206- new coro::SwitchABI (F, S, IsMatCallback));
2207- case coro::ABI::Async:
2208- return std::unique_ptr<coro::BaseABI>(
2209- new coro::AsyncABI (F, S, IsMatCallback));
2210- case coro::ABI::Retcon:
2211- return std::unique_ptr<coro::BaseABI>(
2212- new coro::AnyRetconABI (F, S, IsMatCallback));
2213- case coro::ABI::RetconOnce:
2214- return std::unique_ptr<coro::BaseABI>(
2215- new coro::AnyRetconABI (F, S, IsMatCallback));
2216- }
2217- llvm_unreachable (" Unknown ABI" );
2218- }
2219-
22202210CoroSplitPass::CoroSplitPass (bool OptimizeFrame)
2221- : CreateAndInitABI([](Function &F, coro::Shape &S) {
2222- std::unique_ptr<coro::BaseABI> ABI =
2223- CreateNewABI (F, S, coro::isTriviallyMaterializable);
2224- ABI->init ();
2225- return std::move (ABI);
2226- }),
2227- OptimizeFrame (OptimizeFrame) {}
2228-
2229- // For back compatibility, constructor takes a materializable callback and
2230- // creates a generator for an ABI with a modified materializable callback.
2231- CoroSplitPass::CoroSplitPass (std::function<bool (Instruction &)> IsMatCallback,
2232- bool OptimizeFrame)
2233- : CreateAndInitABI([=](Function &F, coro::Shape &S) {
2234- std::unique_ptr<coro::BaseABI> ABI = CreateNewABI (F, S, IsMatCallback);
2235- ABI->init ();
2236- return std::move (ABI);
2237- }),
2211+ : MaterializableCallback(coro::defaultMaterializable),
22382212 OptimizeFrame(OptimizeFrame) {}
22392213
22402214PreservedAnalyses CoroSplitPass::run (LazyCallGraph::SCC &C,
@@ -2267,23 +2241,12 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
22672241 Function &F = N->getFunction ();
22682242 LLVM_DEBUG (dbgs () << " CoroSplit: Processing coroutine '" << F.getName ()
22692243 << " \n " );
2270-
2271- // The suspend-crossing algorithm in buildCoroutineFrame gets tripped up
2272- // by unreachable blocks, so remove them as a first pass. Remove the
2273- // unreachable blocks before collecting intrinsics into Shape.
2274- removeUnreachableBlocks (F);
2275-
2276- coro::Shape Shape (F, OptimizeFrame);
2277- if (!Shape.CoroBegin )
2278- continue ;
2279-
22802244 F.setSplittedCoroutine ();
22812245
2282- std::unique_ptr<coro::BaseABI> ABI = CreateAndInitABI (F, Shape);
2283-
22842246 SmallVector<Function *, 4 > Clones;
2285- auto &TTI = FAM.getResult <TargetIRAnalysis>(F);
2286- doSplitCoroutine (F, Clones, *ABI, TTI);
2247+ coro::Shape Shape =
2248+ splitCoroutine (F, Clones, FAM.getResult <TargetIRAnalysis>(F),
2249+ OptimizeFrame, MaterializableCallback);
22872250 CurrentSCC = &updateCallGraphAfterCoroutineSplit (
22882251 *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
22892252
0 commit comments