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
