Skip to content

[llvm][Coro] Lower coro.frame in CoroEarly instead of CoroSplit #137976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions llvm/include/llvm/Transforms/Coroutines/CoroShape.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,14 @@ struct Shape {
}

// Scan the function and collect the above intrinsics for later processing
void analyze(Function &F, SmallVectorImpl<CoroFrameInst *> &CoroFrames,
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
void analyze(Function &F, SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
CoroPromiseInst *&CoroPromise);
// If for some reason, we were not able to find coro.begin, bailout.
void invalidateCoroutine(Function &F,
SmallVectorImpl<CoroFrameInst *> &CoroFrames);
void invalidateCoroutine(Function &F);
// Perform ABI related initial transformation
void initABI();
// Remove orphaned and unnecessary intrinsics
void cleanCoroutine(SmallVectorImpl<CoroFrameInst *> &CoroFrames,
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
void cleanCoroutine(SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
CoroPromiseInst *CoroPromise);

// Field indexes for special fields in the switch lowering.
Expand Down Expand Up @@ -265,16 +262,15 @@ struct Shape {

Shape() = default;
explicit Shape(Function &F) {
SmallVector<CoroFrameInst *, 8> CoroFrames;
SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
CoroPromiseInst *CoroPromise = nullptr;

analyze(F, CoroFrames, UnusedCoroSaves, CoroPromise);
analyze(F, UnusedCoroSaves, CoroPromise);
if (!CoroBegin) {
invalidateCoroutine(F, CoroFrames);
invalidateCoroutine(F);
return;
}
cleanCoroutine(CoroFrames, UnusedCoroSaves, CoroPromise);
cleanCoroutine(UnusedCoroSaves, CoroPromise);
}
};

Expand Down
20 changes: 18 additions & 2 deletions llvm/lib/Transforms/Coroutines/CoroEarly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ class Lowerer : public coro::LowererBase {
IRBuilder<> Builder;
PointerType *const AnyResumeFnPtrTy;
Constant *NoopCoro = nullptr;
SmallVector<CoroFrameInst *, 8> CoroFrames;

void lowerResumeOrDestroy(CallBase &CB, CoroSubFnInst::ResumeKind);
void lowerCoroFrames(Function &F, Value *CoroBegin);
void lowerCoroPromise(CoroPromiseInst *Intrin);
void lowerCoroDone(IntrinsicInst *II);
void lowerCoroNoop(IntrinsicInst *II);
Expand All @@ -51,6 +53,18 @@ void Lowerer::lowerResumeOrDestroy(CallBase &CB,
CB.setCallingConv(CallingConv::Fast);
}

void Lowerer::lowerCoroFrames(Function &F, Value *CoroBegin) {
// Lower with poison if we cannot find coro.begin
if (CoroBegin == nullptr)
CoroBegin = PoisonValue::get(PointerType::get(F.getContext(), 0));

for (CoroFrameInst *CF : CoroFrames) {
CF->replaceAllUsesWith(CoroBegin);
CF->eraseFromParent();
}
CoroFrames.clear();
}

// Coroutine promise field is always at the fixed offset from the beginning of
// the coroutine frame. i8* coro.promise(i8*, i1 from) intrinsic adds an offset
// to a passed pointer to move from coroutine frame to coroutine promise and
Expand Down Expand Up @@ -257,6 +271,8 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
break;
}
}
// The coro.frame intrinsic is always lowered to the result of coro.begin.
lowerCoroFrames(F, CoroBegin);

if (CoroId) {
// Make sure that all CoroFree reference the coro.id intrinsic.
Expand All @@ -282,8 +298,8 @@ static bool declaresCoroEarlyIntrinsics(const Module &M) {
M, {"llvm.coro.id", "llvm.coro.id.retcon", "llvm.coro.id.retcon.once",
"llvm.coro.id.async", "llvm.coro.destroy", "llvm.coro.done",
"llvm.coro.end", "llvm.coro.end.async", "llvm.coro.noop",
"llvm.coro.free", "llvm.coro.promise", "llvm.coro.resume",
"llvm.coro.suspend"});
"llvm.coro.frame", "llvm.coro.free", "llvm.coro.promise",
"llvm.coro.resume", "llvm.coro.suspend"});
}

PreservedAnalyses CoroEarlyPass::run(Module &M, ModuleAnalysisManager &) {
Expand Down
24 changes: 1 addition & 23 deletions llvm/lib/Transforms/Coroutines/Coroutines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,

// Collect "interesting" coroutine intrinsics.
void coro::Shape::analyze(Function &F,
SmallVectorImpl<CoroFrameInst *> &CoroFrames,
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
CoroPromiseInst *&CoroPromise) {
clear();
Expand All @@ -215,9 +214,6 @@ void coro::Shape::analyze(Function &F,
case Intrinsic::coro_align:
CoroAligns.push_back(cast<CoroAlignInst>(II));
break;
case Intrinsic::coro_frame:
CoroFrames.push_back(cast<CoroFrameInst>(II));
break;
case Intrinsic::coro_save:
// After optimizations, coro_suspends using this coro_save might have
// been removed, remember orphaned coro_saves to remove them later.
Expand Down Expand Up @@ -351,19 +347,9 @@ void coro::Shape::analyze(Function &F,
}

// If for some reason, we were not able to find coro.begin, bailout.
void coro::Shape::invalidateCoroutine(
Function &F, SmallVectorImpl<CoroFrameInst *> &CoroFrames) {
void coro::Shape::invalidateCoroutine(Function &F) {
assert(!CoroBegin);
{
// Replace coro.frame which are supposed to be lowered to the result of
// coro.begin with poison.
auto *Poison = PoisonValue::get(PointerType::get(F.getContext(), 0));
for (CoroFrameInst *CF : CoroFrames) {
CF->replaceAllUsesWith(Poison);
CF->eraseFromParent();
}
CoroFrames.clear();

// Replace all coro.suspend with poison and remove related coro.saves if
// present.
for (AnyCoroSuspendInst *CS : CoroSuspends) {
Expand Down Expand Up @@ -482,15 +468,7 @@ void coro::AnyRetconABI::init() {
}

void coro::Shape::cleanCoroutine(
SmallVectorImpl<CoroFrameInst *> &CoroFrames,
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves, CoroPromiseInst *PI) {
// The coro.frame intrinsic is always lowered to the result of coro.begin.
for (CoroFrameInst *CF : CoroFrames) {
CF->replaceAllUsesWith(CoroBegin);
CF->eraseFromParent();
}
CoroFrames.clear();

// Remove orphaned coro.saves.
for (CoroSaveInst *CoroSave : UnusedCoroSaves)
CoroSave->eraseFromParent();
Expand Down
Loading