[llvm] [AArch64][SelectionDAG] Fold fp_to_int(fmul) for FPR results (PR #210987)
Kieran B via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 28 07:08:46 PDT 2026
https://github.com/kieroxide updated https://github.com/llvm/llvm-project/pull/210987
>From 1df87cf8f3d1cb29f9c1d705e92a5064e09912d0 Mon Sep 17 00:00:00 2001
From: Kieran Bailey <kieran.bailey at arm.com>
Date: Tue, 21 Jul 2026 12:58:58 +0000
Subject: [PATCH 1/3] [AArch64][SelectionDAG] Fold fp_to_int(fmul) for FPR
results
- Add FmulToFPToIntFPRPats FCVTZ fmul folds (F32 and F64) for any_fp_to_int, fp_to_int_sat, neon_fcvtz.
- Add FPR-result test coverage for fp_to_int and fp_to_int_sat to existing fcvt-fixed.ll
- Create new test file neon-fcvt-fixed.ll for neon.fcvtz testing
A follow up patch will include the fix for GlobalIsel
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 31 ++-
llvm/test/CodeGen/AArch64/fcvt-fixed.ll | 244 +++++++++++++++----
llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll | 148 +++++++++++
3 files changed, 374 insertions(+), 49 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 51fb2e1d1f9f0..43cd4e6466524 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -9251,7 +9251,9 @@ class fixedpoint_vec_f32<ValueType FloatVT>
: ComplexPattern<FloatVT, 1, "SelectCVTFixedPointVec<32>">;
class fixedpoint_vec_f16<ValueType FloatVT>
: ComplexPattern<FloatVT, 1, "SelectCVTFixedPointVec<16>">;
-// This thing just allows us to change the type of the node produced. The imm
+
+// Shared by scalar and vector fixed-point FCVT patterns.
+// Allows transformation of fixedpoint -> vecshift. The imm
// value we want is already in V from SelectCVTFixedPointVec.
def fixedpoint_vec_xform : SDNodeXForm<timm, [{
(void)N;
@@ -9293,6 +9295,33 @@ def : Pat<(v8f16 (sint_to_fp (v8i16 (AArch64vashr_exact v8i16:$Vn, i32:$shift)))
(SCVTFv8i16_shift $Vn, vecshiftR16:$shift)>;
}
+// Fmul fold + FP_to_int conversions bitcast kept in SIMD/FP register
+multiclass FmulToFPToIntFPRPats<SDPatternOperator OpN, string INST> {
+ def : Pat<(f32 (bitconvert (i32 (OpN (fmul FPR32:$Rn, fixedpoint_f32_i32:$scale))))),
+ (!cast<Instruction>(INST # "s") FPR32:$Rn, (fixedpoint_vec_xform fixedpoint_f32_i32:$scale))>;
+ def : Pat<(f64 (bitconvert (i64 (OpN (fmul FPR64:$Rn, fixedpoint_f64_i64:$scale))))),
+ (!cast<Instruction>(INST # "d") FPR64:$Rn, (fixedpoint_vec_xform fixedpoint_f64_i64:$scale))>;
+}
+
+let Predicates = [HasNEON] in {
+ defm : FmulToFPToIntFPRPats<any_fp_to_sint, "FCVTZS">;
+ defm : FmulToFPToIntFPRPats<any_fp_to_uint, "FCVTZU">;
+ defm : FmulToFPToIntFPRPats<int_aarch64_neon_fcvtzs, "FCVTZS">;
+ defm : FmulToFPToIntFPRPats<int_aarch64_neon_fcvtzu, "FCVTZU">;
+}
+
+multiclass FmulToFPToIntSatFPRPats<SDPatternOperator OpN, string INST> {
+ def : Pat<(f32 (bitconvert (i32 (OpN (fmul FPR32:$Rn, fixedpoint_f32_i32:$scale), i32)))),
+ (!cast<Instruction>(INST # "s") FPR32:$Rn, (fixedpoint_vec_xform fixedpoint_f32_i32:$scale))>;
+ def : Pat<(f64 (bitconvert (i64 (OpN (fmul FPR64:$Rn, fixedpoint_f64_i64:$scale), i64)))),
+ (!cast<Instruction>(INST # "d") FPR64:$Rn, (fixedpoint_vec_xform fixedpoint_f64_i64:$scale))>;
+}
+
+let Predicates = [HasNEON] in {
+ defm : FmulToFPToIntSatFPRPats<fp_to_sint_sat, "FCVTZS">;
+ defm : FmulToFPToIntSatFPRPats<fp_to_uint_sat, "FCVTZU">;
+}
+
multiclass FCVTPat<ValueType FVT, ValueType IVT, ValueType ScalarVT, RegisterOperand RC, ComplexPattern fixedpoint> {
// fptosi(fadd(x, x)) -> FCVTZS_shift x, 1
def : Pat<(IVT (fp_to_sint (FVT (fadd RC:$Vn, RC:$Vn)))),
diff --git a/llvm/test/CodeGen/AArch64/fcvt-fixed.ll b/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
index 743d1604388de..4ff1e1cbcda6a 100644
--- a/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
+++ b/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
@@ -41,6 +41,24 @@ define i32 @fcvtzs_f32_i32_32(float %flt) {
ret i32 %cvt
}
+define float @fcvtzs_f32_i32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_f32_i32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_f32_i32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 128.0
+ %cvt = fptosi float %fix to i32
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzs_f32_i64_7(float %flt) {
; CHECK-SD-LABEL: fcvtzs_f32_i64_7:
; CHECK-SD: // %bb.0:
@@ -148,6 +166,25 @@ define i64 @fcvtzs_f64_i64_64(double %dbl) {
ret i64 %cvt
}
+define double @fcvtzs_f64_i64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_f64_i64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs d0, d0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_f64_i64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 128.0
+ %cvt = fptosi double %fix to i64
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
define i32 @fcvtzs_f16_i32_7(half %flt) {
; CHECK-NO16-LABEL: fcvtzs_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -166,8 +203,8 @@ define i32 @fcvtzs_f16_i32_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI8_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI8_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI10_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI10_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -194,8 +231,8 @@ define i32 @fcvtzs_f16_i32_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI9_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI9_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI11_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI11_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -222,8 +259,8 @@ define i64 @fcvtzs_f16_i64_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI10_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI10_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI12_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI12_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -250,8 +287,8 @@ define i64 @fcvtzs_f16_i64_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI11_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI11_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI13_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI13_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -279,6 +316,24 @@ define i32 @fcvtzu_f32_i32_7(float %flt) {
ret i32 %cvt
}
+define float @fcvtzu_f32_i32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_f32_i32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_f32_i32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 128.0
+ %cvt = fptoui float %fix to i32
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i32 @fcvtzu_f32_i32_32(float %flt) {
; CHECK-SD-LABEL: fcvtzu_f32_i32_32:
; CHECK-SD: // %bb.0:
@@ -404,6 +459,25 @@ define i64 @fcvtzu_f64_i64_64(double %dbl) {
ret i64 %cvt
}
+define double @fcvtzu_f64_i64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzu_f64_i64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu d0, d0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_f64_i64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzu d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 128.0
+ %cvt = fptoui double %fix to i64
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
define i32 @fcvtzu_f16_i32_7(half %flt) {
; CHECK-NO16-LABEL: fcvtzu_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -422,8 +496,8 @@ define i32 @fcvtzu_f16_i32_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI20_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI20_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI24_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI24_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -450,8 +524,8 @@ define i32 @fcvtzu_f16_i32_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI21_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI21_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI25_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI25_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -478,8 +552,8 @@ define i64 @fcvtzu_f16_i64_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI22_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI22_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI26_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI26_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -506,8 +580,8 @@ define i64 @fcvtzu_f16_i64_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI23_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI23_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI27_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI27_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -689,8 +763,8 @@ define half @scvtf_f16_i32_7(i32 %int) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI32_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI32_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI36_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI36_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i32 %int to half
@@ -727,8 +801,8 @@ define half @scvtf_f16_i32_15(i32 %int) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI33_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI33_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI37_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI37_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i32 %int to half
@@ -765,8 +839,8 @@ define half @scvtf_f16_i64_7(i64 %long) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI34_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI34_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI38_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI38_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i64 %long to half
@@ -803,8 +877,8 @@ define half @scvtf_f16_i64_15(i64 %long) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI35_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI35_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI39_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI39_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i64 %long to half
@@ -985,8 +1059,8 @@ define half @ucvtf_f16_i32_7(i32 %int) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI44_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI44_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI48_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI48_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i32 %int to half
@@ -1023,8 +1097,8 @@ define half @ucvtf_f16_i32_15(i32 %int) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI45_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI45_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI49_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI49_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i32 %int to half
@@ -1061,8 +1135,8 @@ define half @ucvtf_f16_i64_7(i64 %long) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI46_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI46_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI50_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI50_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i64 %long to half
@@ -1099,8 +1173,8 @@ define half @ucvtf_f16_i64_15(i64 %long) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI47_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI47_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI51_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI51_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i64 %long to half
@@ -1153,6 +1227,24 @@ define i32 @fcvtzs_sat_f32_i32_32(float %flt) {
ret i32 %cvt
}
+define float @fcvtzs_sat_f32_i32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_sat_f32_i32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_sat_f32_i32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 128.0
+ %cvt = call i32 @llvm.fptosi.sat.i32.f32(float %fix)
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzs_sat_f32_i64_64(float %flt) {
; CHECK-SD-LABEL: fcvtzs_sat_f32_i64_64:
; CHECK-SD: // %bb.0:
@@ -1243,6 +1335,25 @@ define i64 @fcvtzs_sat_f64_i64_64(double %dbl) {
ret i64 %cvt
}
+define double @fcvtzs_sat_f64_i64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_sat_f64_i64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs d0, d0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_sat_f64_i64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 128.0
+ %cvt = call i64 @llvm.fptosi.sat.i64.f64(double %fix)
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
define i32 @fcvtzs_sat_f16_i32_7(half %dbl) {
; CHECK-NO16-LABEL: fcvtzs_sat_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -1261,8 +1372,8 @@ define i32 @fcvtzs_sat_f16_i32_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI55_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI55_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI61_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI61_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1289,8 +1400,8 @@ define i32 @fcvtzs_sat_f16_i32_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI56_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI56_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI62_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI62_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1317,8 +1428,8 @@ define i64 @fcvtzs_sat_f16_i64_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI57_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI57_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI63_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI63_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1345,8 +1456,8 @@ define i64 @fcvtzs_sat_f16_i64_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI58_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI58_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI64_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI64_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1399,6 +1510,24 @@ define i32 @fcvtzu_sat_f32_i32_32(float %flt) {
ret i32 %cvt
}
+define float @fcvtzu_sat_f32_i32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_sat_f32_i32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_sat_f32_i32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 128.0
+ %cvt = call i32 @llvm.fptoui.sat.i32.f32(float %fix)
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzu_sat_f32_i64_64(float %flt) {
; CHECK-SD-LABEL: fcvtzu_sat_f32_i64_64:
; CHECK-SD: // %bb.0:
@@ -1489,6 +1618,25 @@ define i64 @fcvtzu_sat_f64_i64_64(double %dbl) {
ret i64 %cvt
}
+define double @fcvtzu_sat_f64_i64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzu_sat_f64_i64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu d0, d0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_sat_f64_i64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzu d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 128.0
+ %cvt = call i64 @llvm.fptoui.sat.i64.f64(double %fix)
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
define i32 @fcvtzu_sat_f16_i32_7(half %dbl) {
; CHECK-NO16-LABEL: fcvtzu_sat_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -1507,8 +1655,8 @@ define i32 @fcvtzu_sat_f16_i32_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI66_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI66_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI74_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI74_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1535,8 +1683,8 @@ define i32 @fcvtzu_sat_f16_i32_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI67_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI67_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI75_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI75_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1563,8 +1711,8 @@ define i64 @fcvtzu_sat_f16_i64_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI68_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI68_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI76_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI76_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1591,8 +1739,8 @@ define i64 @fcvtzu_sat_f16_i64_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI69_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI69_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI77_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI77_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll b/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
new file mode 100644
index 0000000000000..ca162ac506502
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
@@ -0,0 +1,148 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-NO16,CHECK-SD-NO16
+; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-NO16,CHECK-GI-NO16
+
+define i32 @neon_fcvtzs_f32_i32(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs w0, s0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov s1, #8.00000000
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 8.000000e+00
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define float @neon_fcvtzs_f32_i32_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov s1, #8.00000000
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 8.000000e+00
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
+define i64 @neon_fcvtzs_f64_i64(double %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f64_i64:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs x0, d0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f64_i64:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov d1, #8.00000000
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs x0, d0
+; CHECK-GI-NEXT: ret
+ %mul = fmul double %a, 8.000000e+00
+ %r = call i64 @llvm.aarch64.neon.fcvtzs.i64.f64(double %mul)
+ ret i64 %r
+}
+
+define double @neon_fcvtzs_f64_i64_bitcast(double %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f64_i64_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs d0, d0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f64_i64_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov d1, #8.00000000
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs d0, d0
+; CHECK-GI-NEXT: ret
+ %mul = fmul double %a, 8.000000e+00
+ %r = call i64 @llvm.aarch64.neon.fcvtzs.i64.f64(double %mul)
+ %bc = bitcast i64 %r to double
+ ret double %bc
+}
+
+define i32 @neon_fcvtzu_f32_i32(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu w0, s0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov s1, #8.00000000
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 8.000000e+00
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define float @neon_fcvtzu_f32_i32_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov s1, #8.00000000
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 8.000000e+00
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
+define i64 @neon_fcvtzu_f64_i64(double %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f64_i64:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu x0, d0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f64_i64:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov d1, #8.00000000
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzu x0, d0
+; CHECK-GI-NEXT: ret
+ %mul = fmul double %a, 8.000000e+00
+ %r = call i64 @llvm.aarch64.neon.fcvtzu.i64.f64(double %mul)
+ ret i64 %r
+}
+
+define double @neon_fcvtzu_f64_i64_bitcast(double %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f64_i64_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu d0, d0, #3
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f64_i64_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: fmov d1, #8.00000000
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzu d0, d0
+; CHECK-GI-NEXT: ret
+ %mul = fmul double %a, 8.000000e+00
+ %r = call i64 @llvm.aarch64.neon.fcvtzu.i64.f64(double %mul)
+ %bc = bitcast i64 %r to double
+ ret double %bc
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
+; CHECK-GI-NO16: {{.*}}
+; CHECK-NO16: {{.*}}
+; CHECK-SD-NO16: {{.*}}
>From ed45e7cacfb6e6a3b64f3cabfd44b8a76f251e56 Mon Sep 17 00:00:00 2001
From: Kieran Bailey <kieran.bailey at arm.com>
Date: Mon, 27 Jul 2026 15:43:12 +0000
Subject: [PATCH 2/3] Review Commit
- Add maximum scale test for fpr resulting conversions
- Moved neon-fcvt to fcvt-fixed.ll instead of separate file
- Reverted comment back to original
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 5 +-
llvm/test/CodeGen/AArch64/fcvt-fixed.ll | 430 +++++++++++++++----
llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll | 148 -------
3 files changed, 357 insertions(+), 226 deletions(-)
delete mode 100644 llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 43cd4e6466524..63cf927a6d7c9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -9252,9 +9252,8 @@ class fixedpoint_vec_f32<ValueType FloatVT>
class fixedpoint_vec_f16<ValueType FloatVT>
: ComplexPattern<FloatVT, 1, "SelectCVTFixedPointVec<16>">;
-// Shared by scalar and vector fixed-point FCVT patterns.
-// Allows transformation of fixedpoint -> vecshift. The imm
-// value we want is already in V from SelectCVTFixedPointVec.
+// This thing just allows us to change the type of the node produced.
+// The imm value we want is already in V from SelectCVTFixedPointVec.
def fixedpoint_vec_xform : SDNodeXForm<timm, [{
(void)N;
return V;
diff --git a/llvm/test/CodeGen/AArch64/fcvt-fixed.ll b/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
index 4ff1e1cbcda6a..7419d88ef6c8d 100644
--- a/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
+++ b/llvm/test/CodeGen/AArch64/fcvt-fixed.ll
@@ -41,13 +41,13 @@ define i32 @fcvtzs_f32_i32_32(float %flt) {
ret i32 %cvt
}
-define float @fcvtzs_f32_i32_fpr(float %flt) {
-; CHECK-SD-LABEL: fcvtzs_f32_i32_fpr:
+define float @fcvtzs_f32_i32_7_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_f32_i32_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs s0, s0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzs_f32_i32_fpr:
+; CHECK-GI-LABEL: fcvtzs_f32_i32_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
; CHECK-GI-NEXT: fmul s0, s0, s1
@@ -59,6 +59,25 @@ define float @fcvtzs_f32_i32_fpr(float %flt) {
ret float %bc
}
+define float @fcvtzs_f32_i32_32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_f32_i32_32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_f32_i32_32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 4294967296.0
+ %cvt = fptosi float %fix to i32
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzs_f32_i64_7(float %flt) {
; CHECK-SD-LABEL: fcvtzs_f32_i64_7:
; CHECK-SD: // %bb.0:
@@ -166,13 +185,13 @@ define i64 @fcvtzs_f64_i64_64(double %dbl) {
ret i64 %cvt
}
-define double @fcvtzs_f64_i64_fpr(double %dbl) {
-; CHECK-SD-LABEL: fcvtzs_f64_i64_fpr:
+define double @fcvtzs_f64_i64_7_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_f64_i64_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs d0, d0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzs_f64_i64_fpr:
+; CHECK-GI-LABEL: fcvtzs_f64_i64_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
; CHECK-GI-NEXT: fmov d1, x8
@@ -185,6 +204,25 @@ define double @fcvtzs_f64_i64_fpr(double %dbl) {
ret double %bc
}
+define double @fcvtzs_f64_i64_64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_f64_i64_64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs d0, d0, #64
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_f64_i64_64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4895412794951729152 // =0x43f0000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 18446744073709551616.0
+ %cvt = fptosi double %fix to i64
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
define i32 @fcvtzs_f16_i32_7(half %flt) {
; CHECK-NO16-LABEL: fcvtzs_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -203,8 +241,8 @@ define i32 @fcvtzs_f16_i32_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI10_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI10_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI12_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI12_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -231,8 +269,8 @@ define i32 @fcvtzs_f16_i32_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI11_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI11_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI13_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI13_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -259,8 +297,8 @@ define i64 @fcvtzs_f16_i64_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI12_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI12_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI14_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI14_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -287,8 +325,8 @@ define i64 @fcvtzs_f16_i64_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI13_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI13_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI15_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI15_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -316,13 +354,31 @@ define i32 @fcvtzu_f32_i32_7(float %flt) {
ret i32 %cvt
}
-define float @fcvtzu_f32_i32_fpr(float %flt) {
-; CHECK-SD-LABEL: fcvtzu_f32_i32_fpr:
+define i32 @fcvtzu_f32_i32_32(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_f32_i32_32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu w0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_f32_i32_32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu w0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 4294967296.0
+ %cvt = fptoui float %fix to i32
+ ret i32 %cvt
+}
+
+define float @fcvtzu_f32_i32_7_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_f32_i32_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzu s0, s0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzu_f32_i32_fpr:
+; CHECK-GI-LABEL: fcvtzu_f32_i32_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
; CHECK-GI-NEXT: fmul s0, s0, s1
@@ -334,22 +390,23 @@ define float @fcvtzu_f32_i32_fpr(float %flt) {
ret float %bc
}
-define i32 @fcvtzu_f32_i32_32(float %flt) {
-; CHECK-SD-LABEL: fcvtzu_f32_i32_32:
+define float @fcvtzu_f32_i32_32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_f32_i32_32_fpr:
; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzu w0, s0, #32
+; CHECK-SD-NEXT: fcvtzu s0, s0, #32
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzu_f32_i32_32:
+; CHECK-GI-LABEL: fcvtzu_f32_i32_32_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
; CHECK-GI-NEXT: fmov s1, w8
; CHECK-GI-NEXT: fmul s0, s0, s1
-; CHECK-GI-NEXT: fcvtzu w0, s0
+; CHECK-GI-NEXT: fcvtzu s0, s0
; CHECK-GI-NEXT: ret
%fix = fmul float %flt, 4294967296.0
%cvt = fptoui float %fix to i32
- ret i32 %cvt
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
}
define i64 @fcvtzu_f32_i64_7(float %flt) {
@@ -496,8 +553,8 @@ define i32 @fcvtzu_f16_i32_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI24_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI24_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI27_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI27_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -524,8 +581,8 @@ define i32 @fcvtzu_f16_i32_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI25_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI25_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI28_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI28_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -552,8 +609,8 @@ define i64 @fcvtzu_f16_i64_7(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI26_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI26_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI29_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI29_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -580,8 +637,8 @@ define i64 @fcvtzu_f16_i64_15(half %flt) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI27_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI27_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI30_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI30_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -763,8 +820,8 @@ define half @scvtf_f16_i32_7(i32 %int) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI36_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI36_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI39_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI39_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i32 %int to half
@@ -801,8 +858,8 @@ define half @scvtf_f16_i32_15(i32 %int) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI37_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI37_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI40_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI40_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i32 %int to half
@@ -839,8 +896,8 @@ define half @scvtf_f16_i64_7(i64 %long) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI38_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI38_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI41_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI41_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i64 %long to half
@@ -877,8 +934,8 @@ define half @scvtf_f16_i64_15(i64 %long) {
; CHECK-GI-FP16-LABEL: scvtf_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: scvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI39_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI39_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI42_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI42_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = sitofp i64 %long to half
@@ -1059,8 +1116,8 @@ define half @ucvtf_f16_i32_7(i32 %int) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI48_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI48_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI51_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI51_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i32 %int to half
@@ -1097,8 +1154,8 @@ define half @ucvtf_f16_i32_15(i32 %int) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, w0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI49_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI49_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI52_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI52_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i32 %int to half
@@ -1135,8 +1192,8 @@ define half @ucvtf_f16_i64_7(i64 %long) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI50_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI50_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI53_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI53_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i64 %long to half
@@ -1173,8 +1230,8 @@ define half @ucvtf_f16_i64_15(i64 %long) {
; CHECK-GI-FP16-LABEL: ucvtf_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
; CHECK-GI-FP16-NEXT: ucvtf h0, x0
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI51_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI51_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI54_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI54_0]
; CHECK-GI-FP16-NEXT: fdiv h0, h0, h1
; CHECK-GI-FP16-NEXT: ret
%cvt = uitofp i64 %long to half
@@ -1227,13 +1284,13 @@ define i32 @fcvtzs_sat_f32_i32_32(float %flt) {
ret i32 %cvt
}
-define float @fcvtzs_sat_f32_i32_fpr(float %flt) {
-; CHECK-SD-LABEL: fcvtzs_sat_f32_i32_fpr:
+define float @fcvtzs_sat_f32_i32_7_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_sat_f32_i32_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs s0, s0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzs_sat_f32_i32_fpr:
+; CHECK-GI-LABEL: fcvtzs_sat_f32_i32_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
; CHECK-GI-NEXT: fmul s0, s0, s1
@@ -1245,6 +1302,25 @@ define float @fcvtzs_sat_f32_i32_fpr(float %flt) {
ret float %bc
}
+define float @fcvtzs_sat_f32_i32_32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzs_sat_f32_i32_32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_sat_f32_i32_32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 4294967296.0
+ %cvt = call i32 @llvm.fptosi.sat.i32.f32(float %fix)
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzs_sat_f32_i64_64(float %flt) {
; CHECK-SD-LABEL: fcvtzs_sat_f32_i64_64:
; CHECK-SD: // %bb.0:
@@ -1335,13 +1411,13 @@ define i64 @fcvtzs_sat_f64_i64_64(double %dbl) {
ret i64 %cvt
}
-define double @fcvtzs_sat_f64_i64_fpr(double %dbl) {
-; CHECK-SD-LABEL: fcvtzs_sat_f64_i64_fpr:
+define double @fcvtzs_sat_f64_i64_7_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_sat_f64_i64_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzs d0, d0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzs_sat_f64_i64_fpr:
+; CHECK-GI-LABEL: fcvtzs_sat_f64_i64_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
; CHECK-GI-NEXT: fmov d1, x8
@@ -1354,6 +1430,26 @@ define double @fcvtzs_sat_f64_i64_fpr(double %dbl) {
ret double %bc
}
+define double @fcvtzs_sat_f64_i64_64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzs_sat_f64_i64_64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs d0, d0, #64
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzs_sat_f64_i64_64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4895412794951729152 // =0x43f0000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzs d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 18446744073709551616.0
+ %cvt = call i64 @llvm.fptosi.sat.i64.f64(double %fix)
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
+
define i32 @fcvtzs_sat_f16_i32_7(half %dbl) {
; CHECK-NO16-LABEL: fcvtzs_sat_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -1372,8 +1468,8 @@ define i32 @fcvtzs_sat_f16_i32_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI61_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI61_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI66_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI66_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1400,8 +1496,8 @@ define i32 @fcvtzs_sat_f16_i32_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI62_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI62_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI67_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI67_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1428,8 +1524,8 @@ define i64 @fcvtzs_sat_f16_i64_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI63_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI63_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI68_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI68_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1456,8 +1552,8 @@ define i64 @fcvtzs_sat_f16_i64_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzs_sat_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI64_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI64_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI69_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI69_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzs x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1510,13 +1606,13 @@ define i32 @fcvtzu_sat_f32_i32_32(float %flt) {
ret i32 %cvt
}
-define float @fcvtzu_sat_f32_i32_fpr(float %flt) {
-; CHECK-SD-LABEL: fcvtzu_sat_f32_i32_fpr:
+define float @fcvtzu_sat_f32_i32_7_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_sat_f32_i32_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzu s0, s0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzu_sat_f32_i32_fpr:
+; CHECK-GI-LABEL: fcvtzu_sat_f32_i32_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
; CHECK-GI-NEXT: fmul s0, s0, s1
@@ -1528,6 +1624,25 @@ define float @fcvtzu_sat_f32_i32_fpr(float %flt) {
ret float %bc
}
+define float @fcvtzu_sat_f32_i32_32_fpr(float %flt) {
+; CHECK-SD-LABEL: fcvtzu_sat_f32_i32_32_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_sat_f32_i32_32_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %fix = fmul float %flt, 4294967296.0
+ %cvt = call i32 @llvm.fptoui.sat.i32.f32(float %fix)
+ %bc = bitcast i32 %cvt to float
+ ret float %bc
+}
+
define i64 @fcvtzu_sat_f32_i64_64(float %flt) {
; CHECK-SD-LABEL: fcvtzu_sat_f32_i64_64:
; CHECK-SD: // %bb.0:
@@ -1618,13 +1733,13 @@ define i64 @fcvtzu_sat_f64_i64_64(double %dbl) {
ret i64 %cvt
}
-define double @fcvtzu_sat_f64_i64_fpr(double %dbl) {
-; CHECK-SD-LABEL: fcvtzu_sat_f64_i64_fpr:
+define double @fcvtzu_sat_f64_i64_7_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzu_sat_f64_i64_7_fpr:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fcvtzu d0, d0, #7
; CHECK-SD-NEXT: ret
;
-; CHECK-GI-LABEL: fcvtzu_sat_f64_i64_fpr:
+; CHECK-GI-LABEL: fcvtzu_sat_f64_i64_7_fpr:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov x8, #4638707616191610880 // =0x4060000000000000
; CHECK-GI-NEXT: fmov d1, x8
@@ -1637,6 +1752,26 @@ define double @fcvtzu_sat_f64_i64_fpr(double %dbl) {
ret double %bc
}
+define double @fcvtzu_sat_f64_i64_64_fpr(double %dbl) {
+; CHECK-SD-LABEL: fcvtzu_sat_f64_i64_64_fpr:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu d0, d0, #64
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: fcvtzu_sat_f64_i64_64_fpr:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov x8, #4895412794951729152 // =0x43f0000000000000
+; CHECK-GI-NEXT: fmov d1, x8
+; CHECK-GI-NEXT: fmul d0, d0, d1
+; CHECK-GI-NEXT: fcvtzu d0, d0
+; CHECK-GI-NEXT: ret
+ %fix = fmul double %dbl, 18446744073709551616.0
+ %cvt = call i64 @llvm.fptoui.sat.i64.f64(double %fix)
+ %bc = bitcast i64 %cvt to double
+ ret double %bc
+}
+
+
define i32 @fcvtzu_sat_f16_i32_7(half %dbl) {
; CHECK-NO16-LABEL: fcvtzu_sat_f16_i32_7:
; CHECK-NO16: // %bb.0:
@@ -1655,8 +1790,8 @@ define i32 @fcvtzu_sat_f16_i32_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i32_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI74_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI74_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI81_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI81_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1683,8 +1818,8 @@ define i32 @fcvtzu_sat_f16_i32_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i32_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI75_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI75_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI82_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI82_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu w0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1711,8 +1846,8 @@ define i64 @fcvtzu_sat_f16_i64_7(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i64_7:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI76_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI76_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI83_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI83_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1739,8 +1874,8 @@ define i64 @fcvtzu_sat_f16_i64_15(half %dbl) {
;
; CHECK-GI-FP16-LABEL: fcvtzu_sat_f16_i64_15:
; CHECK-GI-FP16: // %bb.0:
-; CHECK-GI-FP16-NEXT: adrp x8, .LCPI77_0
-; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI77_0]
+; CHECK-GI-FP16-NEXT: adrp x8, .LCPI84_0
+; CHECK-GI-FP16-NEXT: ldr h1, [x8, :lo12:.LCPI84_0]
; CHECK-GI-FP16-NEXT: fmul h0, h0, h1
; CHECK-GI-FP16-NEXT: fcvtzu x0, h0
; CHECK-GI-FP16-NEXT: ret
@@ -1748,6 +1883,151 @@ define i64 @fcvtzu_sat_f16_i64_15(half %dbl) {
%cvt = call i64 @llvm.fptoui.sat.i64.f16(half %fix)
ret i64 %cvt
}
+
+define i32 @neon_fcvtzs_f32_i32_7(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_7:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs w0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_7:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 128.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define i32 @neon_fcvtzs_f32_i32_32(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs w0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 4294967296.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define float @neon_fcvtzs_f32_i32_7_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_7_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_7_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 128.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
+define float @neon_fcvtzs_f32_i32_32_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_32_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzs s0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_32_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzs s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 4294967296.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
+define i32 @neon_fcvtzu_f32_i32_7(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_7:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu w0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_7:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 128.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define i32 @neon_fcvtzu_f32_i32_32(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_32:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu w0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_32:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu w0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 4294967296.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ ret i32 %r
+}
+
+define float @neon_fcvtzu_f32_i32_7_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_7_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #7
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_7_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.2s, #67, lsl #24
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 128.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
+define float @neon_fcvtzu_f32_i32_32_bitcast(float %a) {
+; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_32_bitcast:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: fcvtzu s0, s0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_32_bitcast:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: mov w8, #1333788672 // =0x4f800000
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: fmul s0, s0, s1
+; CHECK-GI-NEXT: fcvtzu s0, s0
+; CHECK-GI-NEXT: ret
+ %mul = fmul float %a, 4294967296.0
+ %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
+ %bc = bitcast i32 %r to float
+ ret float %bc
+}
+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
; CHECK-FP16: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll b/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
deleted file mode 100644
index ca162ac506502..0000000000000
--- a/llvm/test/CodeGen/AArch64/neon-fcvt-fixed.ll
+++ /dev/null
@@ -1,148 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-NO16,CHECK-SD-NO16
-; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-NO16,CHECK-GI-NO16
-
-define i32 @neon_fcvtzs_f32_i32(float %a) {
-; CHECK-SD-LABEL: neon_fcvtzs_f32_i32:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzs w0, s0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzs_f32_i32:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov s1, #8.00000000
-; CHECK-GI-NEXT: fmul s0, s0, s1
-; CHECK-GI-NEXT: fcvtzs w0, s0
-; CHECK-GI-NEXT: ret
- %mul = fmul float %a, 8.000000e+00
- %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
- ret i32 %r
-}
-
-define float @neon_fcvtzs_f32_i32_bitcast(float %a) {
-; CHECK-SD-LABEL: neon_fcvtzs_f32_i32_bitcast:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzs s0, s0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzs_f32_i32_bitcast:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov s1, #8.00000000
-; CHECK-GI-NEXT: fmul s0, s0, s1
-; CHECK-GI-NEXT: fcvtzs s0, s0
-; CHECK-GI-NEXT: ret
- %mul = fmul float %a, 8.000000e+00
- %r = call i32 @llvm.aarch64.neon.fcvtzs.i32.f32(float %mul)
- %bc = bitcast i32 %r to float
- ret float %bc
-}
-
-define i64 @neon_fcvtzs_f64_i64(double %a) {
-; CHECK-SD-LABEL: neon_fcvtzs_f64_i64:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzs x0, d0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzs_f64_i64:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov d1, #8.00000000
-; CHECK-GI-NEXT: fmul d0, d0, d1
-; CHECK-GI-NEXT: fcvtzs x0, d0
-; CHECK-GI-NEXT: ret
- %mul = fmul double %a, 8.000000e+00
- %r = call i64 @llvm.aarch64.neon.fcvtzs.i64.f64(double %mul)
- ret i64 %r
-}
-
-define double @neon_fcvtzs_f64_i64_bitcast(double %a) {
-; CHECK-SD-LABEL: neon_fcvtzs_f64_i64_bitcast:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzs d0, d0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzs_f64_i64_bitcast:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov d1, #8.00000000
-; CHECK-GI-NEXT: fmul d0, d0, d1
-; CHECK-GI-NEXT: fcvtzs d0, d0
-; CHECK-GI-NEXT: ret
- %mul = fmul double %a, 8.000000e+00
- %r = call i64 @llvm.aarch64.neon.fcvtzs.i64.f64(double %mul)
- %bc = bitcast i64 %r to double
- ret double %bc
-}
-
-define i32 @neon_fcvtzu_f32_i32(float %a) {
-; CHECK-SD-LABEL: neon_fcvtzu_f32_i32:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzu w0, s0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzu_f32_i32:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov s1, #8.00000000
-; CHECK-GI-NEXT: fmul s0, s0, s1
-; CHECK-GI-NEXT: fcvtzu w0, s0
-; CHECK-GI-NEXT: ret
- %mul = fmul float %a, 8.000000e+00
- %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
- ret i32 %r
-}
-
-define float @neon_fcvtzu_f32_i32_bitcast(float %a) {
-; CHECK-SD-LABEL: neon_fcvtzu_f32_i32_bitcast:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzu s0, s0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzu_f32_i32_bitcast:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov s1, #8.00000000
-; CHECK-GI-NEXT: fmul s0, s0, s1
-; CHECK-GI-NEXT: fcvtzu s0, s0
-; CHECK-GI-NEXT: ret
- %mul = fmul float %a, 8.000000e+00
- %r = call i32 @llvm.aarch64.neon.fcvtzu.i32.f32(float %mul)
- %bc = bitcast i32 %r to float
- ret float %bc
-}
-
-define i64 @neon_fcvtzu_f64_i64(double %a) {
-; CHECK-SD-LABEL: neon_fcvtzu_f64_i64:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzu x0, d0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzu_f64_i64:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov d1, #8.00000000
-; CHECK-GI-NEXT: fmul d0, d0, d1
-; CHECK-GI-NEXT: fcvtzu x0, d0
-; CHECK-GI-NEXT: ret
- %mul = fmul double %a, 8.000000e+00
- %r = call i64 @llvm.aarch64.neon.fcvtzu.i64.f64(double %mul)
- ret i64 %r
-}
-
-define double @neon_fcvtzu_f64_i64_bitcast(double %a) {
-; CHECK-SD-LABEL: neon_fcvtzu_f64_i64_bitcast:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: fcvtzu d0, d0, #3
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: neon_fcvtzu_f64_i64_bitcast:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: fmov d1, #8.00000000
-; CHECK-GI-NEXT: fmul d0, d0, d1
-; CHECK-GI-NEXT: fcvtzu d0, d0
-; CHECK-GI-NEXT: ret
- %mul = fmul double %a, 8.000000e+00
- %r = call i64 @llvm.aarch64.neon.fcvtzu.i64.f64(double %mul)
- %bc = bitcast i64 %r to double
- ret double %bc
-}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
-; CHECK-GI-NO16: {{.*}}
-; CHECK-NO16: {{.*}}
-; CHECK-SD-NO16: {{.*}}
>From f627a42cc0fc5aece07174b705023b1432786841 Mon Sep 17 00:00:00 2001
From: Kieran Bailey <kieran.bailey at arm.com>
Date: Tue, 28 Jul 2026 14:07:03 +0000
Subject: [PATCH 3/3] [AArch64][SelectionDAG] Fold fp_to_int(fmul) for FPR
results
Bundled the FPR with the GPR variants of the patterns.
The multiclass FPToIntegerIntPats cannot be used with any_fp_to_int. Due to the parameter taking an intrinsic, when changed to SDPattternOperator and passing the generic any_fp_to_int, compilation fails due to overlapping patterns in fastIsel. So, I have kept these in a separate multiclass FPToIntegerFmulPats.
The saturated patterns are bundled into its FPToIntegerSatPats class without problem.
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 55 ++++++++++++++-------
1 file changed, 36 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 63cf927a6d7c9..69cf99e54309e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -6675,6 +6675,8 @@ defm FCVTPU : SIMDFPTwoScalar< 1, 1, 0b11010, "fcvtpu", int_aarch64_neon_fcvtp
def FCVTXNv1i64 : SIMDInexactCvtTwoScalar<0b10110, "fcvtxn">;
defm FCVTZS : SIMDFPTwoScalar< 0, 1, 0b11011, "fcvtzs", any_fp_to_sint>;
defm FCVTZU : SIMDFPTwoScalar< 1, 1, 0b11011, "fcvtzu", any_fp_to_uint>;
+defm FCVTZS : SIMDFPScalarRShift<0, 0b11111, "fcvtzs">;
+defm FCVTZU : SIMDFPScalarRShift<1, 0b11111, "fcvtzu">;
defm FRECPE : SIMDFPTwoScalarNonCVT< 0, 1, 0b11101, "frecpe">;
defm FRECPX : SIMDFPTwoScalarNonCVT< 0, 1, 0b11111, "frecpx">;
defm FRSQRTE : SIMDFPTwoScalarNonCVT< 1, 1, 0b11101, "frsqrte">;
@@ -6809,25 +6811,46 @@ multiclass FPToIntegerIntPats<Intrinsic round, string INST> {
def : Pat<(f64 (bitconvert (i64 (round f64:$Rn)))),
(!cast<Instruction>(INST # v1i64) $Rn)>;
}
+}
+
+defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzs, "FCVTZS">;
+defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzu, "FCVTZU">;
+
+// This thing just allows us to change the type of the node produced. The imm
+// value we want is already in V from SelectCVTFixedPointVec.
+def fixedpoint_vec_xform : SDNodeXForm<timm, [{
+ (void)N;
+ return V;
+}]>;
+def gi_fixedpoint_vec_xform : GICustomOperandRenderer<"renderFixedPointXForm">,
+ GISDNodeXFormEquiv<fixedpoint_vec_xform>;
+multiclass FPToIntegerFmulPats<SDPatternOperator OpN, string INST> {
let Predicates = [HasFullFP16] in {
- def : Pat<(i32 (round (fmul f16:$Rn, fixedpoint_f16_i32:$scale))),
+ def : Pat<(i32 (OpN (fmul f16:$Rn, fixedpoint_f16_i32:$scale))),
(!cast<Instruction>(INST # SWHri) $Rn, $scale)>;
- def : Pat<(i64 (round (fmul f16:$Rn, fixedpoint_f16_i64:$scale))),
+ def : Pat<(i64 (OpN (fmul f16:$Rn, fixedpoint_f16_i64:$scale))),
(!cast<Instruction>(INST # SXHri) $Rn, $scale)>;
}
- def : Pat<(i32 (round (fmul f32:$Rn, fixedpoint_f32_i32:$scale))),
+ def : Pat<(i32 (OpN (fmul f32:$Rn, fixedpoint_f32_i32:$scale))),
(!cast<Instruction>(INST # SWSri) $Rn, $scale)>;
- def : Pat<(i64 (round (fmul f32:$Rn, fixedpoint_f32_i64:$scale))),
+ def : Pat<(i64 (OpN (fmul f32:$Rn, fixedpoint_f32_i64:$scale))),
(!cast<Instruction>(INST # SXSri) $Rn, $scale)>;
- def : Pat<(i32 (round (fmul f64:$Rn, fixedpoint_f64_i32:$scale))),
+ def : Pat<(i32 (OpN (fmul f64:$Rn, fixedpoint_f64_i32:$scale))),
(!cast<Instruction>(INST # SWDri) $Rn, $scale)>;
- def : Pat<(i64 (round (fmul f64:$Rn, fixedpoint_f64_i64:$scale))),
+ def : Pat<(i64 (OpN (fmul f64:$Rn, fixedpoint_f64_i64:$scale))),
(!cast<Instruction>(INST # SXDri) $Rn, $scale)>;
+
+ def : Pat<(f32 (bitconvert (i32 (OpN (fmul FPR32:$Rn, fixedpoint_f32_i32:$scale))))),
+ (!cast<Instruction>(INST # "s") FPR32:$Rn, (fixedpoint_vec_xform fixedpoint_f32_i32:$scale))>;
+ def : Pat<(f64 (bitconvert (i64 (OpN (fmul FPR64:$Rn, fixedpoint_f64_i64:$scale))))),
+ (!cast<Instruction>(INST # "d") FPR64:$Rn, (fixedpoint_vec_xform fixedpoint_f64_i64:$scale))>;
}
-defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzs, "FCVTZS">;
-defm : FPToIntegerIntPats<int_aarch64_neon_fcvtzu, "FCVTZU">;
+defm : FPToIntegerFmulPats<any_fp_to_sint, "FCVTZS">;
+defm : FPToIntegerFmulPats<any_fp_to_uint, "FCVTZU">;
+defm : FPToIntegerFmulPats<int_aarch64_neon_fcvtzs, "FCVTZS">;
+defm : FPToIntegerFmulPats<int_aarch64_neon_fcvtzu, "FCVTZU">;
// AArch64's FCVT instructions saturate when out of range.
multiclass FPToIntegerSatPats<SDNode to_int_sat, string INST> {
@@ -6898,6 +6921,11 @@ multiclass FPToIntegerSatPats<SDNode to_int_sat, string INST> {
(!cast<Instruction>(INST # SWDri) $Rn, $scale)>;
def : Pat<(i64 (to_int_sat (fmul f64:$Rn, fixedpoint_f64_i64:$scale), i64)),
(!cast<Instruction>(INST # SXDri) $Rn, $scale)>;
+
+ def : Pat<(f32 (bitconvert (i32 (to_int_sat (fmul FPR32:$Rn, fixedpoint_f32_i32:$scale), i32)))),
+ (!cast<Instruction>(INST # "s") FPR32:$Rn, (fixedpoint_vec_xform fixedpoint_f32_i32:$scale))>;
+ def : Pat<(f64 (bitconvert (i64 (to_int_sat (fmul FPR64:$Rn, fixedpoint_f64_i64:$scale), i64)))),
+ (!cast<Instruction>(INST # "d") FPR64:$Rn, (fixedpoint_vec_xform fixedpoint_f64_i64:$scale))>;
}
defm : FPToIntegerSatPats<fp_to_sint_sat, "FCVTZS">;
@@ -9117,8 +9145,6 @@ def : Pat<(i64 (int_aarch64_neon_sqsub (i64 FPR64:$Rd),
//----------------------------------------------------------------------------
// AdvSIMD scalar shift instructions
//----------------------------------------------------------------------------
-defm FCVTZS : SIMDFPScalarRShift<0, 0b11111, "fcvtzs">;
-defm FCVTZU : SIMDFPScalarRShift<1, 0b11111, "fcvtzu">;
defm SCVTF : SIMDFPScalarRShift<0, 0b11100, "scvtf">;
defm UCVTF : SIMDFPScalarRShift<1, 0b11100, "ucvtf">;
// Codegen patterns for the above. We don't put these directly on the
@@ -9251,15 +9277,6 @@ class fixedpoint_vec_f32<ValueType FloatVT>
: ComplexPattern<FloatVT, 1, "SelectCVTFixedPointVec<32>">;
class fixedpoint_vec_f16<ValueType FloatVT>
: ComplexPattern<FloatVT, 1, "SelectCVTFixedPointVec<16>">;
-
-// This thing just allows us to change the type of the node produced.
-// The imm value we want is already in V from SelectCVTFixedPointVec.
-def fixedpoint_vec_xform : SDNodeXForm<timm, [{
- (void)N;
- return V;
-}]>;
-def gi_fixedpoint_vec_xform : GICustomOperandRenderer<"renderFixedPointXForm">,
- GISDNodeXFormEquiv<fixedpoint_vec_xform>;
def fixedpoint_v2f64 : fixedpoint_vec_f64<v2f64>;
def fixedpoint_v2f32 : fixedpoint_vec_f32<v2f32>;
More information about the llvm-commits
mailing list