https://github.com/NewSigma updated https://github.com/llvm/llvm-project/pull/169866
>From 0e63018ab054e467c18deb67cd647a7fbbf41e1c Mon Sep 17 00:00:00 2001 From: NewSigma <[email protected]> Date: Fri, 28 Nov 2025 11:11:12 +0800 Subject: [PATCH 1/4] [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 <[email protected]> Date: Sat, 29 Nov 2025 10:51:49 +0800 Subject: [PATCH 2/4] 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 } >From 7f59d51d95d7157274a341de66b76f352f7c89bd Mon Sep 17 00:00:00 2001 From: NewSigma <[email protected]> Date: Mon, 1 Dec 2025 10:43:33 +0800 Subject: [PATCH 3/4] Undo formatting --- llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 117 +++++++++---------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp index a84fdad071303..3b3c36b33b28d 100644 --- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -204,66 +204,65 @@ 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()) { - // 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); + 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 6538787e2216920219cfa0dd2d1e52efe30bb53f Mon Sep 17 00:00:00 2001 From: NewSigma <[email protected]> Date: Mon, 1 Dec 2025 10:52:50 +0800 Subject: [PATCH 4/4] Remove presplitcoroutine in clang FE and set it in ME --- clang/lib/CodeGen/CGCoroutine.cpp | 3 --- llvm/lib/Transforms/Coroutines/CoroEarly.cpp | 6 ++---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index b76450152203d..fc5dfe5f50c44 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -975,9 +975,6 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { cast<ReturnStmt>(Ret)->setRetValue(PreviousRetValue); } - // LLVM require the frontend to mark the coroutine. - CurFn->setPresplitCoroutine(); - if (CXXRecordDecl *RD = FnRetTy->getAsCXXRecordDecl(); RD && RD->hasAttr<CoroOnlyDestroyWhenCompleteAttr>()) CurFn->setCoroDestroyOnlyWhenComplete(); diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp index 3b3c36b33b28d..37e50a1a3af98 100644 --- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -236,10 +236,8 @@ void Lowerer::lowerEarlyIntrinsics(Function &F) { 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(); + // Infer `presplitcoroutine` attribute for Switch-Resumed ABI + F.setPresplitCoroutine(); setCannotDuplicate(CII); CII->setCoroutineSelf(); CoroId = cast<CoroIdInst>(&I); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
