Skip to content

Commit b40714b

Browse files
authored
[Coroutines][NFC] Refactor CoroCloner (#116885)
* Move CoroCloner to its own header. For now, the header is located in llvm/lib/Transforms/Coroutines * Change private to protected to allow inheritance * Create CoroSwitchCloner and move some of the switch specific code into this cloner. More code will follow in later commits.
1 parent 38098b4 commit b40714b

File tree

3 files changed

+188
-150
lines changed

3 files changed

+188
-150
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//
2+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
//===----------------------------------------------------------------------===//
7+
// Helper class for splitting a coroutine into separate functions. For example
8+
// the returned-continuation coroutine is split into separate continuation
9+
// functions.
10+
//===----------------------------------------------------------------------===//
11+
12+
#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H
13+
#define LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H
14+
15+
#include "llvm/IR/Function.h"
16+
#include "llvm/IR/IRBuilder.h"
17+
#include "llvm/Support/TimeProfiler.h"
18+
#include "llvm/Transforms/Coroutines/ABI.h"
19+
#include "llvm/Transforms/Coroutines/CoroInstr.h"
20+
#include "llvm/Transforms/Utils/ValueMapper.h"
21+
22+
namespace llvm {
23+
24+
namespace coro {
25+
26+
enum class CloneKind {
27+
/// The shared resume function for a switch lowering.
28+
SwitchResume,
29+
30+
/// The shared unwind function for a switch lowering.
31+
SwitchUnwind,
32+
33+
/// The shared cleanup function for a switch lowering.
34+
SwitchCleanup,
35+
36+
/// An individual continuation function.
37+
Continuation,
38+
39+
/// An async resume function.
40+
Async,
41+
};
42+
43+
class BaseCloner {
44+
protected:
45+
Function &OrigF;
46+
const Twine &Suffix;
47+
coro::Shape &Shape;
48+
CloneKind FKind;
49+
IRBuilder<> Builder;
50+
TargetTransformInfo &TTI;
51+
52+
ValueToValueMapTy VMap;
53+
Function *NewF = nullptr;
54+
Value *NewFramePtr = nullptr;
55+
56+
/// The active suspend instruction; meaningful only for continuation and async
57+
/// ABIs.
58+
AnyCoroSuspendInst *ActiveSuspend = nullptr;
59+
60+
/// Create a cloner for a continuation lowering.
61+
BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
62+
Function *NewF, AnyCoroSuspendInst *ActiveSuspend,
63+
TargetTransformInfo &TTI)
64+
: OrigF(OrigF), Suffix(Suffix), Shape(Shape),
65+
FKind(Shape.ABI == ABI::Async ? CloneKind::Async
66+
: CloneKind::Continuation),
67+
Builder(OrigF.getContext()), TTI(TTI), NewF(NewF),
68+
ActiveSuspend(ActiveSuspend) {
69+
assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||
70+
Shape.ABI == ABI::Async);
71+
assert(NewF && "need existing function for continuation");
72+
assert(ActiveSuspend && "need active suspend point for continuation");
73+
}
74+
75+
public:
76+
BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
77+
CloneKind FKind, TargetTransformInfo &TTI)
78+
: OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind),
79+
Builder(OrigF.getContext()), TTI(TTI) {}
80+
81+
virtual ~BaseCloner() {}
82+
83+
/// Create a clone for a continuation lowering.
84+
static Function *createClone(Function &OrigF, const Twine &Suffix,
85+
coro::Shape &Shape, Function *NewF,
86+
AnyCoroSuspendInst *ActiveSuspend,
87+
TargetTransformInfo &TTI) {
88+
assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce ||
89+
Shape.ABI == ABI::Async);
90+
TimeTraceScope FunctionScope("BaseCloner");
91+
92+
BaseCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI);
93+
Cloner.create();
94+
return Cloner.getFunction();
95+
}
96+
97+
Function *getFunction() const {
98+
assert(NewF != nullptr && "declaration not yet set");
99+
return NewF;
100+
}
101+
102+
virtual void create();
103+
104+
protected:
105+
bool isSwitchDestroyFunction() {
106+
switch (FKind) {
107+
case CloneKind::Async:
108+
case CloneKind::Continuation:
109+
case CloneKind::SwitchResume:
110+
return false;
111+
case CloneKind::SwitchUnwind:
112+
case CloneKind::SwitchCleanup:
113+
return true;
114+
}
115+
llvm_unreachable("Unknown ClonerKind enum");
116+
}
117+
118+
void replaceEntryBlock();
119+
Value *deriveNewFramePointer();
120+
void replaceRetconOrAsyncSuspendUses();
121+
void replaceCoroSuspends();
122+
void replaceCoroEnds();
123+
void replaceSwiftErrorOps();
124+
void salvageDebugInfo();
125+
void handleFinalSuspend();
126+
};
127+
128+
class SwitchCloner : public BaseCloner {
129+
protected:
130+
/// Create a cloner for a switch lowering.
131+
SwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape,
132+
CloneKind FKind, TargetTransformInfo &TTI)
133+
: BaseCloner(OrigF, Suffix, Shape, FKind, TTI) {}
134+
135+
void create() override;
136+
137+
public:
138+
/// Create a clone for a switch lowering.
139+
static Function *createClone(Function &OrigF, const Twine &Suffix,
140+
coro::Shape &Shape, CloneKind FKind,
141+
TargetTransformInfo &TTI) {
142+
assert(Shape.ABI == ABI::Switch);
143+
TimeTraceScope FunctionScope("SwitchCloner");
144+
145+
SwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI);
146+
Cloner.create();
147+
return Cloner.getFunction();
148+
}
149+
};
150+
151+
} // end namespace coro
152+
153+
} // end namespace llvm
154+
155+
#endif // LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1133,7 +1133,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
11331133
bool AllowUnresolved = false;
11341134
// This dbg.declare is preserved for all coro-split function
11351135
// fragments. It will be unreachable in the main function, and
1136-
// processed by coro::salvageDebugInfo() by CoroCloner.
1136+
// processed by coro::salvageDebugInfo() by the Cloner.
11371137
if (UseNewDbgInfoFormat) {
11381138
DbgVariableRecord *NewDVR = new DbgVariableRecord(
11391139
ValueAsMetadata::get(CurrentReload), DDI->getVariable(),

0 commit comments

Comments
 (0)