[llvm] [CoroEarly] Add presplitcoroutine when frontend misses it (PR #169866)

Weibo He via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 27 19:12:47 PST 2025


https://github.com/NewSigma created https://github.com/llvm/llvm-project/pull/169866

This patch proposes adding `presplitcoroutine` attribute instead of asserting it. It doesn't seem good to suppress the requirement in release mode.

Close #156652

>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] [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;
     }
   }
 



More information about the llvm-commits mailing list