[llvm] [AArch64][llvm] Pre-commit tests for new fpcvt codegen (PR #173272)

Jonathan Thackray via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 22 07:31:55 PST 2025


https://github.com/jthackray created https://github.com/llvm/llvm-project/pull/173272

[AArch64][llvm] Pre-commit tests for new fpcvt codegen

[AArch64][llvm] Add codegen for simd fpcvt intrinsics

Add tablegen patterns to provide codegen for SCVTF and UCVTF
operating purely on SIMD & FP registers, using explicit bitcasts.

>From b380116c0167bd002bab99a9aa5a9726ab17c6d5 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Mon, 22 Dec 2025 14:17:52 +0000
Subject: [PATCH 1/2] [AArch64][llvm] Pre-commit tests for new fpcvt codegen

---
 .../AArch64/arm64-cvtf-simd-intrinsics.ll     | 90 +++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll

diff --git a/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll b/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll
new file mode 100644
index 0000000000000..f4dc91cb962ed
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll
@@ -0,0 +1,90 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=aarch64-unknown-unknown -mattr=+neon,+fullfp16,+fprcvt | FileCheck %s --check-prefixes=CHECK
+
+define double @scvtf_bitcast_f32_to_f64(float %f) nounwind {
+; CHECK-LABEL: scvtf_bitcast_f32_to_f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov w8, s0
+; CHECK-NEXT:    scvtf d0, w8
+; CHECK-NEXT:    ret
+  %i = bitcast float %f to i32
+  %r = sitofp i32 %i to double
+  ret double %r
+}
+
+define double @ucvtf_bitcast_f32_to_f64(float %f) nounwind {
+; CHECK-LABEL: ucvtf_bitcast_f32_to_f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov w8, s0
+; CHECK-NEXT:    ucvtf d0, w8
+; CHECK-NEXT:    ret
+  %i = bitcast float %f to i32
+  %r = uitofp i32 %i to double
+  ret double %r
+}
+
+define half @scvtf_bitcast_f32_to_f16(float %f) nounwind {
+; CHECK-LABEL: scvtf_bitcast_f32_to_f16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov w8, s0
+; CHECK-NEXT:    scvtf h0, w8
+; CHECK-NEXT:    ret
+  %i = bitcast float %f to i32
+  %r = sitofp i32 %i to half
+  ret half %r
+}
+
+define half @ucvtf_bitcast_f32_to_f16(float %f) nounwind {
+; CHECK-LABEL: ucvtf_bitcast_f32_to_f16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov w8, s0
+; CHECK-NEXT:    ucvtf h0, w8
+; CHECK-NEXT:    ret
+  %i = bitcast float %f to i32
+  %r = uitofp i32 %i to half
+  ret half %r
+}
+
+define float @scvtf_bitcast_f64_to_f32(double %d) nounwind {
+; CHECK-LABEL: scvtf_bitcast_f64_to_f32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov x8, d0
+; CHECK-NEXT:    scvtf s0, x8
+; CHECK-NEXT:    ret
+  %i = bitcast double %d to i64
+  %r = sitofp i64 %i to float
+  ret float %r
+}
+
+define float @ucvtf_bitcast_f64_to_f32(double %d) nounwind {
+; CHECK-LABEL: ucvtf_bitcast_f64_to_f32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov x8, d0
+; CHECK-NEXT:    ucvtf s0, x8
+; CHECK-NEXT:    ret
+  %i = bitcast double %d to i64
+  %r = uitofp i64 %i to float
+  ret float %r
+}
+
+define half @scvtf_bitcast_f64_to_f16(double %d) nounwind {
+; CHECK-LABEL: scvtf_bitcast_f64_to_f16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov x8, d0
+; CHECK-NEXT:    scvtf h0, x8
+; CHECK-NEXT:    ret
+  %i = bitcast double %d to i64
+  %r = sitofp i64 %i to half
+  ret half %r
+}
+
+define half @ucvtf_bitcast_f64_to_f16(double %d) nounwind {
+; CHECK-LABEL: ucvtf_bitcast_f64_to_f16:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    fmov x8, d0
+; CHECK-NEXT:    ucvtf h0, x8
+; CHECK-NEXT:    ret
+  %i = bitcast double %d to i64
+  %r = uitofp i64 %i to half
+  ret half %r
+}

>From 80bc071af380f13e4a9140de1918a1befeb95a74 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 18 Dec 2025 14:28:38 +0000
Subject: [PATCH 2/2] [AArch64][llvm] Add codegen for simd fpcvt intrinsics

Add tablegen patterns to provide codegen for SCVTF and UCVTF
operating purely on SIMD & FP registers, using explicit bitcasts.
---
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   | 30 +++++++++++++++++++
 .../AArch64/arm64-cvtf-simd-intrinsics.ll     | 27 +++++++----------
 2 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index f3cd613a6bd99..8b0ec69adb737 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -6557,6 +6557,36 @@ defm UQXTN  : SIMDTwoScalarMixedBHS<1, 0b10100, "uqxtn", int_aarch64_neon_scalar
 defm USQADD : SIMDTwoScalarBHSDTied< 1, 0b00011, "usqadd",
                                     int_aarch64_neon_usqadd>;
 
+// Floating-point conversion patterns.
+multiclass IntegerToFPSIMDScalarPatterns<SDPatternOperator OpN, string INST> {
+  let Predicates = [HasFPRCVT] in {
+  def : Pat<(f64 (OpN (i32 (bitconvert (f32 FPR32:$Rn))))),
+            (!cast<Instruction>(INST # DSr) FPR32:$Rn)>;
+  def : Pat<(f16 (OpN (i32 (bitconvert (f32 FPR32:$Rn))))),
+            (!cast<Instruction>(INST # HSr) FPR32:$Rn)>;
+  def : Pat<(f16 (OpN (i64 (bitconvert (f64 FPR64:$Rn))))),
+            (!cast<Instruction>(INST # HDr) FPR64:$Rn)>;
+  def : Pat<(f32 (OpN (i64 (bitconvert (f64 FPR64:$Rn))))),
+            (!cast<Instruction>(INST # SDr) FPR64:$Rn)>;
+  }
+  def : Pat<(f32 (OpN (i32 (bitconvert (f32 FPR32:$Rn))))),
+            (!cast<Instruction>(INST # v1i32) FPR32:$Rn)>;
+  def : Pat<(f64 (OpN (i64 (bitconvert (f64 FPR64:$Rn))))),
+            (!cast<Instruction>(INST # v1i64) FPR64:$Rn)>;
+
+  def : Pat<(f16 (OpN (i16 (vector_extract (v8i16 FPR128:$Rn), (i64 0))))),
+            (!cast<Instruction>(INST # v1i16)
+              (EXTRACT_SUBREG (v8i16 FPR128:$Rn), hsub))>;
+  def : Pat<(f32 (OpN (i32 (vector_extract (v4i32 FPR128:$Rn), (i64 0))))),
+            (!cast<Instruction>(INST # v1i32)
+              (EXTRACT_SUBREG (v4i32 FPR128:$Rn), ssub))>;
+  def : Pat<(f64 (OpN (i64 (vector_extract (v2i64 FPR128:$Rn), (i64 0))))),
+            (!cast<Instruction>(INST # v1i64)
+              (EXTRACT_SUBREG (v2i64 FPR128:$Rn), dsub))>;
+}
+defm : IntegerToFPSIMDScalarPatterns<sint_to_fp, "SCVTF">;
+defm : IntegerToFPSIMDScalarPatterns<uint_to_fp, "UCVTF">;
+
 // Floating-point conversion patterns.
 multiclass FPToIntegerSIMDScalarPatterns<SDPatternOperator OpN, string INST> {
   let Predicates = [HasFPRCVT] in {
diff --git a/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll b/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll
index f4dc91cb962ed..29102d9ca9587 100644
--- a/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-cvtf-simd-intrinsics.ll
@@ -1,11 +1,11 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
 ; RUN: llc < %s -mtriple=aarch64-unknown-unknown -mattr=+neon,+fullfp16,+fprcvt | FileCheck %s --check-prefixes=CHECK
 
 define double @scvtf_bitcast_f32_to_f64(float %f) nounwind {
 ; CHECK-LABEL: scvtf_bitcast_f32_to_f64:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov w8, s0
-; CHECK-NEXT:    scvtf d0, w8
+; CHECK-NEXT:    scvtf d0, s0
 ; CHECK-NEXT:    ret
   %i = bitcast float %f to i32
   %r = sitofp i32 %i to double
@@ -15,8 +15,7 @@ define double @scvtf_bitcast_f32_to_f64(float %f) nounwind {
 define double @ucvtf_bitcast_f32_to_f64(float %f) nounwind {
 ; CHECK-LABEL: ucvtf_bitcast_f32_to_f64:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov w8, s0
-; CHECK-NEXT:    ucvtf d0, w8
+; CHECK-NEXT:    ucvtf d0, s0
 ; CHECK-NEXT:    ret
   %i = bitcast float %f to i32
   %r = uitofp i32 %i to double
@@ -26,8 +25,7 @@ define double @ucvtf_bitcast_f32_to_f64(float %f) nounwind {
 define half @scvtf_bitcast_f32_to_f16(float %f) nounwind {
 ; CHECK-LABEL: scvtf_bitcast_f32_to_f16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov w8, s0
-; CHECK-NEXT:    scvtf h0, w8
+; CHECK-NEXT:    scvtf h0, s0
 ; CHECK-NEXT:    ret
   %i = bitcast float %f to i32
   %r = sitofp i32 %i to half
@@ -37,8 +35,7 @@ define half @scvtf_bitcast_f32_to_f16(float %f) nounwind {
 define half @ucvtf_bitcast_f32_to_f16(float %f) nounwind {
 ; CHECK-LABEL: ucvtf_bitcast_f32_to_f16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov w8, s0
-; CHECK-NEXT:    ucvtf h0, w8
+; CHECK-NEXT:    ucvtf h0, s0
 ; CHECK-NEXT:    ret
   %i = bitcast float %f to i32
   %r = uitofp i32 %i to half
@@ -48,8 +45,7 @@ define half @ucvtf_bitcast_f32_to_f16(float %f) nounwind {
 define float @scvtf_bitcast_f64_to_f32(double %d) nounwind {
 ; CHECK-LABEL: scvtf_bitcast_f64_to_f32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov x8, d0
-; CHECK-NEXT:    scvtf s0, x8
+; CHECK-NEXT:    scvtf s0, d0
 ; CHECK-NEXT:    ret
   %i = bitcast double %d to i64
   %r = sitofp i64 %i to float
@@ -59,8 +55,7 @@ define float @scvtf_bitcast_f64_to_f32(double %d) nounwind {
 define float @ucvtf_bitcast_f64_to_f32(double %d) nounwind {
 ; CHECK-LABEL: ucvtf_bitcast_f64_to_f32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov x8, d0
-; CHECK-NEXT:    ucvtf s0, x8
+; CHECK-NEXT:    ucvtf s0, d0
 ; CHECK-NEXT:    ret
   %i = bitcast double %d to i64
   %r = uitofp i64 %i to float
@@ -70,8 +65,7 @@ define float @ucvtf_bitcast_f64_to_f32(double %d) nounwind {
 define half @scvtf_bitcast_f64_to_f16(double %d) nounwind {
 ; CHECK-LABEL: scvtf_bitcast_f64_to_f16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov x8, d0
-; CHECK-NEXT:    scvtf h0, x8
+; CHECK-NEXT:    scvtf h0, d0
 ; CHECK-NEXT:    ret
   %i = bitcast double %d to i64
   %r = sitofp i64 %i to half
@@ -81,8 +75,7 @@ define half @scvtf_bitcast_f64_to_f16(double %d) nounwind {
 define half @ucvtf_bitcast_f64_to_f16(double %d) nounwind {
 ; CHECK-LABEL: ucvtf_bitcast_f64_to_f16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    fmov x8, d0
-; CHECK-NEXT:    ucvtf h0, x8
+; CHECK-NEXT:    ucvtf h0, d0
 ; CHECK-NEXT:    ret
   %i = bitcast double %d to i64
   %r = uitofp i64 %i to half



More information about the llvm-commits mailing list