Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 42 additions & 35 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -9138,23 +9138,50 @@ 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

// 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 register.
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))>;

// Explicit 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)>;

// FPR fallback patterns.
def : Pat<(i32 (OpN FPR32:$Rn, vecshiftR32:$imm)),
(!cast<Instruction>(INST # "s") FPR32:$Rn, vecshiftR32:$imm)>;
def : Pat<(i64 (OpN (f64 FPR64:$Rn), vecshiftR64:$imm)),
(!cast<Instruction>(INST # "d") FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(v1i64 (OpN (v1f64 FPR64:$Rn), vecshiftR64:$imm)),
(!cast<Instruction>(INST # "d") FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(i32 (OpN (f16 FPR16:$Rn), vecshiftR32:$imm)),
(i32 (INSERT_SUBREG
(i32 (IMPLICIT_DEF)),
(!cast<Instruction>(INST # "h") FPR16:$Rn, vecshiftR32:$imm),
hsub))>;
def : Pat<(i64 (OpN (f16 FPR16:$Rn), vecshiftR64:$imm)),
(i64 (INSERT_SUBREG
(i64 (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 SCVTF and UCVTF. 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.
def : Pat<(int_aarch64_neon_vcvtfp2fxs FPR32:$Rn, vecshiftR32:$imm),
(FCVTZSs FPR32:$Rn, vecshiftR32:$imm)>;
def : Pat<(int_aarch64_neon_vcvtfp2fxu FPR32:$Rn, vecshiftR32:$imm),
(FCVTZUs FPR32:$Rn, vecshiftR32:$imm)>;
def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxs (f64 FPR64:$Rn), vecshiftR64:$imm)),
(FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxu (f64 FPR64:$Rn), vecshiftR64:$imm)),
(FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxs (v1f64 FPR64:$Rn),
vecshiftR64:$imm)),
(FCVTZSd FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(v1i64 (int_aarch64_neon_vcvtfp2fxu (v1f64 FPR64:$Rn),
vecshiftR64:$imm)),
(FCVTZUd FPR64:$Rn, vecshiftR64:$imm)>;
def : Pat<(int_aarch64_neon_vcvtfxu2fp FPR32:$Rn, vecshiftR32:$imm),
(UCVTFs FPR32:$Rn, vecshiftR32:$imm)>;
def : Pat<(f64 (int_aarch64_neon_vcvtfxu2fp (i64 FPR64:$Rn), vecshiftR64:$imm)),
Expand Down Expand Up @@ -9186,26 +9213,6 @@ def : Pat<(f16 (int_aarch64_neon_vcvtfxu2fp FPR32:$Rn, vecshiftR16:$imm)),
(UCVTFh (f16 (EXTRACT_SUBREG FPR32:$Rn, hsub)), vecshiftR16:$imm)>;
def : Pat<(f16 (int_aarch64_neon_vcvtfxu2fp (i64 FPR64:$Rn), vecshiftR16:$imm)),
(UCVTFh (f16 (EXTRACT_SUBREG FPR64:$Rn, hsub)), vecshiftR16:$imm)>;
def : Pat<(i32 (int_aarch64_neon_vcvtfp2fxs (f16 FPR16:$Rn), vecshiftR32:$imm)),
(i32 (INSERT_SUBREG
(i32 (IMPLICIT_DEF)),
(FCVTZSh FPR16:$Rn, vecshiftR32:$imm),
hsub))>;
def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxs (f16 FPR16:$Rn), vecshiftR64:$imm)),
(i64 (INSERT_SUBREG
(i64 (IMPLICIT_DEF)),
(FCVTZSh FPR16:$Rn, vecshiftR64:$imm),
hsub))>;
def : Pat<(i32 (int_aarch64_neon_vcvtfp2fxu (f16 FPR16:$Rn), vecshiftR32:$imm)),
(i32 (INSERT_SUBREG
(i32 (IMPLICIT_DEF)),
(FCVTZUh FPR16:$Rn, vecshiftR32:$imm),
hsub))>;
def : Pat<(i64 (int_aarch64_neon_vcvtfp2fxu (f16 FPR16:$Rn), vecshiftR64:$imm)),
(i64 (INSERT_SUBREG
(i64 (IMPLICIT_DEF)),
(FCVTZUh FPR16:$Rn, vecshiftR64:$imm),
hsub))>;
def : Pat<(i32 (int_aarch64_neon_facge (f16 FPR16:$Rn), (f16 FPR16:$Rm))),
(i32 (INSERT_SUBREG
(i32 (IMPLICIT_DEF)),
Expand Down
78 changes: 78 additions & 0 deletions llvm/test/CodeGen/AArch64/neon-scalar-vcvtfp2fx.ll
Original file line number Diff line number Diff line change
@@ -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_i32_f32(float %a) {
; CHECK-LABEL: vcvtfp2fxs_i32_f32:
; 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_i32_f32_bitcast(float %a) {
; CHECK-LABEL: vcvtfp2fxs_i32_f32_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_i32_f32(float %a) {
; CHECK-LABEL: vcvtfp2fxu_i32_f32:
; 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_i32_f32_bitcast(float %a) {
; CHECK-LABEL: vcvtfp2fxu_i32_f32_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_i64_f64(double %a) {
; CHECK-LABEL: vcvtfp2fxs_i64_f64:
; 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_i64_f64_bitcast(double %a) {
; CHECK-LABEL: vcvtfp2fxs_i64_f64_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_i64_f64(double %a) {
; CHECK-LABEL: vcvtfp2fxu_i64_f64:
; 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_i64_f64_bitcast(double %a) {
; CHECK-LABEL: vcvtfp2fxu_i64_f64_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
}
Loading