19
19
// ===----------------------------------------------------------------------===//
20
20
21
21
#include " llvm/Transforms/Coroutines/CoroSplit.h"
22
- #include " ABI.h"
23
22
#include " CoroInstr.h"
24
23
#include " CoroInternal.h"
25
- #include " MaterializationUtils.h"
26
24
#include " llvm/ADT/DenseMap.h"
27
25
#include " llvm/ADT/PriorityWorklist.h"
28
26
#include " llvm/ADT/SmallPtrSet.h"
@@ -1781,9 +1779,9 @@ CallInst *coro::createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
1781
1779
return TailCall;
1782
1780
}
1783
1781
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) {
1787
1785
assert (Shape.ABI == coro::ABI::Async);
1788
1786
assert (Clones.empty ());
1789
1787
// Reset various things that the optimizer might have decided it
@@ -1876,9 +1874,9 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
1876
1874
}
1877
1875
}
1878
1876
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) {
1882
1880
assert (Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
1883
1881
assert (Clones.empty ());
1884
1882
@@ -2046,27 +2044,26 @@ static bool hasSafeElideCaller(Function &F) {
2046
2044
return false ;
2047
2045
}
2048
2046
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) {
2057
2051
PrettyStackTraceFunction prettyStackTrace (F);
2058
2052
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;
2061
2060
2062
2061
lowerAwaitSuspends (F, Shape);
2063
2062
2064
2063
simplifySuspendPoints (Shape);
2065
-
2066
2064
normalizeCoroutine (F, Shape, TTI);
2067
- ABI. buildCoroutineFrame ();
2065
+ buildCoroutineFrame (F, Shape, MaterializableCallback );
2068
2066
replaceFrameSizeAndAlignment (Shape);
2069
-
2070
2067
bool isNoSuspendCoroutine = Shape.CoroSuspends .empty ();
2071
2068
2072
2069
bool shouldCreateNoAllocVariant = !isNoSuspendCoroutine &&
@@ -2078,7 +2075,18 @@ static void doSplitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
2078
2075
if (isNoSuspendCoroutine) {
2079
2076
handleNoSuspendCoroutine (Shape);
2080
2077
} 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
+ }
2082
2090
}
2083
2091
2084
2092
// Replace all the swifterror operations in the original function.
@@ -2099,6 +2107,8 @@ static void doSplitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
2099
2107
2100
2108
if (shouldCreateNoAllocVariant)
2101
2109
SwitchCoroutineSplitter::createNoAllocVariant (F, Shape, Clones);
2110
+
2111
+ return Shape;
2102
2112
}
2103
2113
2104
2114
static LazyCallGraph::SCC &updateCallGraphAfterCoroutineSplit (
@@ -2197,44 +2207,8 @@ static void addPrepareFunction(const Module &M,
2197
2207
Fns.push_back (PrepareFn);
2198
2208
}
2199
2209
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
-
2220
2210
CoroSplitPass::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),
2238
2212
OptimizeFrame(OptimizeFrame) {}
2239
2213
2240
2214
PreservedAnalyses CoroSplitPass::run (LazyCallGraph::SCC &C,
@@ -2267,23 +2241,12 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
2267
2241
Function &F = N->getFunction ();
2268
2242
LLVM_DEBUG (dbgs () << " CoroSplit: Processing coroutine '" << F.getName ()
2269
2243
<< " \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
-
2280
2244
F.setSplittedCoroutine ();
2281
2245
2282
- std::unique_ptr<coro::BaseABI> ABI = CreateAndInitABI (F, Shape);
2283
-
2284
2246
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);
2287
2250
CurrentSCC = &updateCallGraphAfterCoroutineSplit (
2288
2251
*N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
2289
2252
0 commit comments