Skip to content

Commit baa42ad

Browse files
committed
[llvm][Coro] Lower coro.frame in CoroEarly instead of CoroSplit
1 parent a618ae2 commit baa42ad

File tree

3 files changed

+48
-37
lines changed

3 files changed

+48
-37
lines changed

llvm/include/llvm/Transforms/Coroutines/CoroShape.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,13 @@ struct Shape {
7878
}
7979

8080
// Scan the function and collect the above intrinsics for later processing
81-
void analyze(Function &F, SmallVectorImpl<CoroFrameInst *> &CoroFrames,
82-
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
81+
void analyze(Function &F, SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
8382
// If for some reason, we were not able to find coro.begin, bailout.
84-
void invalidateCoroutine(Function &F,
85-
SmallVectorImpl<CoroFrameInst *> &CoroFrames);
83+
void invalidateCoroutine(Function &F);
8684
// Perform ABI related initial transformation
8785
void initABI();
8886
// Remove orphaned and unnecessary intrinsics
89-
void cleanCoroutine(SmallVectorImpl<CoroFrameInst *> &CoroFrames,
90-
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
87+
void cleanCoroutine(SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
9188

9289
// Field indexes for special fields in the switch lowering.
9390
struct SwitchFieldIndex {
@@ -263,15 +260,14 @@ struct Shape {
263260

264261
Shape() = default;
265262
explicit Shape(Function &F) {
266-
SmallVector<CoroFrameInst *, 8> CoroFrames;
267263
SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
268264

269-
analyze(F, CoroFrames, UnusedCoroSaves);
265+
analyze(F, UnusedCoroSaves);
270266
if (!CoroBegin) {
271-
invalidateCoroutine(F, CoroFrames);
267+
invalidateCoroutine(F);
272268
return;
273269
}
274-
cleanCoroutine(CoroFrames, UnusedCoroSaves);
270+
cleanCoroutine(UnusedCoroSaves);
275271
}
276272
};
277273

llvm/lib/Transforms/Coroutines/CoroEarly.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ class Lowerer : public coro::LowererBase {
2525
IRBuilder<> Builder;
2626
PointerType *const AnyResumeFnPtrTy;
2727
Constant *NoopCoro = nullptr;
28+
SmallVector<CoroFrameInst *, 8> CoroFrames;
2829

2930
void lowerResumeOrDestroy(CallBase &CB, CoroSubFnInst::ResumeKind);
31+
void lowerCoroFrames(Function &F, Value *CoroBegin);
3032
void lowerCoroPromise(CoroPromiseInst *Intrin);
3133
void lowerCoroDone(IntrinsicInst *II);
3234
void lowerCoroNoop(IntrinsicInst *II);
@@ -50,6 +52,18 @@ void Lowerer::lowerResumeOrDestroy(CallBase &CB,
5052
CB.setCallingConv(CallingConv::Fast);
5153
}
5254

55+
void Lowerer::lowerCoroFrames(Function &F, Value *CoroBegin) {
56+
// Lower with poison if we cannot func coro.begin
57+
if (CoroBegin == nullptr)
58+
CoroBegin = PoisonValue::get(PointerType::get(F.getContext(), 0));
59+
60+
for (CoroFrameInst *CF : CoroFrames) {
61+
CF->replaceAllUsesWith(CoroBegin);
62+
CF->eraseFromParent();
63+
}
64+
CoroFrames.clear();
65+
}
66+
5367
// Coroutine promise field is always at the fixed offset from the beginning of
5468
// the coroutine frame. i8* coro.promise(i8*, i1 from) intrinsic adds an offset
5569
// to a passed pointer to move from coroutine frame to coroutine promise and
@@ -165,6 +179,7 @@ static void setCannotDuplicate(CoroIdInst *CoroId) {
165179

166180
void Lowerer::lowerEarlyIntrinsics(Function &F) {
167181
CoroIdInst *CoroId = nullptr;
182+
CoroBeginInst *CoroBegin = nullptr;
168183
SmallVector<CoroFreeInst *, 4> CoroFrees;
169184
bool HasCoroSuspend = false;
170185
for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
@@ -175,6 +190,26 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
175190
switch (CB->getIntrinsicID()) {
176191
default:
177192
continue;
193+
case Intrinsic::coro_begin:
194+
case Intrinsic::coro_begin_custom_abi: {
195+
auto CBI = cast<CoroBeginInst>(&I);
196+
197+
// Ignore coro id's that aren't pre-split.
198+
auto Id = dyn_cast<CoroIdInst>(CBI->getId());
199+
if (Id && !Id->getInfo().isPreSplit())
200+
break;
201+
202+
if (CoroBegin)
203+
report_fatal_error(
204+
"coroutine should have exactly one defining @llvm.coro.begin");
205+
CBI->addRetAttr(Attribute::NonNull);
206+
CBI->addRetAttr(Attribute::NoAlias);
207+
CoroBegin = CBI;
208+
break;
209+
}
210+
case Intrinsic::coro_frame:
211+
CoroFrames.push_back(cast<CoroFrameInst>(&I));
212+
break;
178213
case Intrinsic::coro_free:
179214
CoroFrees.push_back(cast<CoroFreeInst>(&I));
180215
break;
@@ -226,6 +261,8 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
226261
break;
227262
}
228263
}
264+
// The coro.frame intrinsic is always lowered to the result of coro.begin.
265+
lowerCoroFrames(F, CoroBegin);
229266

230267
// Make sure that all CoroFree reference the coro.id intrinsic.
231268
// Token type is not exposed through coroutine C/C++ builtins to plain C, so
@@ -246,10 +283,10 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
246283
static bool declaresCoroEarlyIntrinsics(const Module &M) {
247284
return coro::declaresIntrinsics(
248285
M, {"llvm.coro.id", "llvm.coro.id.retcon", "llvm.coro.id.retcon.once",
249-
"llvm.coro.id.async", "llvm.coro.destroy", "llvm.coro.done",
250-
"llvm.coro.end", "llvm.coro.end.async", "llvm.coro.noop",
251-
"llvm.coro.free", "llvm.coro.promise", "llvm.coro.resume",
252-
"llvm.coro.suspend"});
286+
"llvm.coro.id.async", "llvm.coro.begin", "llvm.coro.destroy",
287+
"llvm.coro.done", "llvm.coro.end", "llvm.coro.end.async",
288+
"llvm.coro.noop", "llvm.coro.frame", "llvm.coro.free",
289+
"llvm.coro.promise", "llvm.coro.resume", "llvm.coro.suspend"});
253290
}
254291

255292
PreservedAnalyses CoroEarlyPass::run(Module &M, ModuleAnalysisManager &) {

llvm/lib/Transforms/Coroutines/Coroutines.cpp

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,
191191

192192
// Collect "interesting" coroutine intrinsics.
193193
void coro::Shape::analyze(Function &F,
194-
SmallVectorImpl<CoroFrameInst *> &CoroFrames,
195194
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves) {
196195
clear();
197196

@@ -214,9 +213,6 @@ void coro::Shape::analyze(Function &F,
214213
case Intrinsic::coro_align:
215214
CoroAligns.push_back(cast<CoroAlignInst>(II));
216215
break;
217-
case Intrinsic::coro_frame:
218-
CoroFrames.push_back(cast<CoroFrameInst>(II));
219-
break;
220216
case Intrinsic::coro_save:
221217
// After optimizations, coro_suspends using this coro_save might have
222218
// been removed, remember orphaned coro_saves to remove them later.
@@ -345,19 +341,9 @@ void coro::Shape::analyze(Function &F,
345341
}
346342

347343
// If for some reason, we were not able to find coro.begin, bailout.
348-
void coro::Shape::invalidateCoroutine(
349-
Function &F, SmallVectorImpl<CoroFrameInst *> &CoroFrames) {
344+
void coro::Shape::invalidateCoroutine(Function &F) {
350345
assert(!CoroBegin);
351346
{
352-
// Replace coro.frame which are supposed to be lowered to the result of
353-
// coro.begin with poison.
354-
auto *Poison = PoisonValue::get(PointerType::get(F.getContext(), 0));
355-
for (CoroFrameInst *CF : CoroFrames) {
356-
CF->replaceAllUsesWith(Poison);
357-
CF->eraseFromParent();
358-
}
359-
CoroFrames.clear();
360-
361347
// Replace all coro.suspend with poison and remove related coro.saves if
362348
// present.
363349
for (AnyCoroSuspendInst *CS : CoroSuspends) {
@@ -476,15 +462,7 @@ void coro::AnyRetconABI::init() {
476462
}
477463

478464
void coro::Shape::cleanCoroutine(
479-
SmallVectorImpl<CoroFrameInst *> &CoroFrames,
480465
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves) {
481-
// The coro.frame intrinsic is always lowered to the result of coro.begin.
482-
for (CoroFrameInst *CF : CoroFrames) {
483-
CF->replaceAllUsesWith(CoroBegin);
484-
CF->eraseFromParent();
485-
}
486-
CoroFrames.clear();
487-
488466
// Remove orphaned coro.saves.
489467
for (CoroSaveInst *CoroSave : UnusedCoroSaves)
490468
CoroSave->eraseFromParent();

0 commit comments

Comments
 (0)