Skip to content

[clang][CIR][AArch64] Add lowering for conversion intrinsics#209252

Open
banach-space wants to merge 1 commit into
llvm:mainfrom
banach-space:andrzej/cir/conversio
Open

[clang][CIR][AArch64] Add lowering for conversion intrinsics#209252
banach-space wants to merge 1 commit into
llvm:mainfrom
banach-space:andrzej/cir/conversio

Conversation

@banach-space

Copy link
Copy Markdown
Contributor

This PR adds lowering for intrinsic from the following groups:

It continues the work started in #190961, #193273 and #199990. This PR
implements the remaining conversions truncating to zero:

  • vcvtd_s32_f64
  • vcvtd_s64_f64
  • vcvtd_u32_f64
  • vcvtd_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.

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 llvm#190961, llvm#193273 and llvm#199990. This PR
implements the remaining conversions truncating to zero:
  * vcvtd_s32_f64
  * vcvtd_s64_f64
  * vcvtd_u32_f64
  * vcvtd_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.
@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Jul 13, 2026
@llvmorg-github-actions

llvmorg-github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clangir

Author: Andrzej Warzyński (banach-space)

Changes

This PR adds lowering for intrinsic from the following groups:

It continues the work started in #190961, #193273 and #199990. This PR
implements the remaining conversions truncating to zero:

  • vcvtd_s32_f64
  • vcvtd_s64_f64
  • vcvtd_u32_f64
  • vcvtd_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.


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

3 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp (+15-2)
  • (modified) clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c (-40)
  • (modified) clang/test/CodeGen/AArch64/neon/intrinsics.c (+45-1)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 2608aaf780591..a5e119817b3fa 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -354,8 +354,17 @@ static mlir::Value emitCommonNeonSISDBuiltinExpr(
     break;
   }
 
-  llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix(
-      static_cast<llvm::Intrinsic::ID>(info.LLVMIntrinsic));
+  unsigned intr = info.LLVMIntrinsic;
+
+  // Use fptosi.sat/fptoui.sat unless under strict FP.
+  assert(!cir::MissingFeatures::emitConstrainedFPCall());
+  if (intr == Intrinsic::aarch64_neon_fcvtzs)
+    intr = Intrinsic::fptosi_sat;
+  else if (intr == Intrinsic::aarch64_neon_fcvtzu)
+    intr = Intrinsic::fptoui_sat;
+
+  llvm::StringRef llvmIntrName =
+      getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(intr));
   mlir::Location loc = cgf.getLoc(expr->getExprLoc());
 
   // The switch stmt is intended to help catch NYI cases and will be removed
@@ -393,6 +402,10 @@ 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_vcvtd_s32_f64:
+  case NEON::BI__builtin_neon_vcvtd_s64_f64:
+  case NEON::BI__builtin_neon_vcvtd_u64_f64:
+  case NEON::BI__builtin_neon_vcvtd_u32_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:
diff --git a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
index f14df46b89177..5a59f80cb0363 100644
--- a/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c
@@ -346,16 +346,6 @@ int32_t test_vcvts_s32_f32(float32_t a) {
   return (int32_t)vcvts_s32_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_s64_f64
-// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTD_S64_F64_I:%.*]] = call i64 @llvm.fptosi.sat.i64.f64(double [[A]])
-// CHECK-NEXT:    ret i64 [[VCVTD_S64_F64_I]]
-//
-int64_t test_vcvtd_s64_f64(float64_t a) {
-  return (int64_t)vcvtd_s64_f64(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvts_s64_f32
 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -366,16 +356,6 @@ int64_t test_vcvts_s64_f32(float32_t a) {
   return (int64_t)vcvts_s64_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_s32_f64
-// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTD_S32_F64_I:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double [[A]])
-// CHECK-NEXT:    ret i32 [[VCVTD_S32_F64_I]]
-//
-int32_t test_vcvtd_s32_f64(float64_t a) {
-  return (int32_t)vcvtd_s32_f64(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvts_u32_f32
 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -386,16 +366,6 @@ uint32_t test_vcvts_u32_f32(float32_t a) {
   return (uint32_t)vcvts_u32_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_u64_f64
-// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTD_U64_F64_I:%.*]] = call i64 @llvm.fptoui.sat.i64.f64(double [[A]])
-// CHECK-NEXT:    ret i64 [[VCVTD_U64_F64_I]]
-//
-uint64_t test_vcvtd_u64_f64(float64_t a) {
-  return (uint64_t)vcvtd_u64_f64(a);
-}
-
 // CHECK-LABEL: define {{[^@]+}}@test_vcvts_u64_f32
 // CHECK-SAME: (float noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  entry:
@@ -406,13 +376,3 @@ uint64_t test_vcvts_u64_f32(float32_t a) {
   return (uint64_t)vcvts_u64_f32(a);
 }
 
-// CHECK-LABEL: define {{[^@]+}}@test_vcvtd_u32_f64
-// CHECK-SAME: (double noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[VCVTD_U32_F64_I:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double [[A]])
-// CHECK-NEXT:    ret i32 [[VCVTD_U32_F64_I]]
-//
-uint32_t test_vcvtd_u32_f64(float64_t a) {
-  return (uint32_t)vcvtd_u32_f64(a);
-}
-
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index eea4ace984870..0e15488aede6b 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -4590,6 +4590,50 @@ uint64x2_t test_vcvtq_u64_f64(float64x2_t a) {
   return vcvtq_u64_f64(a);
 }
 
+// LLVM-LABEL: @test_vcvtd_s32_f64
+// CIR-LABEL: @vcvtd_s32_f64
+int32_t test_vcvtd_s32_f64(float64_t a) {
+// CIR:     cir.call_llvm_intrinsic "fptosi.sat
+
+// LLVM-SAME: double {{.*}} [[A:%.*]])
+// LLVM:    [[VCVTD_S32_F64_I:%.*]] = call i32 @llvm.fptosi.sat.i32.f64(double [[A]])
+// LLVM-NEXT:    ret i32 [[VCVTD_S32_F64_I]]
+  return (int32_t)vcvtd_s32_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtd_s64_f64
+// CIR-LABEL: @vcvtd_s64_f64
+int64_t test_vcvtd_s64_f64(float64_t a) {
+// CIR:     cir.call_llvm_intrinsic "fptosi.sat
+
+// LLVM-SAME: double {{.*}} [[A:%.*]])
+// LLVM:    [[VCVTD_S64_F64_I:%.*]] = call i64 @llvm.fptosi.sat.i64.f64(double [[A]])
+// LLVM-NEXT:    ret i64 [[VCVTD_S64_F64_I]]
+  return (int64_t)vcvtd_s64_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtd_u32_f64
+// CIR-LABEL: @vcvtd_u32_f64
+uint32_t test_vcvtd_u32_f64(float64_t a) {
+// CIR:     cir.call_llvm_intrinsic "fptoui.sat
+
+// LLVM-SAME: double {{.*}} [[A:%.*]])
+// LLVM:    [[VCVTD_U32_F64_I:%.*]] = call i32 @llvm.fptoui.sat.i32.f64(double [[A]])
+// LLVM-NEXT:    ret i32 [[VCVTD_U32_F64_I]]
+  return (uint32_t)vcvtd_u32_f64(a);
+}
+
+// LLVM-LABEL: @test_vcvtd_u64_f64
+// CIR-LABEL: @vcvtd_u64_f64
+uint64_t test_vcvtd_u64_f64(float64_t a) {
+// CIR:     cir.call_llvm_intrinsic "fptoui.sat
+
+// LLVM-SAME: double {{.*}} [[A:%.*]])
+// LLVM:    [[VCVTD_U64_F64_I:%.*]] = call i64 @llvm.fptoui.sat.i64.f64(double [[A]])
+// LLVM-NEXT:    ret i64 [[VCVTD_U64_F64_I]]
+  return (uint64_t)vcvtd_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
@@ -7540,4 +7584,4 @@ float64x2_t test_vrndxq_f64(float64x2_t a) {
 // LLVM: [[VRNDX1_I:%.*]] = call <2 x double> @llvm.rint.v2f64(<2 x double> [[VRNDX_I]])
 // LLVM: ret <2 x double> [[VRNDX1_I]]
   return vrndxq_f64(a);
-}
\ No newline at end of file
+}

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants