[clang] [CIR] Support void calls in cir.call_llvm_intrinsic lowering (PR #199516)

via cfe-commits cfe-commits at lists.llvm.org
Mon May 25 10:09:05 PDT 2026


https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/199516

>From 4f96d7b0eb8f0ef4578a7718e99a7c91a7c67f55 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Mon, 25 May 2026 15:08:32 +0530
Subject: [PATCH] [CIR] Fix cir.call_llvm_intrinsic lowering for 0-result ops

---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 20 +++++++++-----
 .../test/CIR/Lowering/call-llvm-intrinsic.cir | 27 +++++++++++++++++++
 2 files changed, 41 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/call-llvm-intrinsic.cir

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c4e98e299dfc1..8940272d27ffe 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -358,8 +358,12 @@ createCallLLVMIntrinsicOp(mlir::ConversionPatternRewriter &rewriter,
                           mlir::Type resultTy, mlir::ValueRange operands) {
   auto intrinsicNameAttr =
       mlir::StringAttr::get(rewriter.getContext(), intrinsicName);
-  return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
-                                             intrinsicNameAttr, operands);
+  // CallIntrinsicOp has distinct void / single-result create overloads.
+  if (resultTy)
+    return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, resultTy,
+                                               intrinsicNameAttr, operands);
+  return mlir::LLVM::CallIntrinsicOp::create(rewriter, loc, intrinsicNameAttr,
+                                             operands);
 }
 
 static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(
@@ -375,10 +379,14 @@ static mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp(
 mlir::LogicalResult CIRToLLVMLLVMIntrinsicCallOpLowering::matchAndRewrite(
     cir::LLVMIntrinsicCallOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  mlir::Type llvmResTy =
-      getTypeConverter()->convertType(op->getResultTypes()[0]);
-  if (!llvmResTy)
-    return op.emitError("expected LLVM result type");
+  // Result is Optional on the op, so void intrinsics have zero
+  // results; leave llvmResTy null in that case.
+  mlir::Type llvmResTy;
+  if (op->getNumResults() != 0) {
+    llvmResTy = getTypeConverter()->convertType(op->getResultTypes()[0]);
+    if (!llvmResTy)
+      return op.emitError("expected LLVM result type");
+  }
   StringRef name = op.getIntrinsicName();
 
   // Some LLVM intrinsics require ElementType attribute to be attached to
diff --git a/clang/test/CIR/Lowering/call-llvm-intrinsic.cir b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
new file mode 100644
index 0000000000000..edd492aa7477c
--- /dev/null
+++ b/clang/test/CIR/Lowering/call-llvm-intrinsic.cir
@@ -0,0 +1,27 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s
+
+// Contract test for CIRToLLVMLLVMIntrinsicCallOpLowering: the op def
+// declares Optional<CIR_AnyType>:$result, so the lowering must accept
+// 0-result (void) calls in addition to the single-result case.
+
+!s32i = !cir.int<s, 32>
+
+module {
+  // 0-result, 0-operand.
+  // CHECK-LABEL: llvm.func @void_no_operands
+  // CHECK:         llvm.call_intrinsic "llvm.donothing"() : () -> ()
+  // CHECK:         llvm.return
+  cir.func @void_no_operands() {
+    cir.call_llvm_intrinsic "donothing" : () -> ()
+    cir.return
+  }
+
+  // 0-result with one operand.
+  // CHECK-LABEL: llvm.func @void_with_operand
+  // CHECK:         llvm.call_intrinsic "llvm.amdgcn.s.sleep"(%{{.*}}) : (i32) -> ()
+  // CHECK:         llvm.return
+  cir.func @void_with_operand(%arg0: !s32i) {
+    cir.call_llvm_intrinsic "amdgcn.s.sleep" %arg0 : (!s32i) -> ()
+    cir.return
+  }
+}



More information about the cfe-commits mailing list