Author: Andrzej WarzyƄski
Date: 2026-08-18T13:47:28+01:00
New Revision: ac5b4c19e5ca6211b7a0e3dc6a052ffc1730f0c7

URL: 
https://github.com/llvm/llvm-project/commit/ac5b4c19e5ca6211b7a0e3dc6a052ffc1730f0c7
DIFF: 
https://github.com/llvm/llvm-project/commit/ac5b4c19e5ca6211b7a0e3dc6a052ffc1730f0c7.diff

LOG: [clang][CIR][AArch64] Add lowering for conversion intrinsics (#216757)

This PR adds lowering for intrinsic from the following groups:
* https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions

It continues the work started in #190961, #193273, #199990, #209252
and #211609.

This PR implements the conversions for the following "truncating to
nearest" intrinsics:
  * vcvtn_s32_f32
  * vcvtnq_s32_f32
  * vcvtn_u32_f32
  * vcvtnq_u32_f32
  * vcvtns_s32_f32
  * vcvtns_s64_f32
  * vcvtns_u32_f32
  * vcvtns_u64_f32
  * vcvtn_s64_f64
  * vcvtnq_s64_f64
  * vcvtn_u64_f64
  * vcvtnq_u64_f64

The following "truncating to nearest" intrinsics will be added in the
next PR:
  * vcvtnd_s32_f64
  * vcvtnd_s64_f64
  * vcvtnd_u32_f64
  * vcvtnd_u64_f64

The corresponding tests are moved from:
  * clang/test/CodeGen/AArch64/

to:
  * clang/test/CodeGen/AArch64/neon/

The lowering follows the existing implementation in
CodeGen/TargetBuiltins/ARM.cpp. I also did a minor re-shuffling of the
order of intrinsics in the switch statement (in ARM.cpp and
CIRGenBuiltinAArch64.cpp) to allow code re-use and avoid having to
insert many NYI(s) while the fp16 variants are not implemented.

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
    clang/lib/CodeGen/TargetBuiltins/ARM.cpp
    clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
    clang/test/CodeGen/AArch64/neon-intrinsics.c
    clang/test/CodeGen/AArch64/neon-misc.c
    clang/test/CodeGen/AArch64/neon/intrinsics.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 24c47198a39be..bb20e8f3ed73d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -451,6 +451,10 @@ emitCommonNeonSISDBuiltinExpr(CIRGenFunction &cgf,
   case NEON::BI__builtin_neon_vcvts_s64_f32:
   case NEON::BI__builtin_neon_vcvts_u32_f32:
   case NEON::BI__builtin_neon_vcvts_u64_f32:
+  case NEON::BI__builtin_neon_vcvtns_s32_f32:
+  case NEON::BI__builtin_neon_vcvtns_s64_f32:
+  case NEON::BI__builtin_neon_vcvtns_u32_f32:
+  case NEON::BI__builtin_neon_vcvtns_u64_f32:
   case NEON::BI__builtin_neon_vaddlv_s32:
   case NEON::BI__builtin_neon_vaddlv_u32:
   case NEON::BI__builtin_neon_vaddlvq_s32:
@@ -3266,17 +3270,28 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vcvtm_u64_v:
   case NEON::BI__builtin_neon_vcvtmq_u64_v:
   case NEON::BI__builtin_neon_vcvtn_s16_f16:
-  case NEON::BI__builtin_neon_vcvtn_s32_v:
   case NEON::BI__builtin_neon_vcvtnq_s16_f16:
-  case NEON::BI__builtin_neon_vcvtnq_s32_v:
   case NEON::BI__builtin_neon_vcvtn_u16_f16:
-  case NEON::BI__builtin_neon_vcvtn_u32_v:
   case NEON::BI__builtin_neon_vcvtnq_u16_f16:
+    cgm.errorNYI(expr->getSourceRange(),
+                 std::string("unimplemented AArch64 builtin call: ") +
+                     getContext().BuiltinInfo.getName(builtinID));
+    return mlir::Value{};
+
+  case NEON::BI__builtin_neon_vcvtn_s32_v:
+  case NEON::BI__builtin_neon_vcvtnq_s32_v:
+  case NEON::BI__builtin_neon_vcvtn_u32_v:
   case NEON::BI__builtin_neon_vcvtnq_u32_v:
   case NEON::BI__builtin_neon_vcvtn_s64_v:
   case NEON::BI__builtin_neon_vcvtnq_s64_v:
   case NEON::BI__builtin_neon_vcvtn_u64_v:
-  case NEON::BI__builtin_neon_vcvtnq_u64_v:
+  case NEON::BI__builtin_neon_vcvtnq_u64_v: {
+    auto argTy = getFloatNeonType(*this, type);
+    llvm::StringRef intrName =
+        usgn ? "aarch64.neon.fcvtnu" : "aarch64.neon.fcvtns";
+    return emitNeonCall(cgm, builder, {argTy}, ops, intrName, ty, loc);
+  }
+
   case NEON::BI__builtin_neon_vcvtp_s16_f16:
   case NEON::BI__builtin_neon_vcvtp_s32_v:
   case NEON::BI__builtin_neon_vcvtpq_s16_f16:

diff  --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp 
b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 45b0f3d0143e5..bc322ae5c8b17 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -6419,12 +6419,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned 
BuiltinID,
     return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "vcvtm");
   }
   case NEON::BI__builtin_neon_vcvtn_s16_f16:
-  case NEON::BI__builtin_neon_vcvtn_s32_v:
   case NEON::BI__builtin_neon_vcvtnq_s16_f16:
-  case NEON::BI__builtin_neon_vcvtnq_s32_v:
   case NEON::BI__builtin_neon_vcvtn_u16_f16:
-  case NEON::BI__builtin_neon_vcvtn_u32_v:
   case NEON::BI__builtin_neon_vcvtnq_u16_f16:
+  case NEON::BI__builtin_neon_vcvtn_s32_v:
+  case NEON::BI__builtin_neon_vcvtnq_s32_v:
+  case NEON::BI__builtin_neon_vcvtn_u32_v:
   case NEON::BI__builtin_neon_vcvtnq_u32_v:
   case NEON::BI__builtin_neon_vcvtn_s64_v:
   case NEON::BI__builtin_neon_vcvtnq_s64_v:

diff  --git a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c 
b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
index a128227cbe5d1..d1c76e0250549 100644
--- a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
@@ -176,16 +176,6 @@ uint32_t test_vcvtmd_u32_f64(float64_t a) {
   return (uint32_t)vcvtmd_u32_f64(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_s32_f32
-// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTNS_S32_F32_I:%.*]] = call i32 
@llvm.aarch64.neon.fcvtns.i32.f32(float [[A]])
-// CHECK-NEXT:    ret i32 [[VCVTNS_S32_F32_I]]
-//
-int32_t test_vcvtns_s32_f32(float32_t a) {
-  return (int32_t)vcvtns_s32_f32(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_s64_f64
 // CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -196,16 +186,6 @@ int64_t test_vcvtnd_s64_f64(float64_t a) {
   return (int64_t)vcvtnd_s64_f64(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_s64_f32
-// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTNS_S64_F32_I:%.*]] = call i64 
@llvm.aarch64.neon.fcvtns.i64.f32(float [[A]])
-// CHECK-NEXT:    ret i64 [[VCVTNS_S64_F32_I]]
-//
-int64_t test_vcvtns_s64_f32(float32_t a) {
-  return (int64_t)vcvtns_s64_f32(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_s32_f64
 // CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -216,16 +196,6 @@ int32_t test_vcvtnd_s32_f64(float64_t a) {
   return (int32_t)vcvtnd_s32_f64(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_u32_f32
-// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTNS_U32_F32_I:%.*]] = call i32 
@llvm.aarch64.neon.fcvtnu.i32.f32(float [[A]])
-// CHECK-NEXT:    ret i32 [[VCVTNS_U32_F32_I]]
-//
-uint32_t test_vcvtns_u32_f32(float32_t a) {
-  return (uint32_t)vcvtns_u32_f32(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_u64_f64
 // CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -236,16 +206,6 @@ uint64_t test_vcvtnd_u64_f64(float64_t a) {
   return (uint64_t)vcvtnd_u64_f64(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtns_u64_f32
-// CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTNS_U64_F32_I:%.*]] = call i64 
@llvm.aarch64.neon.fcvtnu.i64.f32(float [[A]])
-// CHECK-NEXT:    ret i64 [[VCVTNS_U64_F32_I]]
-//
-uint64_t test_vcvtns_u64_f32(float32_t a) {
-  return (uint64_t)vcvtns_u64_f32(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvtnd_u32_f64
 // CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:

diff  --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c 
b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index 5a44284434e3d..ca38406a1ed45 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -12440,34 +12440,6 @@ float64x1_t test_vneg_f64(float64x1_t a) {
   return vneg_f64(a);
 }
 
-// CHECK-LABEL: define dso_local <1 x i64> @test_vcvtn_s64_f64(
-// CHECK-SAME: <1 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <1 x double> [[A]] to i64
-// CHECK-NEXT:    [[__P0_ADDR_I_SROA_0_0_VEC_INSERT:%.*]] = insertelement <1 x 
i64> undef, i64 [[TMP0]], i64 0
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <1 x i64> 
[[__P0_ADDR_I_SROA_0_0_VEC_INSERT]] to <8 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <1 x i64> 
@llvm.aarch64.neon.fcvtns.v1i64.v1f64(<1 x double> [[VCVTN_I]])
-// CHECK-NEXT:    ret <1 x i64> [[VCVTN1_I]]
-//
-int64x1_t test_vcvtn_s64_f64(float64x1_t a) {
-  return vcvtn_s64_f64(a);
-}
-
-// CHECK-LABEL: define dso_local <1 x i64> @test_vcvtn_u64_f64(
-// CHECK-SAME: <1 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <1 x double> [[A]] to i64
-// CHECK-NEXT:    [[__P0_ADDR_I_SROA_0_0_VEC_INSERT:%.*]] = insertelement <1 x 
i64> undef, i64 [[TMP0]], i64 0
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <1 x i64> 
[[__P0_ADDR_I_SROA_0_0_VEC_INSERT]] to <8 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <1 x i64> 
@llvm.aarch64.neon.fcvtnu.v1i64.v1f64(<1 x double> [[VCVTN_I]])
-// CHECK-NEXT:    ret <1 x i64> [[VCVTN1_I]]
-//
-uint64x1_t test_vcvtn_u64_f64(float64x1_t a) {
-  return vcvtn_u64_f64(a);
-}
-
 // CHECK-LABEL: define dso_local <1 x i64> @test_vcvtp_s64_f64(
 // CHECK-SAME: <1 x double> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]

diff  --git a/clang/test/CodeGen/AArch64/neon-misc.c 
b/clang/test/CodeGen/AArch64/neon-misc.c
index 308718fd1bedf..9ce457d0121c1 100644
--- a/clang/test/CodeGen/AArch64/neon-misc.c
+++ b/clang/test/CodeGen/AArch64/neon-misc.c
@@ -2827,84 +2827,6 @@ float64x2_t test_vrndiq_f64(float64x2_t a) {
   return vrndiq_f64(a);
 }
 
-// CHECK-LABEL: define dso_local <2 x i32> @test_vcvtn_s32_f32(
-// CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <2 x i32> 
@llvm.aarch64.neon.fcvtns.v2i32.v2f32(<2 x float> [[VCVTN_I]])
-// CHECK-NEXT:    ret <2 x i32> [[VCVTN1_I]]
-//
-int32x2_t test_vcvtn_s32_f32(float32x2_t a) {
-  return vcvtn_s32_f32(a);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vcvtnq_s32_f32(
-// CHECK-SAME: <4 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[A]] to <4 x i32>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <4 x i32> 
@llvm.aarch64.neon.fcvtns.v4i32.v4f32(<4 x float> [[VCVTN_I]])
-// CHECK-NEXT:    ret <4 x i32> [[VCVTN1_I]]
-//
-int32x4_t test_vcvtnq_s32_f32(float32x4_t a) {
-  return vcvtnq_s32_f32(a);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vcvtnq_s64_f64(
-// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <2 x i64> 
@llvm.aarch64.neon.fcvtns.v2i64.v2f64(<2 x double> [[VCVTN_I]])
-// CHECK-NEXT:    ret <2 x i64> [[VCVTN1_I]]
-//
-int64x2_t test_vcvtnq_s64_f64(float64x2_t a) {
-  return vcvtnq_s64_f64(a);
-}
-
-// CHECK-LABEL: define dso_local <2 x i32> @test_vcvtn_u32_f32(
-// CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <2 x i32> 
@llvm.aarch64.neon.fcvtnu.v2i32.v2f32(<2 x float> [[VCVTN_I]])
-// CHECK-NEXT:    ret <2 x i32> [[VCVTN1_I]]
-//
-uint32x2_t test_vcvtn_u32_f32(float32x2_t a) {
-  return vcvtn_u32_f32(a);
-}
-
-// CHECK-LABEL: define dso_local <4 x i32> @test_vcvtnq_u32_f32(
-// CHECK-SAME: <4 x float> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x float> [[A]] to <4 x i32>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <4 x i32> 
@llvm.aarch64.neon.fcvtnu.v4i32.v4f32(<4 x float> [[VCVTN_I]])
-// CHECK-NEXT:    ret <4 x i32> [[VCVTN1_I]]
-//
-uint32x4_t test_vcvtnq_u32_f32(float32x4_t a) {
-  return vcvtnq_u32_f32(a);
-}
-
-// CHECK-LABEL: define dso_local <2 x i64> @test_vcvtnq_u64_f64(
-// CHECK-SAME: <2 x double> noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
-// CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
-// CHECK-NEXT:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK-NEXT:    [[VCVTN1_I:%.*]] = call <2 x i64> 
@llvm.aarch64.neon.fcvtnu.v2i64.v2f64(<2 x double> [[VCVTN_I]])
-// CHECK-NEXT:    ret <2 x i64> [[VCVTN1_I]]
-//
-uint64x2_t test_vcvtnq_u64_f64(float64x2_t a) {
-  return vcvtnq_u64_f64(a);
-}
-
 // CHECK-LABEL: define dso_local <2 x i32> @test_vcvtp_s32_f32(
 // CHECK-SAME: <2 x float> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]

diff  --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c 
b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 8bd34b3f052d2..31eb0205389c6 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -4678,6 +4678,170 @@ uint64_t test_vcvts_u64_f32(float32_t a) {
   return (uint64_t)vcvts_u64_f32(a);
 }
 
+//===------------------------------------------------------===//
+// 2.1.4.1 Convearions (truncate to nearest)
+// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions
+//
+// TODO: Add vcvntd_* variants, e.g. vcvtnd_s32_f64.
+//===------------------------------------------------------===//
+// LLVM-LABEL: @test_vcvtn_s32_f32(
+// CIR-LABEL: @vcvtn_s32_f32(
+int32x2_t test_vcvtn_s32_f32(float32x2_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: <2 x float> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32>
+// LLVM:    [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
+// LLVM:    [[VCVTN1_I:%.*]] = call <2 x i32> 
@llvm.aarch64.neon.fcvtns.v2i32.v2f32(<2 x float> [[VCVTN_I]])
+// LLVM:    ret <2 x i32> [[VCVTN1_I]]
+  return vcvtn_s32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtn_u32_f32(
+// CIR-LABEL: @vcvtn_u32_f32(
+uint32x2_t test_vcvtn_u32_f32(float32x2_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: <2 x float> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <2 x float> [[A]] to <2 x i32>
+// LLVM:    [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
+// LLVM:    [[VCVTN1_I:%.*]] = call <2 x i32> 
@llvm.aarch64.neon.fcvtnu.v2i32.v2f32(<2 x float> [[VCVTN_I]])
+// LLVM:    ret <2 x i32> [[VCVTN1_I]]
+  return vcvtn_u32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtnq_s32_f32(
+// CIR-LABEL: @vcvtnq_s32_f32(
+int32x4_t test_vcvtnq_s32_f32(float32x4_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: <4 x float> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <4 x float> [[A]] to <4 x i32>
+// LLVM:    [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
+// LLVM:    [[VCVTN1_I:%.*]] = call <4 x i32> 
@llvm.aarch64.neon.fcvtns.v4i32.v4f32(<4 x float> [[VCVTN_I]])
+// LLVM:    ret <4 x i32> [[VCVTN1_I]]
+  return vcvtnq_s32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtnq_u32_f32(
+// CIR-LABEL: @vcvtnq_u32_f32(
+uint32x4_t test_vcvtnq_u32_f32(float32x4_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: <4 x float> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <4 x float> [[A]] to <4 x i32>
+// LLVM:    [[TMP1:%.*]] = bitcast <4 x i32> [[TMP0]] to <16 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
+// LLVM:    [[VCVTN1_I:%.*]] = call <4 x i32> 
@llvm.aarch64.neon.fcvtnu.v4i32.v4f32(<4 x float> [[VCVTN_I]])
+// LLVM:    ret <4 x i32> [[VCVTN1_I]]
+  return vcvtnq_u32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtns_s32_f32
+// CIR-LABEL: @vcvtns_s32_f32
+int32_t test_vcvtns_s32_f32(float32_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: (float noundef [[A:%.*]])
+// LLVM:    [[VCVTNS_S32_F32_I:%.*]] = call i32 
@llvm.aarch64.neon.fcvtns.i32.f32(float [[A]])
+// LLVM:    ret i32 [[VCVTNS_S32_F32_I]]
+  return (int32_t)vcvtns_s32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtns_s64_f32
+// CIR-LABEL: @vcvtns_s64_f32
+int64_t test_vcvtns_s64_f32(float32_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: (float noundef [[A:%.*]])
+// LLVM:    [[VCVTNS_S64_F32_I:%.*]] = call i64 
@llvm.aarch64.neon.fcvtns.i64.f32(float [[A]])
+// LLVM:    ret i64 [[VCVTNS_S64_F32_I]]
+  return (int64_t)vcvtns_s64_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtns_u32_f32
+// CIR-LABEL: @vcvtns_u32_f32
+uint32_t test_vcvtns_u32_f32(float32_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: (float noundef [[A:%.*]])
+// LLVM:    [[VCVTNS_U32_F32_I:%.*]] = call i32 
@llvm.aarch64.neon.fcvtnu.i32.f32(float [[A]])
+// LLVM:    ret i32 [[VCVTNS_U32_F32_I]]
+  return (uint32_t)vcvtns_u32_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtns_u64_f32
+// CIR-LABEL: @vcvtns_u64_f32
+uint64_t test_vcvtns_u64_f32(float32_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: (float noundef [[A:%.*]])
+// LLVM:    [[VCVTNS_U64_F32_I:%.*]] = call i64 
@llvm.aarch64.neon.fcvtnu.i64.f32(float [[A]])
+// LLVM:    ret i64 [[VCVTNS_U64_F32_I]]
+  return (uint64_t)vcvtns_u64_f32(a);
+}
+
+// LLVM-LABEL: @test_vcvtn_s64_f64(
+// CIR-LABEL: @vcvtn_s64_f64(
+int64x1_t test_vcvtn_s64_f64(float64x1_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: <1 x double> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <1 x double> [[A]] to i64
+// LLVM:    [[__P0_ADDR_I_SROA_0_0_VEC_INSERT:%.*]] = insertelement <1 x i64> 
undef, i64 [[TMP0]], i64 0
+// LLVM:    [[TMP1:%.*]] = bitcast <1 x i64> 
[[__P0_ADDR_I_SROA_0_0_VEC_INSERT]] to <8 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
+// LLVM:    [[VCVTN1_I:%.*]] = call <1 x i64> 
@llvm.aarch64.neon.fcvtns.v1i64.v1f64(<1 x double> [[VCVTN_I]])
+// LLVM:    ret <1 x i64> [[VCVTN1_I]]
+  return vcvtn_s64_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtnq_s64_f64(
+// CIR-LABEL: @vcvtnq_s64_f64(
+int64x2_t test_vcvtnq_s64_f64(float64x2_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtns"
+
+// LLVM-SAME: <2 x double> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
+// LLVM:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
+// LLVM:    [[VCVTN1_I:%.*]] = call <2 x i64> 
@llvm.aarch64.neon.fcvtns.v2i64.v2f64(<2 x double> [[VCVTN_I]])
+// LLVM:    ret <2 x i64> [[VCVTN1_I]]
+  return vcvtnq_s64_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtn_u64_f64(
+// CIR-LABEL: @vcvtn_u64_f64(
+uint64x1_t test_vcvtn_u64_f64(float64x1_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: <1 x double> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <1 x double> [[A]] to i64
+// LLVM:    [[__P0_ADDR_I_SROA_0_0_VEC_INSERT:%.*]] = insertelement <1 x i64> 
undef, i64 [[TMP0]], i64 0
+// LLVM:    [[TMP1:%.*]] = bitcast <1 x i64> 
[[__P0_ADDR_I_SROA_0_0_VEC_INSERT]] to <8 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
+// LLVM:    [[VCVTN1_I:%.*]] = call <1 x i64> 
@llvm.aarch64.neon.fcvtnu.v1i64.v1f64(<1 x double> [[VCVTN_I]])
+// LLVM:    ret <1 x i64> [[VCVTN1_I]]
+  return vcvtn_u64_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtnq_u64_f64(
+// CIR-LABEL: @vcvtnq_u64_f64(
+uint64x2_t test_vcvtnq_u64_f64(float64x2_t a) {
+// CIR:     cir.call_llvm_intrinsic "aarch64.neon.fcvtnu"
+
+// LLVM-SAME: <2 x double> noundef [[A:%.*]])
+// LLVM:    [[TMP0:%.*]] = bitcast <2 x double> [[A]] to <2 x i64>
+// LLVM:    [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <16 x i8>
+// LLVM:    [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
+// LLVM:    [[VCVTN1_I:%.*]] = call <2 x i64> 
@llvm.aarch64.neon.fcvtnu.v2i64.v2f64(<2 x double> [[VCVTN_I]])
+// LLVM:    ret <2 x i64> [[VCVTN1_I]]
+  return vcvtnq_u64_f64(a);
+}
+
 //===------------------------------------------------------===//
 // 2.1.3.2.3 Vector shift right and accumulate
 // 
https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#vector-shift-right-and-accumulate


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

Reply via email to