2020
2121#include " llvm/Transforms/Coroutines/CoroSplit.h"
2222#include " CoroInternal.h"
23+ #include " CoroCloner.h"
2324#include " llvm/ADT/DenseMap.h"
2425#include " llvm/ADT/PriorityWorklist.h"
2526#include " llvm/ADT/STLExtras.h"
4445#include " llvm/IR/DataLayout.h"
4546#include " llvm/IR/DerivedTypes.h"
4647#include " llvm/IR/Dominators.h"
47- #include " llvm/IR/Function.h"
4848#include " llvm/IR/GlobalValue.h"
4949#include " llvm/IR/GlobalVariable.h"
50- #include " llvm/IR/IRBuilder.h"
5150#include " llvm/IR/InstIterator.h"
5251#include " llvm/IR/InstrTypes.h"
5352#include " llvm/IR/Instruction.h"
6160#include " llvm/Support/Casting.h"
6261#include " llvm/Support/Debug.h"
6362#include " llvm/Support/PrettyStackTrace.h"
64- #include " llvm/Support/TimeProfiler.h"
6563#include " llvm/Support/raw_ostream.h"
66- #include " llvm/Transforms/Coroutines/ABI.h"
67- #include " llvm/Transforms/Coroutines/CoroInstr.h"
6864#include " llvm/Transforms/Coroutines/MaterializationUtils.h"
6965#include " llvm/Transforms/Scalar.h"
7066#include " llvm/Transforms/Utils/BasicBlockUtils.h"
7167#include " llvm/Transforms/Utils/CallGraphUpdater.h"
7268#include " llvm/Transforms/Utils/Cloning.h"
7369#include " llvm/Transforms/Utils/Local.h"
74- #include " llvm/Transforms/Utils/ValueMapper.h"
7570#include < cassert>
7671#include < cstddef>
7772#include < cstdint>
@@ -82,122 +77,6 @@ using namespace llvm;
8277
8378#define DEBUG_TYPE " coro-split"
8479
85- namespace {
86-
87- // / A little helper class for building
88- class CoroCloner {
89- public:
90- enum class Kind {
91- // / The shared resume function for a switch lowering.
92- SwitchResume,
93-
94- // / The shared unwind function for a switch lowering.
95- SwitchUnwind,
96-
97- // / The shared cleanup function for a switch lowering.
98- SwitchCleanup,
99-
100- // / An individual continuation function.
101- Continuation,
102-
103- // / An async resume function.
104- Async,
105- };
106-
107- private:
108- Function &OrigF;
109- Function *NewF;
110- const Twine &Suffix;
111- coro::Shape &Shape;
112- Kind FKind;
113- ValueToValueMapTy VMap;
114- IRBuilder<> Builder;
115- Value *NewFramePtr = nullptr ;
116-
117- // / The active suspend instruction; meaningful only for continuation and async
118- // / ABIs.
119- AnyCoroSuspendInst *ActiveSuspend = nullptr ;
120-
121- TargetTransformInfo &TTI;
122-
123- // / Create a cloner for a switch lowering.
124- CoroCloner (Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
125- Kind FKind, TargetTransformInfo &TTI)
126- : OrigF(OrigF), NewF(nullptr ), Suffix(Suffix), Shape(Shape), FKind(FKind),
127- Builder (OrigF.getContext()), TTI(TTI) {
128- assert (Shape.ABI == coro::ABI::Switch);
129- }
130-
131- // / Create a cloner for a continuation lowering.
132- CoroCloner (Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
133- Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
134- TargetTransformInfo &TTI)
135- : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
136- FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
137- Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) {
138- assert (Shape.ABI == coro::ABI::Retcon ||
139- Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async);
140- assert (NewF && " need existing function for continuation" );
141- assert (ActiveSuspend && " need active suspend point for continuation" );
142- }
143-
144- public:
145- // / Create a clone for a switch lowering.
146- static Function *createClone (Function &OrigF, const Twine &Suffix,
147- coro::Shape &Shape, Kind FKind,
148- TargetTransformInfo &TTI) {
149- TimeTraceScope FunctionScope (" CoroCloner" );
150-
151- CoroCloner Cloner (OrigF, Suffix, Shape, FKind, TTI);
152- Cloner.create ();
153- return Cloner.getFunction ();
154- }
155-
156- // / Create a clone for a continuation lowering.
157- static Function *createClone (Function &OrigF, const Twine &Suffix,
158- coro::Shape &Shape, Function *NewF,
159- AnyCoroSuspendInst *ActiveSuspend,
160- TargetTransformInfo &TTI) {
161- TimeTraceScope FunctionScope (" CoroCloner" );
162-
163- CoroCloner Cloner (OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
164- Cloner.create ();
165- return Cloner.getFunction ();
166- }
167-
168- Function *getFunction () const {
169- assert (NewF != nullptr && " declaration not yet set" );
170- return NewF;
171- }
172-
173- void create ();
174-
175- private:
176- bool isSwitchDestroyFunction () {
177- switch (FKind) {
178- case Kind::Async:
179- case Kind::Continuation:
180- case Kind::SwitchResume:
181- return false ;
182- case Kind::SwitchUnwind:
183- case Kind::SwitchCleanup:
184- return true ;
185- }
186- llvm_unreachable (" Unknown CoroCloner::Kind enum" );
187- }
188-
189- void replaceEntryBlock ();
190- Value *deriveNewFramePointer ();
191- void replaceRetconOrAsyncSuspendUses ();
192- void replaceCoroSuspends ();
193- void replaceCoroEnds ();
194- void replaceSwiftErrorOps ();
195- void salvageDebugInfo ();
196- void handleFinalSuspend ();
197- };
198-
199- } // end anonymous namespace
200-
20180// FIXME:
20281// Lower the intrinisc in CoroEarly phase if coroutine frame doesn't escape
20382// and it is known that other transformations, for example, sanitizers
@@ -985,11 +864,7 @@ static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context,
985864// / Clone the body of the original function into a resume function of
986865// / some sort.
987866void CoroCloner::create () {
988- // Create the new function if we don't already have one.
989- if (!NewF) {
990- NewF = createCloneDeclaration (OrigF, Shape, Suffix,
991- OrigF.getParent ()->end (), ActiveSuspend);
992- }
867+ assert (NewF);
993868
994869 // Replace all args with dummy instructions. If an argument is the old frame
995870 // pointer, the dummy will be replaced by the new frame pointer once it is
@@ -1213,12 +1088,20 @@ void CoroCloner::create() {
12131088
12141089 // Salvage debug info that points into the coroutine frame.
12151090 salvageDebugInfo ();
1091+ }
1092+
1093+ void CoroSwitchCloner::create () {
1094+ // Create a new function matching the original type
1095+ NewF = createCloneDeclaration (OrigF, Shape, Suffix,
1096+ OrigF.getParent ()->end (), ActiveSuspend);
1097+
1098+ // Clone the function
1099+ CoroCloner::create ();
12161100
12171101 // Eliminate coro.free from the clones, replacing it with 'null' in cleanup,
12181102 // to suppress deallocation code.
1219- if (Shape.ABI == coro::ABI::Switch)
1220- coro::replaceCoroFree (cast<CoroIdInst>(VMap[Shape.CoroBegin ->getId ()]),
1221- /* Elide=*/ FKind == CoroCloner::Kind::SwitchCleanup);
1103+ coro::replaceCoroFree (cast<CoroIdInst>(VMap[Shape.CoroBegin ->getId ()]),
1104+ /* Elide=*/ FKind == CoroCloner::Kind::SwitchCleanup);
12221105}
12231106
12241107static void updateAsyncFuncPointerContextSize (coro::Shape &Shape) {
@@ -1495,11 +1378,11 @@ struct SwitchCoroutineSplitter {
14951378 // setting new entry block and replacing coro.suspend an appropriate value
14961379 // to force resume or cleanup pass for every suspend point.
14971380 createResumeEntryBlock (F, Shape);
1498- auto *ResumeClone = CoroCloner ::createClone (
1381+ auto *ResumeClone = CoroSwitchCloner ::createClone (
14991382 F, " .resume" , Shape, CoroCloner::Kind::SwitchResume, TTI);
1500- auto *DestroyClone = CoroCloner ::createClone (
1383+ auto *DestroyClone = CoroSwitchCloner ::createClone (
15011384 F, " .destroy" , Shape, CoroCloner::Kind::SwitchUnwind, TTI);
1502- auto *CleanupClone = CoroCloner ::createClone (
1385+ auto *CleanupClone = CoroSwitchCloner ::createClone (
15031386 F, " .cleanup" , Shape, CoroCloner::Kind::SwitchCleanup, TTI);
15041387
15051388 postSplitCleanup (*ResumeClone);
0 commit comments