[clang] Cir neon rounding (PR #195021)

via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 30 00:03:12 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: AbdallahRashed (AbdallahRashed)

<details>
<summary>Changes</summary>

part of https://github.com/llvm/llvm-project/issues/185382

---
Full diff: https://github.com/llvm/llvm-project/pull/195021.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp (+42-4) 
- (added) clang/test/CIR/CodeGenBuiltins/AArch64/neon-vrnd.c (+118) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index cac5f8eced8a7..079492148b6d7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -744,8 +744,6 @@ static mlir::Value emitCommonNeonBuiltinExpr(
   case NEON::BI__builtin_neon_vrecpeq_v:
   case NEON::BI__builtin_neon_vrsqrte_v:
   case NEON::BI__builtin_neon_vrsqrteq_v:
-  case NEON::BI__builtin_neon_vrndi_v:
-  case NEON::BI__builtin_neon_vrndiq_v:
     cgf.cgm.errorNYI(expr->getSourceRange(),
                      std::string("unimplemented AArch64 builtin call: ") +
                          ctx.BuiltinInfo.getName(builtinID));
@@ -843,6 +841,32 @@ static mlir::Value emitCommonNeonBuiltinExpr(
   case NEON::BI__builtin_neon_vmulq_v:
     return cgf.getBuilder().emitIntrinsicCallOp(loc, "aarch64.neon.pmul", vTy,
                                                 ops);
+  case NEON::BI__builtin_neon_vrndi_v:
+  case NEON::BI__builtin_neon_vrndiq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgf.cgm, cgf.getBuilder(), {ty}, ops, "nearbyint", ty,
+                        loc);
+  case NEON::BI__builtin_neon_vrnd32x_f32:
+  case NEON::BI__builtin_neon_vrnd32xq_f32:
+  case NEON::BI__builtin_neon_vrnd32x_f64:
+  case NEON::BI__builtin_neon_vrnd32xq_f64:
+  case NEON::BI__builtin_neon_vrnd32z_f32:
+  case NEON::BI__builtin_neon_vrnd32zq_f32:
+  case NEON::BI__builtin_neon_vrnd32z_f64:
+  case NEON::BI__builtin_neon_vrnd32zq_f64:
+  case NEON::BI__builtin_neon_vrnd64x_f32:
+  case NEON::BI__builtin_neon_vrnd64xq_f32:
+  case NEON::BI__builtin_neon_vrnd64x_f64:
+  case NEON::BI__builtin_neon_vrnd64xq_f64:
+  case NEON::BI__builtin_neon_vrnd64z_f32:
+  case NEON::BI__builtin_neon_vrnd64zq_f32:
+  case NEON::BI__builtin_neon_vrnd64z_f64:
+  case NEON::BI__builtin_neon_vrnd64zq_f64: {
+    llvm::StringRef intrName = getLLVMIntrNameNoPrefix(
+        static_cast<llvm::Intrinsic::ID>(llvmIntrinsic));
+    return emitNeonCall(cgf.cgm, cgf.getBuilder(), {ty}, ops, intrName, ty,
+                        loc);
+  }
   case NEON::BI__builtin_neon_vusmmlaq_s32:
   case NEON::BI__builtin_neon_vusdot_s32:
   case NEON::BI__builtin_neon_vusdotq_s32:
@@ -2602,21 +2626,37 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vrndah_f16:
   case NEON::BI__builtin_neon_vrnda_v:
   case NEON::BI__builtin_neon_vrndaq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "round", ty, loc);
   case NEON::BI__builtin_neon_vrndih_f16:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "nearbyint", ty, loc);
   case NEON::BI__builtin_neon_vrndmh_f16:
   case NEON::BI__builtin_neon_vrndm_v:
   case NEON::BI__builtin_neon_vrndmq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "floor", ty, loc);
   case NEON::BI__builtin_neon_vrndnh_f16:
   case NEON::BI__builtin_neon_vrndn_v:
   case NEON::BI__builtin_neon_vrndnq_v:
   case NEON::BI__builtin_neon_vrndns_f32:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "roundeven", ty, loc);
   case NEON::BI__builtin_neon_vrndph_f16:
   case NEON::BI__builtin_neon_vrndp_v:
   case NEON::BI__builtin_neon_vrndpq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "ceil", ty, loc);
   case NEON::BI__builtin_neon_vrndxh_f16:
   case NEON::BI__builtin_neon_vrndx_v:
   case NEON::BI__builtin_neon_vrndxq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "rint", ty, loc);
   case NEON::BI__builtin_neon_vrndh_f16:
+  case NEON::BI__builtin_neon_vrnd_v:
+  case NEON::BI__builtin_neon_vrndq_v:
+    assert(!cir::MissingFeatures::emitConstrainedFPCall());
+    return emitNeonCall(cgm, builder, {ty}, ops, "trunc", ty, loc);
   case NEON::BI__builtin_neon_vrnd32x_f32:
   case NEON::BI__builtin_neon_vrnd32xq_f32:
   case NEON::BI__builtin_neon_vrnd32x_f64:
@@ -2633,8 +2673,6 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vrnd64zq_f32:
   case NEON::BI__builtin_neon_vrnd64z_f64:
   case NEON::BI__builtin_neon_vrnd64zq_f64:
-  case NEON::BI__builtin_neon_vrnd_v:
-  case NEON::BI__builtin_neon_vrndq_v:
     cgm.errorNYI(expr->getSourceRange(),
                  std::string("unimplemented AArch64 builtin call: ") +
                      getContext().BuiltinInfo.getName(builtinID));
diff --git a/clang/test/CIR/CodeGenBuiltins/AArch64/neon-vrnd.c b/clang/test/CIR/CodeGenBuiltins/AArch64/neon-vrnd.c
new file mode 100644
index 0000000000000..e2ce08af5626b
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/AArch64/neon-vrnd.c
@@ -0,0 +1,118 @@
+// Test AArch64 NEON rounding builtins
+
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon \
+// RUN:   -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon \
+// RUN:   -fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_neon.h>
+
+// vrndq (trunc)
+float32x4_t test_vrndq_f32(float32x4_t a) {
+  return vrndq_f32(a);
+}
+// CIR-LABEL: @vrndq_f32
+// CIR: cir.call_llvm_intrinsic "trunc" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndq_f32
+// LLVM: call <4 x float> @llvm.trunc.v4f32
+
+// vrndaq (round)
+float32x4_t test_vrndaq_f32(float32x4_t a) {
+  return vrndaq_f32(a);
+}
+// CIR-LABEL: @vrndaq_f32
+// CIR: cir.call_llvm_intrinsic "round" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndaq_f32
+// LLVM: call <4 x float> @llvm.round.v4f32
+
+// vrndiq (nearbyint)
+float32x4_t test_vrndiq_f32(float32x4_t a) {
+  return vrndiq_f32(a);
+}
+// CIR-LABEL: @vrndiq_f32
+// CIR: cir.call_llvm_intrinsic "nearbyint" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndiq_f32
+// LLVM: call <4 x float> @llvm.nearbyint.v4f32
+
+// vrndmq (floor)
+float32x4_t test_vrndmq_f32(float32x4_t a) {
+  return vrndmq_f32(a);
+}
+// CIR-LABEL: @vrndmq_f32
+// CIR: cir.call_llvm_intrinsic "floor" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndmq_f32
+// LLVM: call <4 x float> @llvm.floor.v4f32
+
+// vrndnq (roundeven)
+float32x4_t test_vrndnq_f32(float32x4_t a) {
+  return vrndnq_f32(a);
+}
+// CIR-LABEL: @vrndnq_f32
+// CIR: cir.call_llvm_intrinsic "roundeven" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndnq_f32
+// LLVM: call <4 x float> @llvm.roundeven.v4f32
+
+// vrndpq (ceil)
+float32x4_t test_vrndpq_f32(float32x4_t a) {
+  return vrndpq_f32(a);
+}
+// CIR-LABEL: @vrndpq_f32
+// CIR: cir.call_llvm_intrinsic "ceil" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndpq_f32
+// LLVM: call <4 x float> @llvm.ceil.v4f32
+
+// vrndxq (rint)
+float32x4_t test_vrndxq_f32(float32x4_t a) {
+  return vrndxq_f32(a);
+}
+// CIR-LABEL: @vrndxq_f32
+// CIR: cir.call_llvm_intrinsic "rint" {{%.*}} : (!cir.vector<4 x !cir.float>) -> !cir.vector<4 x !cir.float>
+// LLVM-LABEL: @test_vrndxq_f32
+// LLVM: call <4 x float> @llvm.rint.v4f32
+
+// Non-q (64-bit) variants
+float32x2_t test_vrnd_f32(float32x2_t a) {
+  return vrnd_f32(a);
+}
+// CIR-LABEL: @vrnd_f32
+// CIR: cir.call_llvm_intrinsic "trunc" {{%.*}} : (!cir.vector<2 x !cir.float>) -> !cir.vector<2 x !cir.float>
+// LLVM-LABEL: @test_vrnd_f32
+// LLVM: call <2 x float> @llvm.trunc.v2f32
+
+float32x2_t test_vrnda_f32(float32x2_t a) {
+  return vrnda_f32(a);
+}
+// CIR-LABEL: @vrnda_f32
+// CIR: cir.call_llvm_intrinsic "round" {{%.*}} : (!cir.vector<2 x !cir.float>) -> !cir.vector<2 x !cir.float>
+// LLVM-LABEL: @test_vrnda_f32
+// LLVM: call <2 x float> @llvm.round.v2f32
+
+float32x2_t test_vrndi_f32(float32x2_t a) {
+  return vrndi_f32(a);
+}
+// CIR-LABEL: @vrndi_f32
+// CIR: cir.call_llvm_intrinsic "nearbyint" {{%.*}} : (!cir.vector<2 x !cir.float>) -> !cir.vector<2 x !cir.float>
+// LLVM-LABEL: @test_vrndi_f32
+// LLVM: call <2 x float> @llvm.nearbyint.v2f32
+
+// f64 variants
+float64x2_t test_vrndq_f64(float64x2_t a) {
+  return vrndq_f64(a);
+}
+// CIR-LABEL: @vrndq_f64
+// CIR: cir.call_llvm_intrinsic "trunc" {{%.*}} : (!cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+// LLVM-LABEL: @test_vrndq_f64
+// LLVM: call <2 x double> @llvm.trunc.v2f64
+
+float64x2_t test_vrndiq_f64(float64x2_t a) {
+  return vrndiq_f64(a);
+}
+// CIR-LABEL: @vrndiq_f64
+// CIR: cir.call_llvm_intrinsic "nearbyint" {{%.*}} : (!cir.vector<2 x !cir.double>) -> !cir.vector<2 x !cir.double>
+// LLVM-LABEL: @test_vrndiq_f64
+// LLVM: call <2 x double> @llvm.nearbyint.v2f64

``````````

</details>


https://github.com/llvm/llvm-project/pull/195021


More information about the cfe-commits mailing list