Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -4746,6 +4746,27 @@ def : Pat<(v2f64 (AArch64frsqrts (v2f64 FPR128:$Rn), (v2f64 FPR128:$Rm))), (FRSQRTSv2f64 FPR128:$Rn, FPR128:$Rm)>; +// Some float -> int -> float conversion patterns for which we want to keep the +// int values in FP registers using the corresponding NEON instructions to +// avoid more costly int <-> fp register transfers. +let Predicates = [HasNEON] in { +def : Pat<(f64 (sint_to_fp (i64 (fp_to_sint f64:$Rn)))), + (SCVTFv1i64 (i64 (FCVTZSv1i64 f64:$Rn)))>; +def : Pat<(f32 (sint_to_fp (i32 (fp_to_sint f32:$Rn)))), + (SCVTFv1i32 (i32 (FCVTZSv1i32 f32:$Rn)))>; +def : Pat<(f64 (uint_to_fp (i64 (fp_to_uint f64:$Rn)))), + (UCVTFv1i64 (i64 (FCVTZUv1i64 f64:$Rn)))>; +def : Pat<(f32 (uint_to_fp (i32 (fp_to_uint f32:$Rn)))), + (UCVTFv1i32 (i32 (FCVTZUv1i32 f32:$Rn)))>; + +let Predicates = [HasFullFP16] in { +def : Pat<(f16 (sint_to_fp (i32 (fp_to_sint f16:$Rn)))), + (SCVTFv1i16 (f16 (FCVTZSv1f16 f16:$Rn)))>; +def : Pat<(f16 (uint_to_fp (i32 (fp_to_uint f16:$Rn)))), + (UCVTFv1i16 (f16 (FCVTZUv1f16 f16:$Rn)))>; +} +} + // If an integer is about to be converted to a floating point value, // just load it on the floating point unit. // Here are the patterns for 8 and 16-bits to float. Index: llvm/test/CodeGen/AArch64/cvt-fp-int-fp.ll =================================================================== --- llvm/test/CodeGen/AArch64/cvt-fp-int-fp.ll +++ llvm/test/CodeGen/AArch64/cvt-fp-int-fp.ll @@ -4,8 +4,8 @@ define double @t1(double %x) { ; CHECK-LABEL: t1: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzs x8, d0 -; CHECK-NEXT: scvtf d0, x8 +; CHECK-NEXT: fcvtzs d0, d0 +; CHECK-NEXT: scvtf d0, d0 ; CHECK-NEXT: ret entry: %conv = fptosi double %x to i64 @@ -16,8 +16,8 @@ define float @t2(float %x) { ; CHECK-LABEL: t2: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: scvtf s0, w8 +; CHECK-NEXT: fcvtzs s0, s0 +; CHECK-NEXT: scvtf s0, s0 ; CHECK-NEXT: ret entry: %conv = fptosi float %x to i32 @@ -28,8 +28,8 @@ define half @t3(half %x) { ; CHECK-LABEL: t3: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzs w8, h0 -; CHECK-NEXT: scvtf h0, w8 +; CHECK-NEXT: fcvtzs h0, h0 +; CHECK-NEXT: scvtf h0, h0 ; CHECK-NEXT: ret entry: %conv = fptosi half %x to i32 @@ -40,8 +40,8 @@ define double @t4(double %x) { ; CHECK-LABEL: t4: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzu x8, d0 -; CHECK-NEXT: ucvtf d0, x8 +; CHECK-NEXT: fcvtzu d0, d0 +; CHECK-NEXT: ucvtf d0, d0 ; CHECK-NEXT: ret entry: %conv = fptoui double %x to i64 @@ -52,8 +52,8 @@ define float @t5(float %x) { ; CHECK-LABEL: t5: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzs w8, s0 -; CHECK-NEXT: scvtf s0, w8 +; CHECK-NEXT: fcvtzs s0, s0 +; CHECK-NEXT: scvtf s0, s0 ; CHECK-NEXT: ret entry: %conv = fptosi float %x to i32 @@ -64,8 +64,8 @@ define half @t6(half %x) { ; CHECK-LABEL: t6: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fcvtzs w8, h0 -; CHECK-NEXT: scvtf h0, w8 +; CHECK-NEXT: fcvtzs h0, h0 +; CHECK-NEXT: scvtf h0, h0 ; CHECK-NEXT: ret entry: %conv = fptosi half %x to i32