[llvm] [llvm][Coro] Lower coro.frame in CoroEarly instead of CoroSplit (PR #137976)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 30 08:13:33 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-coroutines
Author: None (NewSigma)
<details>
<summary>Changes</summary>
Documentation of CoroEarly states:
> This pass lowers coro.frame, coro.done, and coro.promise intrinsics.
However, currently coro.frame lowering is handled by CoroSplit. This commit moves this operation to CoroEarly.
---
Full diff: https://github.com/llvm/llvm-project/pull/137976.diff
3 Files Affected:
- (modified) llvm/include/llvm/Transforms/Coroutines/CoroShape.h (+6-10)
- (modified) llvm/lib/Transforms/Coroutines/CoroEarly.cpp (+41-4)
- (modified) llvm/lib/Transforms/Coroutines/Coroutines.cpp (+1-23)
``````````diff
diff --git a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
index ea93ced1ce29e..c3b14fbc36e66 100644
--- a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
+++ b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
@@ -78,16 +78,13 @@ 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);
// 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);
// Field indexes for special fields in the switch lowering.
struct SwitchFieldIndex {
@@ -263,15 +260,14 @@ struct Shape {
Shape() = default;
explicit Shape(Function &F) {
- SmallVector<CoroFrameInst *, 8> CoroFrames;
SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
- analyze(F, CoroFrames, UnusedCoroSaves);
+ analyze(F, UnusedCoroSaves);
if (!CoroBegin) {
- invalidateCoroutine(F, CoroFrames);
+ invalidateCoroutine(F);
return;
}
- cleanCoroutine(CoroFrames, UnusedCoroSaves);
+ cleanCoroutine(UnusedCoroSaves);
}
};
diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
index 5375448d2d2e2..df62cc6c51953 100644
--- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
@@ -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);
@@ -50,6 +52,18 @@ void Lowerer::lowerResumeOrDestroy(CallBase &CB,
CB.setCallingConv(CallingConv::Fast);
}
+void Lowerer::lowerCoroFrames(Function &F, Value *CoroBegin) {
+ // Lower with poison if we cannot func 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
@@ -165,6 +179,7 @@ static void setCannotDuplicate(CoroIdInst *CoroId) {
void Lowerer::lowerEarlyIntrinsics(Function &F) {
CoroIdInst *CoroId = nullptr;
+ CoroBeginInst *CoroBegin = nullptr;
SmallVector<CoroFreeInst *, 4> CoroFrees;
bool HasCoroSuspend = false;
for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
@@ -175,6 +190,26 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
switch (CB->getIntrinsicID()) {
default:
continue;
+ case Intrinsic::coro_begin:
+ case Intrinsic::coro_begin_custom_abi: {
+ auto CBI = cast<CoroBeginInst>(&I);
+
+ // Ignore coro id's that aren't pre-split.
+ auto Id = dyn_cast<CoroIdInst>(CBI->getId());
+ if (Id && !Id->getInfo().isPreSplit())
+ break;
+
+ if (CoroBegin)
+ report_fatal_error(
+ "coroutine should have exactly one defining @llvm.coro.begin");
+ CBI->addRetAttr(Attribute::NonNull);
+ CBI->addRetAttr(Attribute::NoAlias);
+ CoroBegin = CBI;
+ break;
+ }
+ case Intrinsic::coro_frame:
+ CoroFrames.push_back(cast<CoroFrameInst>(&I));
+ break;
case Intrinsic::coro_free:
CoroFrees.push_back(cast<CoroFreeInst>(&I));
break;
@@ -226,6 +261,8 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
break;
}
}
+ // The coro.frame intrinsic is always lowered to the result of coro.begin.
+ lowerCoroFrames(F, CoroBegin);
// Make sure that all CoroFree reference the coro.id intrinsic.
// Token type is not exposed through coroutine C/C++ builtins to plain C, so
@@ -246,10 +283,10 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
static bool declaresCoroEarlyIntrinsics(const Module &M) {
return coro::declaresIntrinsics(
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.id.async", "llvm.coro.begin", "llvm.coro.destroy",
+ "llvm.coro.done", "llvm.coro.end", "llvm.coro.end.async",
+ "llvm.coro.noop", "llvm.coro.frame", "llvm.coro.free",
+ "llvm.coro.promise", "llvm.coro.resume", "llvm.coro.suspend"});
}
PreservedAnalyses CoroEarlyPass::run(Module &M, ModuleAnalysisManager &) {
diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
index 7b59c39283ded..7dee7a6f571d7 100644
--- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp
+++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
@@ -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) {
clear();
@@ -214,9 +213,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.
@@ -345,19 +341,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) {
@@ -476,15 +462,7 @@ void coro::AnyRetconABI::init() {
}
void coro::Shape::cleanCoroutine(
- SmallVectorImpl<CoroFrameInst *> &CoroFrames,
SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves) {
- // 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();
``````````
</details>
https://github.com/llvm/llvm-project/pull/137976
More information about the llvm-commits
mailing list