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

Reply via email to