[clang] 1ba6cc0 - [clang][CIR] Add lowering for vcvtd_n_ and vcvts_n_ conversion intrinsics (#190961) (#193273)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 24 09:47:05 PDT 2026
Author: Andrzej WarzyĆski
Date: 2026-04-24T17:47:01+01:00
New Revision: 1ba6cc0e318bb022dfd322e39df49c5f0dc89068
URL: https://github.com/llvm/llvm-project/commit/1ba6cc0e318bb022dfd322e39df49c5f0dc89068
DIFF: https://github.com/llvm/llvm-project/commit/1ba6cc0e318bb022dfd322e39df49c5f0dc89068.diff
LOG: [clang][CIR] Add lowering for vcvtd_n_ and vcvts_n_ conversion intrinsics (#190961) (#193273)
This PR adds lowering for the missing conversion intrinsics with an
immediate argument (identified by `_n_` in the intrinsic name), namely
the `vcvts_n_` and `vcvtd_n_` variants.
It also moves the corresponding tests from:
* clang/test/CodeGen/AArch64/neon_intrinsics.c
to:
* clang/test/CodeGen/AArch64/neon/intrinsics.c
The lowering follows the existing implementation in
CodeGen/TargetBuiltins/ARM.cpp.
Reference:
[1] https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#conversions
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
clang/test/CodeGen/AArch64/neon-intrinsics.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 ace8a5737f4bd..294e87168b0e5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -309,6 +309,14 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
case NEON::BI__builtin_neon_vpminqd_f64:
case NEON::BI__builtin_neon_vpminnms_f32:
case NEON::BI__builtin_neon_vpminnmqd_f64:
+ case NEON::BI__builtin_neon_vcvts_n_f32_s32:
+ case NEON::BI__builtin_neon_vcvts_n_f32_u32:
+ case NEON::BI__builtin_neon_vcvts_n_s32_f32:
+ case NEON::BI__builtin_neon_vcvts_n_u32_f32:
+ case NEON::BI__builtin_neon_vcvtd_n_f64_s64:
+ case NEON::BI__builtin_neon_vcvtd_n_f64_u64:
+ case NEON::BI__builtin_neon_vcvtd_n_s64_f64:
+ case NEON::BI__builtin_neon_vcvtd_n_u64_f64:
return emitNeonCall(cgf.cgm, cgf.getBuilder(),
{cgf.convertType(expr->getArg(0)->getType())}, ops,
llvmIntrName, cgf.convertType(expr->getType()), loc);
diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index f5a2637104736..920a0236bb433 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -16314,86 +16314,6 @@ uint32_t test_vqrshrund_n_s64(int64_t a) {
return (uint32_t)vqrshrund_n_s64(a, 32);
}
-// CHECK-LABEL: define dso_local float @test_vcvts_n_f32_s32(
-// CHECK-SAME: i32 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTS_N_F32_S32:%.*]] = call float @llvm.aarch64.neon.vcvtfxs2fp.f32.i32(i32 [[A]], i32 1)
-// CHECK-NEXT: ret float [[VCVTS_N_F32_S32]]
-//
-float32_t test_vcvts_n_f32_s32(int32_t a) {
- return vcvts_n_f32_s32(a, 1);
-}
-
-// CHECK-LABEL: define dso_local double @test_vcvtd_n_f64_s64(
-// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTD_N_F64_S64:%.*]] = call double @llvm.aarch64.neon.vcvtfxs2fp.f64.i64(i64 [[A]], i32 1)
-// CHECK-NEXT: ret double [[VCVTD_N_F64_S64]]
-//
-float64_t test_vcvtd_n_f64_s64(int64_t a) {
- return vcvtd_n_f64_s64(a, 1);
-}
-
-// CHECK-LABEL: define dso_local float @test_vcvts_n_f32_u32(
-// CHECK-SAME: i32 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTS_N_F32_U32:%.*]] = call float @llvm.aarch64.neon.vcvtfxu2fp.f32.i32(i32 [[A]], i32 32)
-// CHECK-NEXT: ret float [[VCVTS_N_F32_U32]]
-//
-float32_t test_vcvts_n_f32_u32(uint32_t a) {
- return vcvts_n_f32_u32(a, 32);
-}
-
-// CHECK-LABEL: define dso_local double @test_vcvtd_n_f64_u64(
-// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTD_N_F64_U64:%.*]] = call double @llvm.aarch64.neon.vcvtfxu2fp.f64.i64(i64 [[A]], i32 64)
-// CHECK-NEXT: ret double [[VCVTD_N_F64_U64]]
-//
-float64_t test_vcvtd_n_f64_u64(uint64_t a) {
- return vcvtd_n_f64_u64(a, 64);
-}
-
-// CHECK-LABEL: define dso_local i32 @test_vcvts_n_s32_f32(
-// CHECK-SAME: float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTS_N_S32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f32(float [[A]], i32 1)
-// CHECK-NEXT: ret i32 [[VCVTS_N_S32_F32]]
-//
-int32_t test_vcvts_n_s32_f32(float32_t a) {
- return (int32_t)vcvts_n_s32_f32(a, 1);
-}
-
-// CHECK-LABEL: define dso_local i64 @test_vcvtd_n_s64_f64(
-// CHECK-SAME: double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTD_N_S64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f64(double [[A]], i32 1)
-// CHECK-NEXT: ret i64 [[VCVTD_N_S64_F64]]
-//
-int64_t test_vcvtd_n_s64_f64(float64_t a) {
- return (int64_t)vcvtd_n_s64_f64(a, 1);
-}
-
-// CHECK-LABEL: define dso_local i32 @test_vcvts_n_u32_f32(
-// CHECK-SAME: float noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTS_N_U32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f32(float [[A]], i32 32)
-// CHECK-NEXT: ret i32 [[VCVTS_N_U32_F32]]
-//
-uint32_t test_vcvts_n_u32_f32(float32_t a) {
- return (uint32_t)vcvts_n_u32_f32(a, 32);
-}
-
-// CHECK-LABEL: define dso_local i64 @test_vcvtd_n_u64_f64(
-// CHECK-SAME: double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*:]]
-// CHECK-NEXT: [[VCVTD_N_U64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f64(double [[A]], i32 64)
-// CHECK-NEXT: ret i64 [[VCVTD_N_U64_F64]]
-//
-uint64_t test_vcvtd_n_u64_f64(float64_t a) {
- return (uint64_t)vcvtd_n_u64_f64(a, 64);
-}
-
// CHECK-LABEL: define dso_local <8 x i8> @test_vreinterpret_s8_s16(
// CHECK-SAME: <4 x i16> 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 b8863168d2886..bf14d1abc9d8e 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -3623,6 +3623,94 @@ float64x1_t test_vcvt_n_f64_u64(uint64x1_t a) {
return vcvt_n_f64_u64(a, 64);
}
+// ALL-LABEL: @test_vcvts_n_f32_s32(
+float32_t test_vcvts_n_f32_s32(int32_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<1>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfxs2fp" %{{.*}}, [[CST]]
+
+// LLVM-SAME: i32 {{.*}} [[A:%.*]])
+// LLVM: [[VCVTS_N_F32_S32:%.*]] = call float @llvm.aarch64.neon.vcvtfxs2fp.f32.i32(i32 [[A]], i32 1)
+// LLVM: ret float [[VCVTS_N_F32_S32]]
+ return vcvts_n_f32_s32(a, 1);
+}
+
+// ALL-LABEL: @test_vcvts_n_f32_u32(
+float32_t test_vcvts_n_f32_u32(uint32_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<32>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfxu2fp" %{{.*}}, [[CST]]
+
+// LLVM-SAME: i32 {{.*}} [[A:%.*]])
+// LLVM: [[VCVTS_N_F32_U32:%.*]] = call float @llvm.aarch64.neon.vcvtfxu2fp.f32.i32(i32 [[A]], i32 32)
+// LLVM: ret float [[VCVTS_N_F32_U32]]
+ return vcvts_n_f32_u32(a, 32);
+}
+
+// ALL-LABEL: @test_vcvts_n_s32_f32(
+int32_t test_vcvts_n_s32_f32(float32_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<1>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfp2fxs" %{{.*}}, [[CST]]
+
+// LLVM-SAME: float {{.*}} [[A:%.*]])
+// LLVM: [[VCVTS_N_S32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f32(float [[A]], i32 1)
+// LLVM: ret i32 [[VCVTS_N_S32_F32]]
+ return (int32_t)vcvts_n_s32_f32(a, 1);
+}
+
+// ALL-LABEL: @test_vcvts_n_u32_f32(
+uint32_t test_vcvts_n_u32_f32(float32_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<32>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfp2fxu" %{{.*}}, [[CST]]
+
+// LLVM-SAME: float {{.*}} [[A:%.*]])
+// LLVM: [[VCVTS_N_U32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f32(float [[A]], i32 32)
+// LLVM: ret i32 [[VCVTS_N_U32_F32]]
+ return (uint32_t)vcvts_n_u32_f32(a, 32);
+}
+
+// ALL-LABEL: @test_vcvtd_n_f64_s64(
+float64_t test_vcvtd_n_f64_s64(int64_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<1>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfxs2fp" %{{.*}}, [[CST]]
+
+// LLVM-SAME: i64 {{.*}} [[A:%.*]])
+// LLVM: [[VCVTD_N_F64_S64:%.*]] = call double @llvm.aarch64.neon.vcvtfxs2fp.f64.i64(i64 [[A]], i32 1)
+// LLVM: ret double [[VCVTD_N_F64_S64]]
+ return vcvtd_n_f64_s64(a, 1);
+}
+
+// ALL-LABEL: @test_vcvtd_n_f64_u64(
+float64_t test_vcvtd_n_f64_u64(uint64_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<64>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfxu2fp" %{{.*}}, [[CST]]
+
+// LLVM-SAME: i64 {{.*}} [[A:%.*]])
+// LLVM: [[VCVTD_N_F64_U64:%.*]] = call double @llvm.aarch64.neon.vcvtfxu2fp.f64.i64(i64 [[A]], i32 64)
+// LLVM: ret double [[VCVTD_N_F64_U64]]
+ return vcvtd_n_f64_u64(a, 64);
+}
+
+// ALL-LABEL: @test_vcvtd_n_s64_f64(
+int64_t test_vcvtd_n_s64_f64(float64_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<1>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfp2fxs" %{{.*}}, [[CST]]
+
+// LLVM-SAME: double {{.*}}[[A:%.*]])
+// LLVM: [[VCVTD_N_S64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f64(double [[A]], i32 1)
+// LLVM: ret i64 [[VCVTD_N_S64_F64]]
+ return (int64_t)vcvtd_n_s64_f64(a, 1);
+}
+
+// ALL-LABEL: @test_vcvtd_n_u64_f64(
+uint64_t test_vcvtd_n_u64_f64(float64_t a) {
+// CIR: [[CST:%.*]] = cir.const #cir.int<64>
+// CIR: cir.call_llvm_intrinsic "aarch64.neon.vcvtfp2fxu" %{{.*}}, [[CST]]
+
+// LLVM-SAME: double {{.*}} [[A:%.*]])
+// LLVM: [[VCVTD_N_U64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f64(double [[A]], i32 64)
+// LLVM: ret i64 [[VCVTD_N_U64_F64]]
+ return (uint64_t)vcvtd_n_u64_f64(a, 64);
+}
+
//===------------------------------------------------------===//
// 2.1.3.2.4 Vector rounding shift right and accumulate
// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#vector-rounding-shift-right-and-accumulate
More information about the cfe-commits
mailing list