Author: Andres-Salamanca Date: 2026-10-08T01:00:24Z New Revision: 25da5b6127d758ebf7ce2e033479e41479653bb3
URL: https://github.com/llvm/llvm-project/commit/25da5b6127d758ebf7ce2e033479e41479653bb3 DIFF: https://github.com/llvm/llvm-project/commit/25da5b6127d758ebf7ce2e033479e41479653bb3.diff LOG: [CIR] Add cir.coro.suspend intrinsic (#228310) Implement `cir.coro.suspend` and lower __builtin_coro_suspend to the CIR coroutine suspend intrinsic. Added: clang/test/CIR/IR/coro-suspend.cir Modified: clang/include/clang/CIR/Dialect/IR/CIROps.td clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp clang/lib/CIR/CodeGen/CIRGenFunction.h clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 73521879937fe..42ff7a9131cfd 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5138,6 +5138,32 @@ def CIR_CoroSizeOp : CIR_CoroIntrinsicOp<"size", (ins), let llvmOp = "CoroSizeOp"; } +//===----------------------------------------------------------------------===// +// Coroutine intrinsic SuspendOp +//===----------------------------------------------------------------------===// + +def CIR_CoroSuspendOp : CIR_CoroIntrinsicOp<"suspend", + (ins Token:$save, CIR_AnyBoolType: $final), + (outs CIR_SInt8:$result), [TokenConsumerTrait]> { + let summary = "Represents llvm.coro.suspend"; + let description = [{ + `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 + 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..841de79fa0d2f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1825,9 +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: - cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_suspend NYI"); - return getUndefRValue(e->getType()); + 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/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp index c2a85aab2c19d..c1f6a3732c160 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 02627b488b23d..587676cefe428 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -2058,6 +2058,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..507c0757af282 100644 --- a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp +++ b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp @@ -77,6 +77,34 @@ 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) +} + +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: ] 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
