[llvm] [CoroEarly] Add presplitcoroutine when frontend misses it (PR #169866)
Weibo He via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 30 17:27:27 PST 2025
https://github.com/NewSigma updated https://github.com/llvm/llvm-project/pull/169866
>From 0e63018ab054e467c18deb67cd647a7fbbf41e1c Mon Sep 17 00:00:00 2001
From: NewSigma <NewSigma at 163.com>
Date: Fri, 28 Nov 2025 11:11:12 +0800
Subject: [PATCH 1/2] [CoroEarly] Add presplitcoroutine when frontend misses it
---
llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 116 ++++++++++---------
1 file changed, 59 insertions(+), 57 deletions(-)
diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
index cdb58523d1e0e..a84fdad071303 100644
--- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp
@@ -204,64 +204,66 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) {
continue;
switch (CB->getIntrinsicID()) {
- default:
- continue;
- case Intrinsic::coro_begin:
- case Intrinsic::coro_begin_custom_abi:
- if (CoroBegin)
- report_fatal_error(
- "coroutine should have exactly one defining @llvm.coro.begin");
- CoroBegin = cast<CoroBeginInst>(&I);
- break;
- case Intrinsic::coro_free:
- CoroFrees.push_back(cast<CoroFreeInst>(&I));
- break;
- case Intrinsic::coro_suspend:
- // Make sure that final suspend point is not duplicated as CoroSplit
- // pass expects that there is at most one final suspend point.
- if (cast<CoroSuspendInst>(&I)->isFinal())
- CB->setCannotDuplicate();
- HasCoroSuspend = true;
- break;
- case Intrinsic::coro_end_async:
- case Intrinsic::coro_end:
- // Make sure that fallthrough coro.end is not duplicated as CoroSplit
- // pass expects that there is at most one fallthrough coro.end.
- if (cast<AnyCoroEndInst>(&I)->isFallthrough())
- CB->setCannotDuplicate();
- break;
- case Intrinsic::coro_noop:
- lowerCoroNoop(cast<IntrinsicInst>(&I));
- break;
- case Intrinsic::coro_id:
- if (auto *CII = cast<CoroIdInst>(&I)) {
- if (CII->getInfo().isPreSplit()) {
- assert(F.isPresplitCoroutine() &&
- "The frontend uses Switch-Resumed ABI should emit "
- "\"presplitcoroutine\" attribute for the coroutine.");
- setCannotDuplicate(CII);
- CII->setCoroutineSelf();
- CoroId = cast<CoroIdInst>(&I);
- }
+ default:
+ continue;
+ case Intrinsic::coro_begin:
+ case Intrinsic::coro_begin_custom_abi:
+ if (CoroBegin)
+ report_fatal_error(
+ "coroutine should have exactly one defining @llvm.coro.begin");
+ CoroBegin = cast<CoroBeginInst>(&I);
+ break;
+ case Intrinsic::coro_free:
+ CoroFrees.push_back(cast<CoroFreeInst>(&I));
+ break;
+ case Intrinsic::coro_suspend:
+ // Make sure that final suspend point is not duplicated as CoroSplit
+ // pass expects that there is at most one final suspend point.
+ if (cast<CoroSuspendInst>(&I)->isFinal())
+ CB->setCannotDuplicate();
+ HasCoroSuspend = true;
+ break;
+ case Intrinsic::coro_end_async:
+ case Intrinsic::coro_end:
+ // Make sure that fallthrough coro.end is not duplicated as CoroSplit
+ // pass expects that there is at most one fallthrough coro.end.
+ if (cast<AnyCoroEndInst>(&I)->isFallthrough())
+ CB->setCannotDuplicate();
+ break;
+ case Intrinsic::coro_noop:
+ lowerCoroNoop(cast<IntrinsicInst>(&I));
+ break;
+ case Intrinsic::coro_id:
+ if (auto *CII = cast<CoroIdInst>(&I)) {
+ if (CII->getInfo().isPreSplit()) {
+ // The frontend uses Switch-Resumed ABI should emit
+ // `presplitcoroutine` attribute for the coroutine.
+ if (!F.isPresplitCoroutine())
+ F.setPresplitCoroutine();
+
+ setCannotDuplicate(CII);
+ CII->setCoroutineSelf();
+ CoroId = cast<CoroIdInst>(&I);
}
- break;
- case Intrinsic::coro_id_retcon:
- case Intrinsic::coro_id_retcon_once:
- case Intrinsic::coro_id_async:
- F.setPresplitCoroutine();
- break;
- case Intrinsic::coro_resume:
- lowerResumeOrDestroy(*CB, CoroSubFnInst::ResumeIndex);
- break;
- case Intrinsic::coro_destroy:
- lowerResumeOrDestroy(*CB, CoroSubFnInst::DestroyIndex);
- break;
- case Intrinsic::coro_promise:
- lowerCoroPromise(cast<CoroPromiseInst>(&I));
- break;
- case Intrinsic::coro_done:
- lowerCoroDone(cast<IntrinsicInst>(&I));
- break;
+ }
+ break;
+ case Intrinsic::coro_id_retcon:
+ case Intrinsic::coro_id_retcon_once:
+ case Intrinsic::coro_id_async:
+ F.setPresplitCoroutine();
+ break;
+ case Intrinsic::coro_resume:
+ lowerResumeOrDestroy(*CB, CoroSubFnInst::ResumeIndex);
+ break;
+ case Intrinsic::coro_destroy:
+ lowerResumeOrDestroy(*CB, CoroSubFnInst::DestroyIndex);
+ break;
+ case Intrinsic::coro_promise:
+ lowerCoroPromise(cast<CoroPromiseInst>(&I));
+ break;
+ case Intrinsic::coro_done:
+ lowerCoroDone(cast<IntrinsicInst>(&I));
+ break;
}
}
>From 4a738e6e2cb5fb4cb2c8ceea6a0624fde6c3f489 Mon Sep 17 00:00:00 2001
From: NewSigma <NewSigma at 163.com>
Date: Sat, 29 Nov 2025 10:51:49 +0800
Subject: [PATCH 2/2] Add test
---
.../Coroutines/coro-early-presplit.ll | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 llvm/test/Transforms/Coroutines/coro-early-presplit.ll
diff --git a/llvm/test/Transforms/Coroutines/coro-early-presplit.ll b/llvm/test/Transforms/Coroutines/coro-early-presplit.ll
new file mode 100644
index 0000000000000..7f7af060d51a8
--- /dev/null
+++ b/llvm/test/Transforms/Coroutines/coro-early-presplit.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; Check that coro-early can infer presplitcoroutine attribute
+; RUN: opt < %s -passes='module(coro-early)' -S | FileCheck %s
+
+define void @f() {
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null)
+; CHECK-NEXT: ret void
+;
+entry:
+ call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+ ret void
+}
+
+; CHECK: attributes #0 = { presplitcoroutine }
More information about the llvm-commits
mailing list