Add PromoteIntOp_FP_TO_XINT_SAT to type legalize the bit width operand from i32 to i64 for RV64. Add test cases for the saturating intrinsics for half/float/double and i32/i64. CodeGen is definitely not optimal. We can probably make use of the native behavior of fcvt instructions in many cases. Fixes PR50083
540 lines
16 KiB
LLVM
540 lines
16 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
|
|
; RUN: | FileCheck -check-prefix=RV32IF %s
|
|
; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
|
|
; RUN: | FileCheck -check-prefix=RV64IF %s
|
|
|
|
; For RV64F, fcvt.l.s is semantically equivalent to fcvt.w.s in this case
|
|
; because fptosi will produce poison if the result doesn't fit into an i32.
|
|
define i32 @fcvt_w_s(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_w_s:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fmv.w.x ft0, a0
|
|
; RV32IF-NEXT: fcvt.w.s a0, ft0, rtz
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_w_s:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
|
; RV64IF-NEXT: ret
|
|
%1 = fptosi float %a to i32
|
|
ret i32 %1
|
|
}
|
|
|
|
define i32 @fcvt_w_s_sat(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_w_s_sat:
|
|
; RV32IF: # %bb.0: # %start
|
|
; RV32IF-NEXT: lui a1, %hi(.LCPI1_0)
|
|
; RV32IF-NEXT: flw ft1, %lo(.LCPI1_0)(a1)
|
|
; RV32IF-NEXT: fmv.w.x ft0, a0
|
|
; RV32IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: bnez a0, .LBB1_2
|
|
; RV32IF-NEXT: # %bb.1: # %start
|
|
; RV32IF-NEXT: lui a0, 524288
|
|
; RV32IF-NEXT: j .LBB1_3
|
|
; RV32IF-NEXT: .LBB1_2:
|
|
; RV32IF-NEXT: fcvt.w.s a0, ft0, rtz
|
|
; RV32IF-NEXT: .LBB1_3: # %start
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI1_1)
|
|
; RV32IF-NEXT: flw ft1, %lo(.LCPI1_1)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft1, ft0
|
|
; RV32IF-NEXT: bnez a2, .LBB1_6
|
|
; RV32IF-NEXT: # %bb.4: # %start
|
|
; RV32IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV32IF-NEXT: beqz a1, .LBB1_7
|
|
; RV32IF-NEXT: .LBB1_5: # %start
|
|
; RV32IF-NEXT: ret
|
|
; RV32IF-NEXT: .LBB1_6:
|
|
; RV32IF-NEXT: addi a0, a1, -1
|
|
; RV32IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV32IF-NEXT: bnez a1, .LBB1_5
|
|
; RV32IF-NEXT: .LBB1_7: # %start
|
|
; RV32IF-NEXT: mv a0, zero
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_w_s_sat:
|
|
; RV64IF: # %bb.0: # %start
|
|
; RV64IF-NEXT: lui a1, %hi(.LCPI1_0)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI1_0)(a1)
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV64IF-NEXT: lui a1, 524288
|
|
; RV64IF-NEXT: bnez a0, .LBB1_2
|
|
; RV64IF-NEXT: # %bb.1: # %start
|
|
; RV64IF-NEXT: lui a0, 524288
|
|
; RV64IF-NEXT: j .LBB1_3
|
|
; RV64IF-NEXT: .LBB1_2:
|
|
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
|
; RV64IF-NEXT: .LBB1_3: # %start
|
|
; RV64IF-NEXT: lui a2, %hi(.LCPI1_1)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI1_1)(a2)
|
|
; RV64IF-NEXT: flt.s a2, ft1, ft0
|
|
; RV64IF-NEXT: bnez a2, .LBB1_6
|
|
; RV64IF-NEXT: # %bb.4: # %start
|
|
; RV64IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV64IF-NEXT: beqz a1, .LBB1_7
|
|
; RV64IF-NEXT: .LBB1_5: # %start
|
|
; RV64IF-NEXT: ret
|
|
; RV64IF-NEXT: .LBB1_6:
|
|
; RV64IF-NEXT: addiw a0, a1, -1
|
|
; RV64IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV64IF-NEXT: bnez a1, .LBB1_5
|
|
; RV64IF-NEXT: .LBB1_7: # %start
|
|
; RV64IF-NEXT: mv a0, zero
|
|
; RV64IF-NEXT: ret
|
|
start:
|
|
%0 = tail call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %0
|
|
}
|
|
declare i32 @llvm.fptosi.sat.i32.f32(float)
|
|
|
|
; For RV64F, fcvt.lu.s is semantically equivalent to fcvt.wu.s in this case
|
|
; because fptoui will produce poison if the result doesn't fit into an i32.
|
|
define i32 @fcvt_wu_s(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_wu_s:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fmv.w.x ft0, a0
|
|
; RV32IF-NEXT: fcvt.wu.s a0, ft0, rtz
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_wu_s:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
|
; RV64IF-NEXT: ret
|
|
%1 = fptoui float %a to i32
|
|
ret i32 %1
|
|
}
|
|
|
|
define i32 @fcvt_wu_s_sat(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_wu_s_sat:
|
|
; RV32IF: # %bb.0: # %start
|
|
; RV32IF-NEXT: fmv.w.x ft0, a0
|
|
; RV32IF-NEXT: fmv.w.x ft1, zero
|
|
; RV32IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV32IF-NEXT: bnez a0, .LBB3_2
|
|
; RV32IF-NEXT: # %bb.1: # %start
|
|
; RV32IF-NEXT: mv a1, zero
|
|
; RV32IF-NEXT: j .LBB3_3
|
|
; RV32IF-NEXT: .LBB3_2:
|
|
; RV32IF-NEXT: fcvt.wu.s a1, ft0, rtz
|
|
; RV32IF-NEXT: .LBB3_3: # %start
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI3_0)
|
|
; RV32IF-NEXT: flw ft1, %lo(.LCPI3_0)(a0)
|
|
; RV32IF-NEXT: flt.s a2, ft1, ft0
|
|
; RV32IF-NEXT: addi a0, zero, -1
|
|
; RV32IF-NEXT: bnez a2, .LBB3_5
|
|
; RV32IF-NEXT: # %bb.4: # %start
|
|
; RV32IF-NEXT: mv a0, a1
|
|
; RV32IF-NEXT: .LBB3_5: # %start
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_wu_s_sat:
|
|
; RV64IF: # %bb.0: # %start
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fmv.w.x ft1, zero
|
|
; RV64IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV64IF-NEXT: bnez a0, .LBB3_2
|
|
; RV64IF-NEXT: # %bb.1: # %start
|
|
; RV64IF-NEXT: mv a0, zero
|
|
; RV64IF-NEXT: j .LBB3_3
|
|
; RV64IF-NEXT: .LBB3_2:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
|
; RV64IF-NEXT: .LBB3_3: # %start
|
|
; RV64IF-NEXT: lui a1, %hi(.LCPI3_0)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI3_0)(a1)
|
|
; RV64IF-NEXT: flt.s a1, ft1, ft0
|
|
; RV64IF-NEXT: beqz a1, .LBB3_5
|
|
; RV64IF-NEXT: # %bb.4:
|
|
; RV64IF-NEXT: addi a0, zero, -1
|
|
; RV64IF-NEXT: srli a0, a0, 32
|
|
; RV64IF-NEXT: .LBB3_5: # %start
|
|
; RV64IF-NEXT: ret
|
|
start:
|
|
%0 = tail call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %0
|
|
}
|
|
declare i32 @llvm.fptoui.sat.i32.f32(float)
|
|
|
|
define i32 @fmv_x_w(float %a, float %b) nounwind {
|
|
; RV32IF-LABEL: fmv_x_w:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fmv.w.x ft0, a1
|
|
; RV32IF-NEXT: fmv.w.x ft1, a0
|
|
; RV32IF-NEXT: fadd.s ft0, ft1, ft0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fmv_x_w:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a1
|
|
; RV64IF-NEXT: fmv.w.x ft1, a0
|
|
; RV64IF-NEXT: fadd.s ft0, ft1, ft0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
; Ensure fmv.x.w is generated even for a soft float calling convention
|
|
%1 = fadd float %a, %b
|
|
%2 = bitcast float %1 to i32
|
|
ret i32 %2
|
|
}
|
|
|
|
define float @fcvt_s_w(i32 %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_w:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_w:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = sitofp i32 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_wu(i32 %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_wu:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_wu:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = uitofp i32 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fmv_w_x(i32 %a, i32 %b) nounwind {
|
|
; RV32IF-LABEL: fmv_w_x:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fmv.w.x ft0, a0
|
|
; RV32IF-NEXT: fmv.w.x ft1, a1
|
|
; RV32IF-NEXT: fadd.s ft0, ft0, ft1
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fmv_w_x:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fmv.w.x ft1, a1
|
|
; RV64IF-NEXT: fadd.s ft0, ft0, ft1
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
; Ensure fmv.w.x is generated even for a soft float calling convention
|
|
%1 = bitcast i32 %a to float
|
|
%2 = bitcast i32 %b to float
|
|
%3 = fadd float %1, %2
|
|
ret float %3
|
|
}
|
|
|
|
define i64 @fcvt_l_s(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_l_s:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_l_s:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
|
; RV64IF-NEXT: ret
|
|
%1 = fptosi float %a to i64
|
|
ret i64 %1
|
|
}
|
|
|
|
define i64 @fcvt_l_s_sat(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_l_s_sat:
|
|
; RV32IF: # %bb.0: # %start
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a1, %hi(.LCPI9_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI9_0)(a1)
|
|
; RV32IF-NEXT: fmv.w.x ft1, a0
|
|
; RV32IF-NEXT: fsw ft1, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: fle.s s0, ft0, ft1
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: mv a2, a0
|
|
; RV32IF-NEXT: bnez s0, .LBB9_2
|
|
; RV32IF-NEXT: # %bb.1: # %start
|
|
; RV32IF-NEXT: mv a2, zero
|
|
; RV32IF-NEXT: .LBB9_2: # %start
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI9_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI9_1)(a0)
|
|
; RV32IF-NEXT: flw ft1, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flt.s a3, ft0, ft1
|
|
; RV32IF-NEXT: fmv.s ft0, ft1
|
|
; RV32IF-NEXT: addi a0, zero, -1
|
|
; RV32IF-NEXT: beqz a3, .LBB9_9
|
|
; RV32IF-NEXT: # %bb.3: # %start
|
|
; RV32IF-NEXT: feq.s a2, ft0, ft0
|
|
; RV32IF-NEXT: beqz a2, .LBB9_10
|
|
; RV32IF-NEXT: .LBB9_4: # %start
|
|
; RV32IF-NEXT: lui a4, 524288
|
|
; RV32IF-NEXT: beqz s0, .LBB9_11
|
|
; RV32IF-NEXT: .LBB9_5: # %start
|
|
; RV32IF-NEXT: bnez a3, .LBB9_12
|
|
; RV32IF-NEXT: .LBB9_6: # %start
|
|
; RV32IF-NEXT: bnez a2, .LBB9_8
|
|
; RV32IF-NEXT: .LBB9_7: # %start
|
|
; RV32IF-NEXT: mv a1, zero
|
|
; RV32IF-NEXT: .LBB9_8: # %start
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
; RV32IF-NEXT: .LBB9_9: # %start
|
|
; RV32IF-NEXT: mv a0, a2
|
|
; RV32IF-NEXT: feq.s a2, ft0, ft0
|
|
; RV32IF-NEXT: bnez a2, .LBB9_4
|
|
; RV32IF-NEXT: .LBB9_10: # %start
|
|
; RV32IF-NEXT: mv a0, zero
|
|
; RV32IF-NEXT: lui a4, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB9_5
|
|
; RV32IF-NEXT: .LBB9_11: # %start
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: beqz a3, .LBB9_6
|
|
; RV32IF-NEXT: .LBB9_12:
|
|
; RV32IF-NEXT: addi a1, a4, -1
|
|
; RV32IF-NEXT: beqz a2, .LBB9_7
|
|
; RV32IF-NEXT: j .LBB9_8
|
|
;
|
|
; RV64IF-LABEL: fcvt_l_s_sat:
|
|
; RV64IF: # %bb.0: # %start
|
|
; RV64IF-NEXT: lui a1, %hi(.LCPI9_0)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI9_0)(a1)
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV64IF-NEXT: addi a1, zero, -1
|
|
; RV64IF-NEXT: bnez a0, .LBB9_2
|
|
; RV64IF-NEXT: # %bb.1: # %start
|
|
; RV64IF-NEXT: slli a0, a1, 63
|
|
; RV64IF-NEXT: j .LBB9_3
|
|
; RV64IF-NEXT: .LBB9_2:
|
|
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
|
; RV64IF-NEXT: .LBB9_3: # %start
|
|
; RV64IF-NEXT: lui a2, %hi(.LCPI9_1)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI9_1)(a2)
|
|
; RV64IF-NEXT: flt.s a2, ft1, ft0
|
|
; RV64IF-NEXT: bnez a2, .LBB9_6
|
|
; RV64IF-NEXT: # %bb.4: # %start
|
|
; RV64IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV64IF-NEXT: beqz a1, .LBB9_7
|
|
; RV64IF-NEXT: .LBB9_5: # %start
|
|
; RV64IF-NEXT: ret
|
|
; RV64IF-NEXT: .LBB9_6:
|
|
; RV64IF-NEXT: srli a0, a1, 1
|
|
; RV64IF-NEXT: feq.s a1, ft0, ft0
|
|
; RV64IF-NEXT: bnez a1, .LBB9_5
|
|
; RV64IF-NEXT: .LBB9_7: # %start
|
|
; RV64IF-NEXT: mv a0, zero
|
|
; RV64IF-NEXT: ret
|
|
start:
|
|
%0 = tail call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %0
|
|
}
|
|
declare i64 @llvm.fptosi.sat.i64.f32(float)
|
|
|
|
define i64 @fcvt_lu_s(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_lu_s:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_lu_s:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
|
; RV64IF-NEXT: ret
|
|
%1 = fptoui float %a to i64
|
|
ret i64 %1
|
|
}
|
|
|
|
define i64 @fcvt_lu_s_sat(float %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_lu_s_sat:
|
|
; RV32IF: # %bb.0: # %start
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: fmv.w.x ft1, a0
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fsw ft1, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: fle.s s0, ft0, ft1
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: mv a3, a0
|
|
; RV32IF-NEXT: bnez s0, .LBB11_2
|
|
; RV32IF-NEXT: # %bb.1: # %start
|
|
; RV32IF-NEXT: mv a3, zero
|
|
; RV32IF-NEXT: .LBB11_2: # %start
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI11_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI11_0)(a0)
|
|
; RV32IF-NEXT: flw ft1, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flt.s a4, ft0, ft1
|
|
; RV32IF-NEXT: addi a2, zero, -1
|
|
; RV32IF-NEXT: addi a0, zero, -1
|
|
; RV32IF-NEXT: beqz a4, .LBB11_7
|
|
; RV32IF-NEXT: # %bb.3: # %start
|
|
; RV32IF-NEXT: beqz s0, .LBB11_8
|
|
; RV32IF-NEXT: .LBB11_4: # %start
|
|
; RV32IF-NEXT: bnez a4, .LBB11_6
|
|
; RV32IF-NEXT: .LBB11_5: # %start
|
|
; RV32IF-NEXT: mv a2, a1
|
|
; RV32IF-NEXT: .LBB11_6: # %start
|
|
; RV32IF-NEXT: mv a1, a2
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
; RV32IF-NEXT: .LBB11_7: # %start
|
|
; RV32IF-NEXT: mv a0, a3
|
|
; RV32IF-NEXT: bnez s0, .LBB11_4
|
|
; RV32IF-NEXT: .LBB11_8: # %start
|
|
; RV32IF-NEXT: mv a1, zero
|
|
; RV32IF-NEXT: beqz a4, .LBB11_5
|
|
; RV32IF-NEXT: j .LBB11_6
|
|
;
|
|
; RV64IF-LABEL: fcvt_lu_s_sat:
|
|
; RV64IF: # %bb.0: # %start
|
|
; RV64IF-NEXT: fmv.w.x ft0, a0
|
|
; RV64IF-NEXT: fmv.w.x ft1, zero
|
|
; RV64IF-NEXT: fle.s a0, ft1, ft0
|
|
; RV64IF-NEXT: bnez a0, .LBB11_2
|
|
; RV64IF-NEXT: # %bb.1: # %start
|
|
; RV64IF-NEXT: mv a1, zero
|
|
; RV64IF-NEXT: j .LBB11_3
|
|
; RV64IF-NEXT: .LBB11_2:
|
|
; RV64IF-NEXT: fcvt.lu.s a1, ft0, rtz
|
|
; RV64IF-NEXT: .LBB11_3: # %start
|
|
; RV64IF-NEXT: lui a0, %hi(.LCPI11_0)
|
|
; RV64IF-NEXT: flw ft1, %lo(.LCPI11_0)(a0)
|
|
; RV64IF-NEXT: flt.s a2, ft1, ft0
|
|
; RV64IF-NEXT: addi a0, zero, -1
|
|
; RV64IF-NEXT: bnez a2, .LBB11_5
|
|
; RV64IF-NEXT: # %bb.4: # %start
|
|
; RV64IF-NEXT: mv a0, a1
|
|
; RV64IF-NEXT: .LBB11_5: # %start
|
|
; RV64IF-NEXT: ret
|
|
start:
|
|
%0 = tail call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %0
|
|
}
|
|
declare i64 @llvm.fptoui.sat.i64.f32(float)
|
|
|
|
define float @fcvt_s_l(i64 %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_l:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: call __floatdisf@plt
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_l:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.l ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = sitofp i64 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_lu(i64 %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_lu:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: addi sp, sp, -16
|
|
; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: call __floatundisf@plt
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_lu:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.lu ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = uitofp i64 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_w_i8(i8 signext %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_w_i8:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_w_i8:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = sitofp i8 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_wu_i8(i8 zeroext %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_wu_i8:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_wu_i8:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = uitofp i8 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_w_i16(i16 signext %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_w_i16:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_w_i16:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.w ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = sitofp i16 %a to float
|
|
ret float %1
|
|
}
|
|
|
|
define float @fcvt_s_wu_i16(i16 zeroext %a) nounwind {
|
|
; RV32IF-LABEL: fcvt_s_wu_i16:
|
|
; RV32IF: # %bb.0:
|
|
; RV32IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV32IF-NEXT: fmv.x.w a0, ft0
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: fcvt_s_wu_i16:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.s.wu ft0, a0
|
|
; RV64IF-NEXT: fmv.x.w a0, ft0
|
|
; RV64IF-NEXT: ret
|
|
%1 = uitofp i16 %a to float
|
|
ret float %1
|
|
}
|