https://github.com/vsytch created 
https://github.com/llvm/llvm-project/pull/222472

Implement the remaining C++ coroutine intrinsics and builtins in ClangIR:
- Add `CIR_Coro{Save,Suspend,Resume,Destroy,Done,Noop,Align}Op` operations in 
`CIROps.td` with TableGen DirectToLLVM lowering (`llvmOp` mappings).
- Implement codegen for 
`__builtin_coro_{resume,destroy,done,noop,align,suspend}` and add integral 
casting for `__builtin_coro_size` and `__builtin_coro_align`.
- Emit the `"presplitcoroutine"` passthrough function attribute when lowering 
coroutine functions in DirectToLLVM.
- Update `cir::FuncOp::verify()` to accept flattened coroutine functions 
containing `cir.coro.intrinsic.suspend` (where `cir.coro.body` has been 
lowered).
- Enable the TODO coroutine builtin tests in `coro-builtins.cpp` and add a 
DirectToLLVM lowering test in `coro-intrinsics.cir`.


>From 2a2fc6d14a044ed7b3da604a8a29dfc4fb7d273c Mon Sep 17 00:00:00 2001
From: Vlad Sytchenko <[email protected]>
Date: Wed, 9 Sep 2026 22:46:02 +0000
Subject: [PATCH] [CIR] Add coroutine intrinsics, builtins, and DirectToLLVM
 lowering

Implement the remaining C++ coroutine intrinsics and builtins in ClangIR:
- Add CIR_Coro{Save,Suspend,Resume,Destroy,Done,Noop,Align}Op operations in
  CIROps.td with TableGen DirectToLLVM lowering (llvmOp mappings).
- Implement codegen for __builtin_coro_{resume,destroy,done,noop,align,suspend}
  and add integral casting for __builtin_coro_size and __builtin_coro_align.
- Emit the "presplitcoroutine" passthrough function attribute when lowering
  coroutine functions in DirectToLLVM.
- Update cir::FuncOp::verify() to accept flattened coroutine functions
  containing cir.coro.intrinsic.suspend (where cir.coro.body has been lowered).
- Enable the TODO coroutine builtin tests in coro-builtins.cpp and add a
  DirectToLLVM lowering test in coro-intrinsics.cir.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 101 ++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  39 ++++---
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp     |  40 +++++++
 clang/lib/CIR/CodeGen/CIRGenFunction.h        |   6 ++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       |   9 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  22 +++-
 .../CIR/CodeGenCoroutines/coro-builtins.cpp   |  32 ++++--
 clang/test/CIR/Lowering/coro-intrinsics.cir   |  52 +++++++++
 8 files changed, 269 insertions(+), 32 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/coro-intrinsics.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d1047ab88b942..50823fe636552 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5019,6 +5019,107 @@ def CIR_CoroPromiseOp : CIR_CoroIntrinsicOp<"promise",
   let llvmOp = "CoroPromiseOp";
 }
 
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic SaveOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroSaveOp : CIR_CoroIntrinsicOp<"save",
+    (ins CIR_VoidPtrType:$handle),
+    (outs Token:$result), [TokenProducerTrait]> {
+  let summary = "Represents llvm.coro.save";
+  let description = [{
+    Saves the state of a coroutine identified by `handle` for a subsequent
+    suspension point, producing a token consumed by `coro.intrinsic.suspend`.
+  }];
+  let llvmOp = "CoroSaveOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic SuspendOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroSuspendOp : CIR_CoroIntrinsicOp<"suspend",
+    (ins Token:$save, CIR_AnyBoolType:$final_suspend),
+    (outs CIR_SInt8:$result), [TokenConsumerTrait]> {
+  let summary = "Represents llvm.coro.suspend";
+  let description = [{
+    Marks a coroutine suspension point. Consumes the token `save` produced
+    by `coro.intrinsic.save` (or `cir.token.none`) and a boolean flag
+    `final_suspend` indicating whether this is the final suspension point.
+    Returns an 8-bit signed integer indicating whether the coroutine should
+    suspend (`-1`), resume (`0`), or destroy (`1`).
+  }];
+  let llvmOp = "CoroSuspendOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic ResumeOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroResumeOp : CIR_CoroIntrinsicOp<"resume",
+    (ins CIR_VoidPtrType:$handle), (outs)> {
+  let summary = "Represents llvm.coro.resume";
+  let description = [{
+    Resumes a suspended coroutine given its frame pointer `handle`.
+  }];
+  let llvmOp = "CoroResumeOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic DestroyOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroDestroyOp : CIR_CoroIntrinsicOp<"destroy",
+    (ins CIR_VoidPtrType:$handle), (outs)> {
+  let summary = "Represents llvm.coro.destroy";
+  let description = [{
+    Destroys a suspended coroutine given its frame pointer `handle`.
+  }];
+  let llvmOp = "CoroDestroyOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic DoneOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroDoneOp : CIR_CoroIntrinsicOp<"done",
+    (ins CIR_VoidPtrType:$handle),
+    (outs CIR_AnyBoolType:$result)> {
+  let summary = "Represents llvm.coro.done";
+  let description = [{
+    Checks whether a suspended coroutine identified by `handle` is at its
+    final suspension point.
+  }];
+  let llvmOp = "CoroDoneOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic NoopOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroNoopOp : CIR_CoroIntrinsicOp<"noop",
+    (ins), (outs CIR_VoidPtrType:$result)> {
+  let summary = "Represents llvm.coro.noop";
+  let description = [{
+    Returns the coroutine handle for a coroutine that does nothing when resumed
+    or destroyed.
+  }];
+  let llvmOp = "CoroNoopOp";
+}
+
+//===----------------------------------------------------------------------===//
+// Coroutine intrinsic AlignOp
+//===----------------------------------------------------------------------===//
+
+def CIR_CoroAlignOp : CIR_CoroIntrinsicOp<"align",
+    (ins), (outs CIR_UInt64:$result)> {
+  let summary = "Represents llvm.coro.align";
+  let description = [{
+    Returns the required alignment, in bytes, of the coroutine frame.
+  }];
+  let llvmOp = "CoroAlignOp";
+}
+
 
//===----------------------------------------------------------------------===//
 // CopyOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index d4c17d3c5f24f..291f10e59ecae 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1735,24 +1735,27 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     return RValue::get(emitCoroEndBuiltinCall(e).getResult());
   case Builtin::BI__builtin_coro_promise:
     return RValue::get(emitCoroPromiseBuiltinCall(e).getResult());
-  case Builtin::BI__builtin_coro_resume:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_resume NYI");
-    return getUndefRValue(e->getType());
+  case Builtin::BI__builtin_coro_resume: {
+    emitCoroResumeBuiltinCall(e);
+    return RValue::get(nullptr);
+  }
   case Builtin::BI__builtin_coro_noop:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_noop NYI");
-    return getUndefRValue(e->getType());
-  case Builtin::BI__builtin_coro_destroy:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_destroy NYI");
-    return getUndefRValue(e->getType());
+    return RValue::get(emitCoroNoopBuiltinCall(e).getResult());
+  case Builtin::BI__builtin_coro_destroy: {
+    emitCoroDestroyBuiltinCall(e);
+    return RValue::get(nullptr);
+  }
   case Builtin::BI__builtin_coro_done:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_done NYI");
-    return getUndefRValue(e->getType());
+    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_align:
-    cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_align NYI");
-    return getUndefRValue(e->getType());
+    return RValue::get(emitCoroSuspendBuiltinCall(e).getResult());
+  case Builtin::BI__builtin_coro_align: {
+    mlir::Value align = emitCoroAlignBuiltinCall(e).getResult();
+    mlir::Type expectedTy = convertType(e->getType());
+    if (align.getType() != expectedTy)
+      align = builder.createIntCast(align, expectedTy);
+    return RValue::get(align);
+  }
 
   case Builtin::BI__builtin_coro_frame: {
     return emitCoroutineFrame();
@@ -1764,7 +1767,11 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   }
 
   case Builtin::BI__builtin_coro_size: {
-    return RValue::get(emitCoroSizeBuiltinCall(e).getResult());
+    mlir::Value size = emitCoroSizeBuiltinCall(e).getResult();
+    mlir::Type expectedTy = convertType(e->getType());
+    if (size.getType() != expectedTy)
+      size = builder.createIntCast(size, expectedTy);
+    return RValue::get(size);
   }
 
   case Builtin::BI__builtin_constant_p: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 7004f2d7750e6..a57d1151b84bb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -321,6 +321,46 @@ CIRGenFunction::emitCoroPromiseBuiltinCall(const CallExpr 
*e) {
   return coroPromise;
 }
 
+cir::CoroResumeOp CIRGenFunction::emitCoroResumeBuiltinCall(const CallExpr *e) 
{
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  mlir::Value handle = emitScalarExpr(e->getArg(0));
+  return cir::CoroResumeOp::create(cgm.getBuilder(), loc, handle);
+}
+
+cir::CoroDestroyOp
+CIRGenFunction::emitCoroDestroyBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  mlir::Value handle = emitScalarExpr(e->getArg(0));
+  return cir::CoroDestroyOp::create(cgm.getBuilder(), loc, handle);
+}
+
+cir::CoroDoneOp CIRGenFunction::emitCoroDoneBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  mlir::Value handle = emitScalarExpr(e->getArg(0));
+  return cir::CoroDoneOp::create(cgm.getBuilder(), loc,
+                                 convertType(e->getType()), handle);
+}
+
+cir::CoroNoopOp CIRGenFunction::emitCoroNoopBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  return cir::CoroNoopOp::create(cgm.getBuilder(), loc,
+                                 convertType(e->getType()));
+}
+
+cir::CoroAlignOp CIRGenFunction::emitCoroAlignBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  return cir::CoroAlignOp::create(cgm.getBuilder(), loc);
+}
+
+cir::CoroSuspendOp
+CIRGenFunction::emitCoroSuspendBuiltinCall(const CallExpr *e) {
+  mlir::Location loc = getLoc(e->getBeginLoc());
+  CIRGenBuilderTy &builder = cgm.getBuilder();
+  mlir::Value saveToken = cir::TokenNoneOp::create(builder, loc);
+  mlir::Value finalSuspend = emitScalarExpr(e->getArg(0));
+  return cir::CoroSuspendOp::create(builder, loc, saveToken, finalSuspend);
+}
+
 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 8547a77e86faf..f5264c785f81c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1916,6 +1916,12 @@ class CIRGenFunction : public CIRGenTypeCache {
   cir::CoroAllocOp emitCoroAllocBuiltinCall(const CallExpr *e);
   cir::CoroBeginOp emitCoroBeginBuiltinCall(const CallExpr *e);
   cir::CoroPromiseOp emitCoroPromiseBuiltinCall(const CallExpr *e);
+  cir::CoroResumeOp emitCoroResumeBuiltinCall(const CallExpr *e);
+  cir::CoroDestroyOp emitCoroDestroyBuiltinCall(const CallExpr *e);
+  cir::CoroDoneOp emitCoroDoneBuiltinCall(const CallExpr *e);
+  cir::CoroNoopOp emitCoroNoopBuiltinCall(const CallExpr *e);
+  cir::CoroAlignOp emitCoroAlignBuiltinCall(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/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 113c687970534..82f5520ccf673 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2853,10 +2853,13 @@ mlir::LogicalResult cir::FuncOp::verify() {
 
   if (!isDeclaration() && getCoroutine()) {
     bool foundAwait = false;
+    bool foundCoroSuspend = false;
     int coroBodyCount = 0;
     this->walk([&](Operation *op) {
-      if (auto await = dyn_cast<AwaitOp>(op)) {
+      if (isa<AwaitOp>(op)) {
         foundAwait = true;
+      } else if (isa<CoroSuspendOp>(op)) {
+        foundCoroSuspend = true;
       } else if (isa<CoroBodyOp>(op)) {
         coroBodyCount++;
         if (coroBodyCount > 1) {
@@ -2865,10 +2868,10 @@ mlir::LogicalResult cir::FuncOp::verify() {
       }
       return mlir::WalkResult::advance();
     });
-    if (!foundAwait)
+    if (!foundAwait && !foundCoroSuspend)
       return emitOpError()
              << "coroutine body must use at least one cir.await op";
-    if (coroBodyCount != 1)
+    if (coroBodyCount > 1 || (coroBodyCount != 1 && !foundCoroSuspend))
       return emitOpError()
              << "coroutine function must have exactly one cir.body op";
   }
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6761da8be6491..eec77588ddba5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2813,9 +2813,25 @@ mlir::LogicalResult 
CIRToLLVMFuncOpLowering::matchAndRewrite(
   // function attribute, so route it through the `passthrough` array. The MLIR
   // LLVM IR translator forwards `passthrough` entries to LLVM IR as function
   // attributes.
-  if (op->hasAttr(CIRDialect::getStrictFPAttrName()))
-    fn.setPassthroughAttr(rewriter.getArrayAttr(
-        {rewriter.getStringAttr(CIRDialect::getStrictFPAttrName())}));
+  if (auto passthrough = op->getAttrOfType<mlir::ArrayAttr>("passthrough"))
+    fn.setPassthroughAttr(passthrough);
+
+  if (op->hasAttr(CIRDialect::getStrictFPAttrName())) {
+    llvm::SmallVector<mlir::Attribute, 2> passthroughAttrs;
+    if (auto existing = fn.getPassthroughAttr())
+      passthroughAttrs.append(existing.begin(), existing.end());
+    passthroughAttrs.push_back(
+        rewriter.getStringAttr(CIRDialect::getStrictFPAttrName()));
+    fn.setPassthroughAttr(rewriter.getArrayAttr(passthroughAttrs));
+  }
+
+  if (op.getCoroutine()) {
+    llvm::SmallVector<mlir::Attribute, 2> passthroughAttrs;
+    if (auto existing = fn.getPassthroughAttr())
+      passthroughAttrs.append(existing.begin(), existing.end());
+    passthroughAttrs.push_back(rewriter.getStringAttr("presplitcoroutine"));
+    fn.setPassthroughAttr(rewriter.getArrayAttr(passthroughAttrs));
+  }
 
   if (std::optional<cir::InlineKind> inlineKind = op.getInlineKind()) {
     fn.setNoInline(*inlineKind == cir::InlineKind::NoInline);
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
index 564dc4e49a9cf..c21d7bbac0b65 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-builtins.cpp
@@ -29,8 +29,13 @@ void f(int n) {
 
   // LLVM: call i1 @llvm.coro.alloc(token %[[COROID]])
 
-  // TODO
-  //__builtin_coro_noop();
+  __builtin_coro_noop();
+  // CIR: cir.coro.intrinsic.noop() : () -> !cir.ptr<!void>
+  // LLVM: call ptr @llvm.coro.noop()
+
+  __builtin_coro_align();
+  // CIR: cir.coro.intrinsic.align() : () -> !u64i
+  // LLVM: call i64 @llvm.coro.align.i64()
 
   __builtin_coro_begin(myAlloc(__builtin_coro_size()));
   // TODO(CIR): Support both variants of the coroutine size intrinsic, matching
@@ -44,14 +49,17 @@ void f(int n) {
   // LLVM: %[[MEM:.*]] = call noundef ptr @_Z7myAllocx(i64 noundef %[[SIZE]])
   // LLVM: %[[FRAME:.*]] = call ptr @llvm.coro.begin(token %[[COROID]], ptr 
%[[MEM]])
 
-  // TODO(CIR):
-  //__builtin_coro_resume(__builtin_coro_frame());
+  __builtin_coro_resume(__builtin_coro_frame());
+  // CIR: cir.coro.intrinsic.resume(%[[FRAME]]) : (!cir.ptr<!void>) -> ()
+  // LLVM: call void @llvm.coro.resume(ptr %[[FRAME]])
 
-  // TODO(CIR):
-  //__builtin_coro_destroy(__builtin_coro_frame());
+  __builtin_coro_destroy(__builtin_coro_frame());
+  // CIR: cir.coro.intrinsic.destroy(%[[FRAME]]) : (!cir.ptr<!void>) -> ()
+  // LLVM: call void @llvm.coro.destroy(ptr %[[FRAME]])
 
-  // TODO(CIR):
-  //__builtin_coro_done(__builtin_coro_frame());
+  __builtin_coro_done(__builtin_coro_frame());
+  // CIR: cir.coro.intrinsic.done(%[[FRAME]]) : (!cir.ptr<!void>) -> !cir.bool
+  // LLVM: call i1 @llvm.coro.done(ptr %[[FRAME]])
 
   __builtin_coro_promise(__builtin_coro_frame(), 48, 0);
   // CIR: %[[ALIGN:.*]] = cir.const #cir.int<48> : !s32i
@@ -72,6 +80,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(1);
+  // CIR: %[[TK_SAVE:.*]] = cir.token.none
+  // CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+  // CIR: %[[SUSP_FINAL:.*]] = cir.cast int_to_bool %[[ONE]] : !s32i -> 
!cir.bool
+  // CIR: cir.coro.intrinsic.suspend(%[[TK_SAVE]], %[[SUSP_FINAL]]) : (token, 
!cir.bool) -> !s8i
+  // LLVM: call i8 @llvm.coro.suspend(token none, i1 true)
 }
diff --git a/clang/test/CIR/Lowering/coro-intrinsics.cir 
b/clang/test/CIR/Lowering/coro-intrinsics.cir
new file mode 100644
index 0000000000000..c2dc430458844
--- /dev/null
+++ b/clang/test/CIR/Lowering/coro-intrinsics.cir
@@ -0,0 +1,52 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s -check-prefix=MLIR
+// RUN: cir-translate %s -cir-to-llvmir --disable-cc-lowering | FileCheck %s 
-check-prefix=LLVM
+
+!void = !cir.void
+!s8i = !cir.int<s, 8>
+!u64i = !cir.int<u, 64>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func @test_coro_intrinsics(%arg0: !cir.ptr<!void>) {
+    %save = cir.coro.intrinsic.save(%arg0) : (!cir.ptr<!void>) -> token
+    %false = cir.const #cir.bool<false> : !cir.bool
+    %susp = cir.coro.intrinsic.suspend(%save, %false) : (token, !cir.bool) -> 
!s8i
+    cir.coro.intrinsic.resume(%arg0) : (!cir.ptr<!void>) -> ()
+    cir.coro.intrinsic.destroy(%arg0) : (!cir.ptr<!void>) -> ()
+    %done = cir.coro.intrinsic.done(%arg0) : (!cir.ptr<!void>) -> !cir.bool
+    %noop = cir.coro.intrinsic.noop() : () -> !cir.ptr<!void>
+    %align = cir.coro.intrinsic.align() : () -> !u64i
+    cir.return
+  }
+
+  cir.func coroutine @test_coro_func(%arg0: !cir.ptr<!void>) {
+    %save = cir.coro.intrinsic.save(%arg0) : (!cir.ptr<!void>) -> token
+    %false = cir.const #cir.bool<false> : !cir.bool
+    %susp = cir.coro.intrinsic.suspend(%save, %false) : (token, !cir.bool) -> 
!s8i
+    cir.return
+  }
+}
+
+// MLIR-LABEL: llvm.func @test_coro_intrinsics(%arg0: !llvm.ptr)
+// MLIR: %[[SAVE:.*]] = llvm.intr.coro.save %arg0 : (!llvm.ptr) -> token
+// MLIR: %[[FALSE:.*]] = llvm.mlir.constant(false) : i1
+// MLIR: %[[SUSP:.*]] = llvm.intr.coro.suspend %[[SAVE]], %[[FALSE]] : i8
+// MLIR: llvm.intr.coro.resume %arg0 : !llvm.ptr
+// MLIR: llvm.intr.coro.destroy %arg0 : !llvm.ptr
+// MLIR: %[[DONE:.*]] = llvm.intr.coro.done %arg0 : (!llvm.ptr) -> i1
+// MLIR: %[[NOOP:.*]] = llvm.intr.coro.noop : !llvm.ptr
+// MLIR: %[[ALIGN:.*]] = llvm.intr.coro.align : i64
+
+// MLIR-LABEL: llvm.func @test_coro_func(%arg0: !llvm.ptr)
+// MLIR-SAME: passthrough = ["presplitcoroutine"]
+
+// LLVM-LABEL: define void @test_coro_intrinsics(ptr %0)
+// LLVM: %[[SAVE:.*]] = call token @llvm.coro.save(ptr %0)
+// LLVM: %[[SUSP:.*]] = call i8 @llvm.coro.suspend(token %[[SAVE]], i1 false)
+// LLVM: call void @llvm.coro.resume(ptr %0)
+// LLVM: call void @llvm.coro.destroy(ptr %0)
+// LLVM: %[[DONE:.*]] = call i1 @llvm.coro.done(ptr %0)
+// LLVM: %[[NOOP:.*]] = call ptr @llvm.coro.noop()
+// LLVM: %[[ALIGN:.*]] = call i64 @llvm.coro.align.i64()
+
+// LLVM: define void @test_coro_func(ptr %0) #[[CORO_ATTR:[0-9]+]]
+// LLVM: attributes #[[CORO_ATTR]] = {{.*}}presplitcoroutine

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

Reply via email to