[AArch64][SelectionDAG] Avoid cross-bank copy for NEON vcvtfp2fx result - #210275
Conversation
|
@llvm/pr-subscribers-backend-aarch64 Author: Kieran B (kieroxide) Changes
A follow-up patch will also include the fix for GlobalIsel Full diff: https://github.com/llvm/llvm-project/pull/210275.diff 3 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 51fb2e1d1f9f0..f0e7e020c05e4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -9121,6 +9121,49 @@ defm FCVTZS : SIMDFPScalarRShift<0, 0b11111, "fcvtzs">;
defm FCVTZU : SIMDFPScalarRShift<1, 0b11111, "fcvtzu">;
defm SCVTF : SIMDFPScalarRShift<0, 0b11100, "scvtf">;
defm UCVTF : SIMDFPScalarRShift<1, 0b11100, "ucvtf">;
+
+// Transformation for SIMD shift imm to fixed point imm for FPR-to-GPR result
+def fixedpoint_scalar_xform : SDNodeXForm<timm, [{
+ (void)N;
+ return V;
+}]>;
+
+multiclass FPToFixedScalarPats<SDPatternOperator OpN, string INST > {
+// Allow integer result to remain in GPR registers
+// SelectionDAG-only as GIsel doesn't import fixedpoint_scalar_xform
+// Give priority over generic FPR fallback
+let AddedComplexity = 1 in {
+ def : Pat<(i32 (OpN FPR32:$Rn, vecshiftR32:$imm)),
+ (!cast<Instruction>(INST # "SWSri") FPR32:$Rn, (fixedpoint_scalar_xform vecshiftR32:$imm))>;
+ def : Pat<(i64 (OpN (f64 FPR64:$Rn), vecshiftR64:$imm)),
+ (!cast<Instruction>(INST # "SXDri") FPR64:$Rn, (fixedpoint_scalar_xform vecshiftR64:$imm))>;
+
+ def : Pat<(i32 (OpN (f16 FPR16:$Rn), vecshiftR32:$imm)),
+ (!cast<Instruction>(INST # "SWHri") FPR16:$Rn, (fixedpoint_scalar_xform vecshiftR32:$imm))>;
+ def : Pat<(i64 (OpN (f16 FPR16:$Rn), vecshiftR64:$imm)),
+ (!cast<Instruction>(INST # "SXHri") FPR16:$Rn, (fixedpoint_scalar_xform vecshiftR64:$imm))>;
+ }
+
+ // Bitcast results kept in FP/SIMD registers.
+ def : Pat<(f32 (bitconvert(i32 (OpN FPR32:$Rn, vecshiftR32:$imm)))),
+ (!cast<Instruction>(INST # "s") FPR32:$Rn, vecshiftR32:$imm)>;
+ def : Pat<(f64 (bitconvert(i64 (OpN (f64 FPR64:$Rn), vecshiftR64:$imm)))),
+ (!cast<Instruction>(INST # "d") FPR64:$Rn, vecshiftR64:$imm)>;
+
+ def : Pat<(f32(bitconvert (i32 (OpN (f16 FPR16:$Rn), vecshiftR32:$imm)))),
+ (f32 (INSERT_SUBREG
+ (f32 (IMPLICIT_DEF)),
+ (!cast<Instruction>(INST # "h") FPR16:$Rn, vecshiftR32:$imm),
+ hsub))>;
+ def : Pat<(f64 (bitconvert (i64 (OpN (f16 FPR16:$Rn), vecshiftR64:$imm)))),
+ (f64 (INSERT_SUBREG
+ (f64 (IMPLICIT_DEF)),
+ (!cast<Instruction>(INST # "h") FPR16:$Rn, vecshiftR64:$imm),
+ hsub))>;
+}
+defm : FPToFixedScalarPats<int_aarch64_neon_vcvtfp2fxs, "FCVTZS">;
+defm : FPToFixedScalarPats<int_aarch64_neon_vcvtfp2fxu, "FCVTZU">;
+
// Codegen patterns for the above. We don't put these directly on the
// instructions because TableGen's type inference can't handle the truth.
// Having the same base pattern for fp <--> int totally freaks it out.
diff --git a/llvm/test/CodeGen/AArch64/fp16_intrinsic_scalar_2op.ll b/llvm/test/CodeGen/AArch64/fp16_intrinsic_scalar_2op.ll
index da70599483a63..f44e1a6fa9970 100644
--- a/llvm/test/CodeGen/AArch64/fp16_intrinsic_scalar_2op.ll
+++ b/llvm/test/CodeGen/AArch64/fp16_intrinsic_scalar_2op.ll
@@ -185,6 +185,7 @@ declare i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half, i32) #1
declare i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half, i32) #1
declare half @llvm.aarch64.neon.vcvtfxu2fp.f16.i32(i32, i32) #1
declare i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half, i32) #1
+declare i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half, i32) #1
define dso_local half @test_vcvth_n_f16_s16_1(i16 %a) {
; CHECK-SD-LABEL: test_vcvth_n_f16_s16_1:
@@ -247,11 +248,16 @@ entry:
}
define dso_local i16 @test_vcvth_n_s16_f16_1(half %a) {
-; CHECK-LABEL: test_vcvth_n_s16_f16_1:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzs h0, h0, #1
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_s16_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs w0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s16_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #1
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%fcvth_n = tail call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1)
%0 = trunc i32 %fcvth_n to i16
@@ -259,11 +265,16 @@ entry:
}
define dso_local i16 @test_vcvth_n_s16_f16_16(half %a) {
-; CHECK-LABEL: test_vcvth_n_s16_f16_16:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzs h0, h0, #16
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_s16_f16_16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs w0, h0, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s16_f16_16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #16
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%fcvth_n = tail call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 16)
%0 = trunc i32 %fcvth_n to i16
@@ -271,47 +282,89 @@ entry:
}
define dso_local i32 @test_vcvth_n_s32_f16_1(half %a) {
-; CHECK-LABEL: test_vcvth_n_s32_f16_1:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzs h0, h0, #1
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_s32_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs w0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s32_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #1
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%vcvth_n_s32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 1)
ret i32 %vcvth_n_s32_f16
}
define dso_local i32 @test_vcvth_n_s32_f16_16(half %a) {
-; CHECK-LABEL: test_vcvth_n_s32_f16_16:
+; CHECK-SD-LABEL: test_vcvth_n_s32_f16_16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs w0, h0, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s32_f16_16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #16
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %vcvth_n_s32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 16)
+ ret i32 %vcvth_n_s32_f16
+}
+
+define dso_local float @test_vcvth_n_s32_f16_fpr(half %a) {
+; CHECK-LABEL: test_vcvth_n_s32_f16_fpr:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fcvtzs h0, h0, #16
-; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
entry:
%vcvth_n_s32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f16(half %a, i32 16)
- ret i32 %vcvth_n_s32_f16
+ %bc = bitcast i32 %vcvth_n_s32_f16 to float
+ ret float %bc
}
define dso_local i64 @test_vcvth_n_s64_f16_1(half %a) {
-; CHECK-LABEL: test_vcvth_n_s64_f16_1:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzs h0, h0, #1
-; CHECK-NEXT: fmov x0, d0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_s64_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs x0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s64_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #1
+; CHECK-GI-NEXT: fmov x0, d0
+; CHECK-GI-NEXT: ret
entry:
%vcvth_n_s64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 1)
ret i64 %vcvth_n_s64_f16
}
define dso_local i64 @test_vcvth_n_s64_f16_32(half %a) {
-; CHECK-LABEL: test_vcvth_n_s64_f16_32:
+; CHECK-SD-LABEL: test_vcvth_n_s64_f16_32:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzs x0, h0, #32
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_s64_f16_32:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzs h0, h0, #32
+; CHECK-GI-NEXT: fmov x0, d0
+; CHECK-GI-NEXT: ret
+entry:
+ %vcvth_n_s64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 32)
+ ret i64 %vcvth_n_s64_f16
+}
+
+define dso_local double @test_vcvth_n_s64_f16_fpr(half %a) {
+; CHECK-LABEL: test_vcvth_n_s64_f16_fpr:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fcvtzs h0, h0, #32
-; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
entry:
%vcvth_n_s64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f16(half %a, i32 32)
- ret i64 %vcvth_n_s64_f16
+ %bc = bitcast i64 %vcvth_n_s64_f16 to double
+ ret double %bc
}
define dso_local half @test_vcvth_n_f16_u16_1(i16 %a) {
@@ -375,11 +428,16 @@ entry:
}
define dso_local i16 @test_vcvth_n_u16_f16_1(half %a) {
-; CHECK-LABEL: test_vcvth_n_u16_f16_1:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzu h0, h0, #1
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_u16_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu w0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u16_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #1
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%fcvth_n = tail call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1)
%0 = trunc i32 %fcvth_n to i16
@@ -387,11 +445,16 @@ entry:
}
define dso_local i16 @test_vcvth_n_u16_f16_16(half %a) {
-; CHECK-LABEL: test_vcvth_n_u16_f16_16:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzu h0, h0, #16
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_u16_f16_16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu w0, h0, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u16_f16_16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #16
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%fcvth_n = tail call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 16)
%0 = trunc i32 %fcvth_n to i16
@@ -399,25 +462,89 @@ entry:
}
define dso_local i32 @test_vcvth_n_u32_f16_1(half %a) {
-; CHECK-LABEL: test_vcvth_n_u32_f16_1:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: fcvtzu h0, h0, #1
-; CHECK-NEXT: fmov w0, s0
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: test_vcvth_n_u32_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu w0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u32_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #1
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
entry:
%vcvth_n_u32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 1)
ret i32 %vcvth_n_u32_f16
}
define dso_local i32 @test_vcvth_n_u32_f16_16(half %a) {
-; CHECK-LABEL: test_vcvth_n_u32_f16_16:
+; CHECK-SD-LABEL: test_vcvth_n_u32_f16_16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu w0, h0, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u32_f16_16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #16
+; CHECK-GI-NEXT: fmov w0, s0
+; CHECK-GI-NEXT: ret
+entry:
+ %vcvth_n_u32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 16)
+ ret i32 %vcvth_n_u32_f16
+}
+
+define dso_local float @test_vcvth_n_u32_f16_fpr(half %a) {
+; CHECK-LABEL: test_vcvth_n_u32_f16_fpr:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fcvtzu h0, h0, #16
-; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
entry:
%vcvth_n_u32_f16 = tail call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f16(half %a, i32 16)
- ret i32 %vcvth_n_u32_f16
+ %bc = bitcast i32 %vcvth_n_u32_f16 to float
+ ret float %bc
+}
+
+define dso_local i64 @test_vcvth_n_u64_f16_1(half %a) {
+; CHECK-SD-LABEL: test_vcvth_n_u64_f16_1:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu x0, h0, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u64_f16_1:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #1
+; CHECK-GI-NEXT: fmov x0, d0
+; CHECK-GI-NEXT: ret
+entry:
+ %vcvth_n_u64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 1)
+ ret i64 %vcvth_n_u64_f16
+}
+
+define dso_local i64 @test_vcvth_n_u64_f16_16(half %a) {
+; CHECK-SD-LABEL: test_vcvth_n_u64_f16_16:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: fcvtzu x0, h0, #16
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: test_vcvth_n_u64_f16_16:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: fcvtzu h0, h0, #16
+; CHECK-GI-NEXT: fmov x0, d0
+; CHECK-GI-NEXT: ret
+entry:
+ %vcvth_n_u64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 16)
+ ret i64 %vcvth_n_u64_f16
+}
+
+define dso_local double @test_vcvth_n_u64_f16_fpr(half %a) {
+; CHECK-LABEL: test_vcvth_n_u64_f16_fpr:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fcvtzu h0, h0, #16
+; CHECK-NEXT: ret
+entry:
+ %vcvth_n_u64_f16 = tail call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f16(half %a, i32 16)
+ %bc = bitcast i64 %vcvth_n_u64_f16 to double
+ ret double %bc
}
define dso_local i16 @vcageh_f16_test(half %a, half %b) {
diff --git a/llvm/test/CodeGen/AArch64/neon-scalar-vcvtfp2fx.ll b/llvm/test/CodeGen/AArch64/neon-scalar-vcvtfp2fx.ll
new file mode 100644
index 0000000000000..5ca1d8c44cf58
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/neon-scalar-vcvtfp2fx.ll
@@ -0,0 +1,78 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64 -global-isel=0 < %s | FileCheck %s
+
+define i32 @vcvtfp2fxs_f32_i32(float %a) {
+; CHECK-LABEL: vcvtfp2fxs_f32_i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzs w0, s0, #16
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f32(float %a, i32 16)
+ ret i32 %r
+}
+
+define float @vcvtfp2fxs_f32_i32_bitcast(float %a) {
+; CHECK-LABEL: vcvtfp2fxs_f32_i32_bitcast:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzs s0, s0, #16
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f32(float %a, i32 16)
+ %b = bitcast i32 %r to float
+ ret float %b
+}
+
+define i32 @vcvtfp2fxu_f32_i32(float %a) {
+; CHECK-LABEL: vcvtfp2fxu_f32_i32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzu w0, s0, #16
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f32(float %a, i32 16)
+ ret i32 %r
+}
+
+define float @vcvtfp2fxu_f32_i32_bitcast(float %a) {
+; CHECK-LABEL: vcvtfp2fxu_f32_i32_bitcast:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzu s0, s0, #16
+; CHECK-NEXT: ret
+ %r = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f32(float %a, i32 16)
+ %b = bitcast i32 %r to float
+ ret float %b
+}
+
+define i64 @vcvtfp2fxs_f64_i64(double %a) {
+; CHECK-LABEL: vcvtfp2fxs_f64_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzs x0, d0, #16
+; CHECK-NEXT: ret
+ %r = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f64(double %a, i32 16)
+ ret i64 %r
+}
+
+define double @vcvtfp2fxs_f64_i64_bitcast(double %a) {
+; CHECK-LABEL: vcvtfp2fxs_f64_i64_bitcast:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzs d0, d0, #16
+; CHECK-NEXT: ret
+ %r = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f64(double %a, i32 16)
+ %b = bitcast i64 %r to double
+ ret double %b
+}
+
+define i64 @vcvtfp2fxu_f64_i64(double %a) {
+; CHECK-LABEL: vcvtfp2fxu_f64_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzu x0, d0, #16
+; CHECK-NEXT: ret
+ %r = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f64(double %a, i32 16)
+ ret i64 %r
+}
+
+define double @vcvtfp2fxu_f64_i64_bitcast(double %a) {
+; CHECK-LABEL: vcvtfp2fxu_f64_i64_bitcast:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fcvtzu d0, d0, #16
+; CHECK-NEXT: ret
+ %r = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f64(double %a, i32 16)
+ %b = bitcast i64 %r to double
+ ret double %b
+}
|
|
|
||
| multiclass FPToFixedScalarPats<SDPatternOperator OpN, string INST > { | ||
| // Allow integer result to remain in GPR registers | ||
| // SelectionDAG-only as GIsel doesn't import fixedpoint_scalar_xform |
There was a problem hiding this comment.
I am not sure what do you mean to say about GIsel here ? I think this comment needs to be clarified if you want to keep it in the code.
There was a problem hiding this comment.
I meant that the renderer for fixedpoint_scalar_xform has not been added so GIsel cannot use it. I will update the comment to be clearer
| // Allow integer result to remain in GPR registers | ||
| // SelectionDAG-only as GIsel doesn't import fixedpoint_scalar_xform | ||
| // Give priority over generic FPR fallback | ||
| let AddedComplexity = 1 in { |
There was a problem hiding this comment.
If you are creating a class of patterns, I think it is a good idea to bundle these there as well, so they are all in the same place.
CarolineConcatto
left a comment
There was a problem hiding this comment.
Can you double check your commit message. I think it needs to be updated according to your latest change.
e999588 to
a840342
Compare
There was a problem hiding this comment.
Where are these f16 tests coming from ? They don't seem to test any of the new patterns?
There was a problem hiding this comment.
I will remove them. They were from my first commit when i did have 16 bit pattern FPR
a840342 to
41eb642
Compare
Lukacma
left a comment
There was a problem hiding this comment.
After the f16 tests are removed this patch LGTM
5960974 to
6651c05
Compare
…sults - Add SelectionDAG-only patterns for NEON vcvtfp2fx so integer result select GPR instead of FPR, avoiding the need for cross-bank copies. - Bitcast uses still select the FP/SIMD-register forms where available. - Add complexity used to prioritize the new patterns over the generic FP/SIMD patterns which GlobalIsel still uses - Add testing for GPR-resulting and FPR-resulting patterns - Add missing tests in fp16_intrinsic_scalar_2op.ll: test_vcvth_n_u64_f16_1 and test_vcvth_n_u64_f16_16 A follow-up patch will also include the fix for GlobalIsel
- Moved the existing FPR fallbacks into the multiclass - Removed unnecessary AddedComplexity - Restructured comments based on review suggestions
- Acle requires f16 conversions to lower to Hd register - Remove f16 GPR conversion patterns for vcvth_n - Remove the bitconvert test cases for f16
I will remove the missing test cases for u64_f16 as they will be added when the f16 patterns are fixed and are unrelated to my patch.
…sults Updated the types in test names to be correct order for llvm standard
6651c05 to
2547417
Compare
🐧 Linux x64 Test Results
Failed Tests(click on a test name to see its output) lldb-apilldb-api.commands/process/attach/TestProcessAttach.pyIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
A follow-up patch will also include the fix for GlobalIsel.