https://github.com/Andres-Salamanca updated 
https://github.com/llvm/llvm-project/pull/228310

>From 129c890ff2e43ef31e0ba51db81cac7824315f84 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Thu, 1 Oct 2026 22:09:01 -0500
Subject: [PATCH 1/3] [CIR] Add cir.coro.suspend intrinsic

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 26 +++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  3 +--
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp     | 10 +++++++
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |  1 +
 .../CIR/CodeGenCoroutines/coro-builtins.cpp   |  8 ++++--
 5 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 985cc3712c581..7a10c7d9d1521 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5137,6 +5137,32 @@ def CIR_CoroSizeOp : CIR_CoroIntrinsicOp<"size", (ins),
   let llvmOp = "CoroSizeOp";
 }
 
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic SuspendOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroSuspendOp : CIR_CoroIntrinsicOp<"suspend",
+    (ins Token:$id, CIR_AnyBoolType: $final),
+    (outs CIR_UInt8:$result), [TokenConsumerTrait]> {
+  let summary = "Represents llvm.coro.suspend";
+  let description = [{
+    `cir.coro.suspend` represents the `llvm.coro.suspend` intrinsic.
+
+    It marks the point where execution of a switched-resume coroutine is
+    suspended and control returns to the caller. The result value indicates
+    how the coroutine should proceed: -1 if suspended, 0 if resumed, or 1
+    if destroyed.
+
+    The `id` operand is the token produced by a `cir.coro.save` that marks
+    the point when the coroutine state is prepared for suspension.
+
+    The `final` operand indicates whether this is a final suspend point.
+    If more than one suspend point is marked final, the resume and destroy
+    branches must lead to the same basic blocks.
+  }];
+  let llvmOp = "CoroSuspendOp";
+}
+
 
//===----------------------------------------------------------------------===//
 // Coroutine intrinsic PromiseOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 97ce3fbcabcbc..ef00f4536fa57 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1826,8 +1826,7 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BI__builtin_coro_done:
     return RValue::get(emitCoroDoneBuiltinCall(e).getResult());
   case Builtin::BI__builtin_coro_suspend:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_suspend NYI");
-    return getUndefRValue(e->getType());
+    return RValue::get(emitCoroSuspendBuiltinCall(e).getResult());
   case Builtin::BI__builtin_coro_align:
     cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_align NYI");
     return getUndefRValue(e->getType());
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index d92c65dc43c5f..ecd8e7df00614 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -287,6 +287,16 @@ cir::CoroNoopOp 
CIRGenFunction::emitCoroNoopBuiltinCall(const CallExpr *e) {
   return cir::CoroNoopOp::create(cgm.getBuilder(), loc);
 }
 
+cir::CoroSuspendOp
+CIRGenFunction::emitCoroSuspendBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  llvm::SmallVector<mlir::Value, 2> args;
+  args.push_back(cir::TokenNoneOp::create(builder, loc));
+  args.push_back(emitScalarExpr(e->getArg(0)));
+
+  return cir::CoroSuspendOp::create(cgm.getBuilder(), loc, args);
+}
+
 static mlir::LogicalResult
 coroutineBodyExceptionHelper(CIRGenFunction &cgf, const CoroutineBodyStmt &s) {
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c6427d60a3792..3abb947709c9f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -2040,6 +2040,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e);
   cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e);
   cir::CoroNoopOp emitCoroNoopBuiltinCall(const CallExpr *e);
+  cir::CoroSuspendOp emitCoroSuspendBuiltinCall(const CallExpr *e);
 
   cir::CoroSizeOp emitCoroSizeBuiltinCall(const CallExpr *e);
   cir::CoroFreeOp emitCoroFreeBuiltin(const CallExpr *e);
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
index 539151dbd633d..61e0e1fbe6b3a 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
@@ -77,6 +77,10 @@ void f(int n) {
 
   // LLVM: call void @llvm.coro.end(ptr %[[FRAME]], i1 false, token none)
 
-  // TODO(CIR):
-  //__builtin_coro_suspend(1);
+  __builtin_coro_suspend(true);
+  // CIR: %[[TK_NONE2:.*]] = cir.token.none
+  // CIR: %[[TRUE:.*]] = cir.const #true
+  // CIR: cir.coro.intrinsic.suspend(%[[TK_NONE2]], %[[TRUE]])
+
+  // LLVM: call i8 @llvm.coro.suspend(token none, i1 true)
 }

>From 7b6c16406b2da1efbce0eb5028f54e3d0f544ad0 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 6 Oct 2026 18:11:27 -0500
Subject: [PATCH 2/3] Address review comments

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  2 +-
 .../CIR/CodeGenCoroutines/coro-builtins.cpp   | 24 +++++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7a10c7d9d1521..7fb2ecbe9c091 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5143,7 +5143,7 @@ def CIR_CoroSizeOp : CIR_CoroIntrinsicOp<"size", (ins),
 
 def CIR_CoroSuspendOp : CIR_CoroIntrinsicOp<"suspend",
     (ins Token:$id, CIR_AnyBoolType: $final),
-    (outs CIR_UInt8:$result), [TokenConsumerTrait]> {
+    (outs CIR_SInt8:$result), [TokenConsumerTrait]> {
   let summary = "Represents llvm.coro.suspend";
   let description = [{
     `cir.coro.suspend` represents the `llvm.coro.suspend` intrinsic.
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
index 61e0e1fbe6b3a..507c0757af282 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
@@ -84,3 +84,27 @@ void f(int n) {
 
   // LLVM: call i8 @llvm.coro.suspend(token none, i1 true)
 }
+
+void test_suspend_switch() {
+  switch (__builtin_coro_suspend(false)) {
+  case -1:
+    return;
+  case 0:
+    break;
+  }
+}
+
+// CIR: cir.func{{.*}} @_Z19test_suspend_switchv
+// CIR: %[[TK_NONE:.*]] = cir.token.none
+// CIR: %[[FALSE:.*]] = cir.const #false
+// CIR: %[[SUSPEND:.*]] = cir.coro.intrinsic.suspend(%[[TK_NONE]], %[[FALSE]]) 
: (token, !cir.bool) -> !s8i
+// CIR: %[[CAST:.*]] = cir.cast integral %[[SUSPEND]] : !s8i -> !s32i
+// CIR: cir.switch(%[[CAST]] : !s32i)
+
+// LLVM: define{{.*}} void @_Z19test_suspend_switchv
+// LLVM: %[[SUSPEND:.*]] = call i8 @llvm.coro.suspend(token none, i1 false)
+// LLVM: %[[CAST:.*]] = sext i8 %[[SUSPEND]] to i32
+// LLVM: switch i32 %[[CAST]], label %{{.*}} [
+// LLVM:   i32 -1, label %{{.*}}
+// LLVM:   i32 0, label %{{.*}}
+// LLVM: ]

>From f3765547d50e665b22e893e2c9350ce4301f3c3f Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Wed, 7 Oct 2026 18:00:04 -0500
Subject: [PATCH 3/3] Address review comments

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td |  4 ++--
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp      |  7 +++++--
 clang/test/CIR/IR/coro-suspend.cir           | 15 +++++++++++++++
 3 files changed, 22 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CIR/IR/coro-suspend.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7fb2ecbe9c091..4451065124f43 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5142,11 +5142,11 @@ def CIR_CoroSizeOp : CIR_CoroIntrinsicOp<"size", (ins),
 
//===----------------------------------------------------------------------===//
 
 def CIR_CoroSuspendOp : CIR_CoroIntrinsicOp<"suspend",
-    (ins Token:$id, CIR_AnyBoolType: $final),
+    (ins Token:$save, CIR_AnyBoolType: $final),
     (outs CIR_SInt8:$result), [TokenConsumerTrait]> {
   let summary = "Represents llvm.coro.suspend";
   let description = [{
-    `cir.coro.suspend` represents the `llvm.coro.suspend` intrinsic.
+    `cir.coro.intrinsic.suspend` represents the `llvm.coro.suspend` intrinsic.
 
     It marks the point where execution of a switched-resume coroutine is
     suspended and control returns to the caller. The result value indicates
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index ef00f4536fa57..841de79fa0d2f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1825,8 +1825,11 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   }
   case Builtin::BI__builtin_coro_done:
     return RValue::get(emitCoroDoneBuiltinCall(e).getResult());
-  case Builtin::BI__builtin_coro_suspend:
-    return RValue::get(emitCoroSuspendBuiltinCall(e).getResult());
+  case Builtin::BI__builtin_coro_suspend: {
+    mlir::Value result = emitCoroSuspendBuiltinCall(e).getResult();
+    return RValue::get(
+        builder.createIntCast(result, convertType(e->getType())));
+  }
   case Builtin::BI__builtin_coro_align:
     cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_align NYI");
     return getUndefRValue(e->getType());
diff --git a/clang/test/CIR/IR/coro-suspend.cir 
b/clang/test/CIR/IR/coro-suspend.cir
new file mode 100644
index 0000000000000..2416aa263ba3c
--- /dev/null
+++ b/clang/test/CIR/IR/coro-suspend.cir
@@ -0,0 +1,15 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!void = !cir.void
+#false = #cir.bool<false> : !cir.bool
+!s8i = !cir.int<s, 8>
+
+module {
+  cir.func @test_coro_noop() {
+    %0 = cir.token.none
+    %1 = cir.const #false
+    %2 = cir.coro.intrinsic.suspend(%0, %1) : (token, !cir.bool) -> !s8i
+    // CHECK: cir.coro.intrinsic.suspend(%0, %1) : (token, !cir.bool) -> !s8i
+    cir.return
+  }
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to