This avoids the call overhead as well as the the save/restore of fflags and the snan handling in the libm function. The save/restore of fflags and snan handling are needed to be correct for -ftrapping-math. I think we can ignore them in the default environment. The inline sequence will generate an invalid exception for nan and an inexact exception if fractional bits are discarded. I've used a custom inserter to explicitly create the control flow around the float->int->float conversion. We can probably avoid the final fsgnj after the conversion for no signed zeros FMF, but I'll leave that for future work. Note the comparison constant is slightly different than glibc uses. They use 1<<53 for double, I'm using 1<<52. I believe either are valid. Numbers >= 1<<52 can't have any fractional bits. It's ok to do the float->int->float conversion on numbers between 1<<53 and 1<<52 since they will all fit in 64. We only have a problem if the double can't fit in i64 Reviewed By: reames Differential Revision: https://reviews.llvm.org/D136508
721 lines
24 KiB
LLVM
721 lines
24 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \
|
|
; RUN: -target-abi=ilp32f | FileCheck -check-prefixes=CHECKIF,RV32IF %s
|
|
; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \
|
|
; RUN: -target-abi=lp64f | FileCheck -check-prefixes=CHECKIF,RV64IF %s
|
|
|
|
define signext i32 @test_floor_si32(float %x) {
|
|
; CHECKIF-LABEL: test_floor_si32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.w.s a0, fa0, rdn
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.floor.f32(float %x)
|
|
%b = call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_floor_si64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_floor_si64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI1_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI1_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB1_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rdn
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rdn
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB1_2:
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI1_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI1_1)(a0)
|
|
; RV32IF-NEXT: fle.s s0, ft0, fs0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lui a3, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB1_4
|
|
; RV32IF-NEXT: # %bb.3:
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: .LBB1_4:
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI1_2)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI1_2)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: beqz a2, .LBB1_6
|
|
; RV32IF-NEXT: # %bb.5:
|
|
; RV32IF-NEXT: addi a1, a3, -1
|
|
; RV32IF-NEXT: .LBB1_6:
|
|
; RV32IF-NEXT: feq.s a3, fs0, fs0
|
|
; RV32IF-NEXT: seqz a3, a3
|
|
; RV32IF-NEXT: addi a3, a3, -1
|
|
; RV32IF-NEXT: and a1, a3, a1
|
|
; RV32IF-NEXT: neg a4, s0
|
|
; RV32IF-NEXT: and a0, a4, a0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a0, a3, a0
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_floor_si64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.l.s a0, fa0, rdn
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.floor.f32(float %x)
|
|
%b = call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_floor_ui32(float %x) {
|
|
; CHECKIF-LABEL: test_floor_ui32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.wu.s a0, fa0, rdn
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.floor.f32(float %x)
|
|
%b = call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_floor_ui64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_floor_ui64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI3_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI3_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB3_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rdn
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rdn
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB3_2:
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fle.s a0, ft0, fs0
|
|
; RV32IF-NEXT: neg s0, a0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI3_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI3_1)(a2)
|
|
; RV32IF-NEXT: and a0, s0, a0
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a1, s0, a1
|
|
; RV32IF-NEXT: or a1, a2, a1
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_floor_ui64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, fa0, rdn
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.floor.f32(float %x)
|
|
%b = call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_ceil_si32(float %x) {
|
|
; CHECKIF-LABEL: test_ceil_si32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.w.s a0, fa0, rup
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.ceil.f32(float %x)
|
|
%b = call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_ceil_si64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_ceil_si64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI5_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI5_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB5_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rup
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rup
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB5_2:
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI5_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI5_1)(a0)
|
|
; RV32IF-NEXT: fle.s s0, ft0, fs0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lui a3, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB5_4
|
|
; RV32IF-NEXT: # %bb.3:
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: .LBB5_4:
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI5_2)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI5_2)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: beqz a2, .LBB5_6
|
|
; RV32IF-NEXT: # %bb.5:
|
|
; RV32IF-NEXT: addi a1, a3, -1
|
|
; RV32IF-NEXT: .LBB5_6:
|
|
; RV32IF-NEXT: feq.s a3, fs0, fs0
|
|
; RV32IF-NEXT: seqz a3, a3
|
|
; RV32IF-NEXT: addi a3, a3, -1
|
|
; RV32IF-NEXT: and a1, a3, a1
|
|
; RV32IF-NEXT: neg a4, s0
|
|
; RV32IF-NEXT: and a0, a4, a0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a0, a3, a0
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_ceil_si64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.l.s a0, fa0, rup
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.ceil.f32(float %x)
|
|
%b = call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_ceil_ui32(float %x) {
|
|
; CHECKIF-LABEL: test_ceil_ui32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.wu.s a0, fa0, rup
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.ceil.f32(float %x)
|
|
%b = call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_ceil_ui64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_ceil_ui64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI7_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI7_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB7_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rup
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rup
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB7_2:
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fle.s a0, ft0, fs0
|
|
; RV32IF-NEXT: neg s0, a0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI7_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI7_1)(a2)
|
|
; RV32IF-NEXT: and a0, s0, a0
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a1, s0, a1
|
|
; RV32IF-NEXT: or a1, a2, a1
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_ceil_ui64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, fa0, rup
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.ceil.f32(float %x)
|
|
%b = call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_trunc_si32(float %x) {
|
|
; CHECKIF-LABEL: test_trunc_si32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.w.s a0, fa0, rtz
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.trunc.f32(float %x)
|
|
%b = call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_trunc_si64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_trunc_si64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI9_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI9_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB9_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rtz
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rtz
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB9_2:
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI9_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI9_1)(a0)
|
|
; RV32IF-NEXT: fle.s s0, ft0, fs0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lui a3, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB9_4
|
|
; RV32IF-NEXT: # %bb.3:
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: .LBB9_4:
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI9_2)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI9_2)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: beqz a2, .LBB9_6
|
|
; RV32IF-NEXT: # %bb.5:
|
|
; RV32IF-NEXT: addi a1, a3, -1
|
|
; RV32IF-NEXT: .LBB9_6:
|
|
; RV32IF-NEXT: feq.s a3, fs0, fs0
|
|
; RV32IF-NEXT: seqz a3, a3
|
|
; RV32IF-NEXT: addi a3, a3, -1
|
|
; RV32IF-NEXT: and a1, a3, a1
|
|
; RV32IF-NEXT: neg a4, s0
|
|
; RV32IF-NEXT: and a0, a4, a0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a0, a3, a0
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_trunc_si64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.l.s a0, fa0, rtz
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.trunc.f32(float %x)
|
|
%b = call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_trunc_ui32(float %x) {
|
|
; CHECKIF-LABEL: test_trunc_ui32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.wu.s a0, fa0, rtz
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.trunc.f32(float %x)
|
|
%b = call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_trunc_ui64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_trunc_ui64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI11_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI11_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB11_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rtz
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rtz
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB11_2:
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fle.s a0, ft0, fs0
|
|
; RV32IF-NEXT: neg s0, a0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI11_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI11_1)(a2)
|
|
; RV32IF-NEXT: and a0, s0, a0
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a1, s0, a1
|
|
; RV32IF-NEXT: or a1, a2, a1
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_trunc_ui64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, fa0, rtz
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.trunc.f32(float %x)
|
|
%b = call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_round_si32(float %x) {
|
|
; CHECKIF-LABEL: test_round_si32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.w.s a0, fa0, rmm
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.round.f32(float %x)
|
|
%b = call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_round_si64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_round_si64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI13_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI13_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB13_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rmm
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rmm
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB13_2:
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI13_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI13_1)(a0)
|
|
; RV32IF-NEXT: fle.s s0, ft0, fs0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lui a3, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB13_4
|
|
; RV32IF-NEXT: # %bb.3:
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: .LBB13_4:
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI13_2)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI13_2)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: beqz a2, .LBB13_6
|
|
; RV32IF-NEXT: # %bb.5:
|
|
; RV32IF-NEXT: addi a1, a3, -1
|
|
; RV32IF-NEXT: .LBB13_6:
|
|
; RV32IF-NEXT: feq.s a3, fs0, fs0
|
|
; RV32IF-NEXT: seqz a3, a3
|
|
; RV32IF-NEXT: addi a3, a3, -1
|
|
; RV32IF-NEXT: and a1, a3, a1
|
|
; RV32IF-NEXT: neg a4, s0
|
|
; RV32IF-NEXT: and a0, a4, a0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a0, a3, a0
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_round_si64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.l.s a0, fa0, rmm
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.round.f32(float %x)
|
|
%b = call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_round_ui32(float %x) {
|
|
; CHECKIF-LABEL: test_round_ui32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.wu.s a0, fa0, rmm
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.round.f32(float %x)
|
|
%b = call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_round_ui64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_round_ui64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI15_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI15_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB15_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rmm
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rmm
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB15_2:
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fle.s a0, ft0, fs0
|
|
; RV32IF-NEXT: neg s0, a0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI15_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI15_1)(a2)
|
|
; RV32IF-NEXT: and a0, s0, a0
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a1, s0, a1
|
|
; RV32IF-NEXT: or a1, a2, a1
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_round_ui64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, fa0, rmm
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.round.f32(float %x)
|
|
%b = call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_roundeven_si32(float %x) {
|
|
; CHECKIF-LABEL: test_roundeven_si32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.w.s a0, fa0, rne
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.roundeven.f32(float %x)
|
|
%b = call i32 @llvm.fptosi.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_roundeven_si64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_roundeven_si64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI17_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI17_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB17_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rne
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rne
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB17_2:
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI17_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI17_1)(a0)
|
|
; RV32IF-NEXT: fle.s s0, ft0, fs0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixsfdi@plt
|
|
; RV32IF-NEXT: lui a3, 524288
|
|
; RV32IF-NEXT: bnez s0, .LBB17_4
|
|
; RV32IF-NEXT: # %bb.3:
|
|
; RV32IF-NEXT: lui a1, 524288
|
|
; RV32IF-NEXT: .LBB17_4:
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI17_2)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI17_2)(a2)
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: beqz a2, .LBB17_6
|
|
; RV32IF-NEXT: # %bb.5:
|
|
; RV32IF-NEXT: addi a1, a3, -1
|
|
; RV32IF-NEXT: .LBB17_6:
|
|
; RV32IF-NEXT: feq.s a3, fs0, fs0
|
|
; RV32IF-NEXT: seqz a3, a3
|
|
; RV32IF-NEXT: addi a3, a3, -1
|
|
; RV32IF-NEXT: and a1, a3, a1
|
|
; RV32IF-NEXT: neg a4, s0
|
|
; RV32IF-NEXT: and a0, a4, a0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a0, a3, a0
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_roundeven_si64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.l.s a0, fa0, rne
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.roundeven.f32(float %x)
|
|
%b = call i64 @llvm.fptosi.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i32 @test_roundeven_ui32(float %x) {
|
|
; CHECKIF-LABEL: test_roundeven_ui32:
|
|
; CHECKIF: # %bb.0:
|
|
; CHECKIF-NEXT: fcvt.wu.s a0, fa0, rne
|
|
; CHECKIF-NEXT: feq.s a1, fa0, fa0
|
|
; CHECKIF-NEXT: seqz a1, a1
|
|
; CHECKIF-NEXT: addi a1, a1, -1
|
|
; CHECKIF-NEXT: and a0, a1, a0
|
|
; CHECKIF-NEXT: ret
|
|
%a = call float @llvm.roundeven.f32(float %x)
|
|
%b = call i32 @llvm.fptoui.sat.i32.f32(float %a)
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_roundeven_ui64(float %x) nounwind {
|
|
; RV32IF-LABEL: test_roundeven_ui64:
|
|
; RV32IF: # %bb.0:
|
|
; 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: fsw fs0, 4(sp) # 4-byte Folded Spill
|
|
; RV32IF-NEXT: lui a0, %hi(.LCPI19_0)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI19_0)(a0)
|
|
; RV32IF-NEXT: fmv.s fs0, fa0
|
|
; RV32IF-NEXT: fabs.s ft1, fa0
|
|
; RV32IF-NEXT: flt.s a0, ft1, ft0
|
|
; RV32IF-NEXT: beqz a0, .LBB19_2
|
|
; RV32IF-NEXT: # %bb.1:
|
|
; RV32IF-NEXT: fcvt.w.s a0, fs0, rne
|
|
; RV32IF-NEXT: fcvt.s.w ft0, a0, rne
|
|
; RV32IF-NEXT: fsgnj.s fs0, ft0, fs0
|
|
; RV32IF-NEXT: .LBB19_2:
|
|
; RV32IF-NEXT: fmv.w.x ft0, zero
|
|
; RV32IF-NEXT: fle.s a0, ft0, fs0
|
|
; RV32IF-NEXT: neg s0, a0
|
|
; RV32IF-NEXT: fmv.s fa0, fs0
|
|
; RV32IF-NEXT: call __fixunssfdi@plt
|
|
; RV32IF-NEXT: lui a2, %hi(.LCPI19_1)
|
|
; RV32IF-NEXT: flw ft0, %lo(.LCPI19_1)(a2)
|
|
; RV32IF-NEXT: and a0, s0, a0
|
|
; RV32IF-NEXT: flt.s a2, ft0, fs0
|
|
; RV32IF-NEXT: neg a2, a2
|
|
; RV32IF-NEXT: or a0, a2, a0
|
|
; RV32IF-NEXT: and a1, s0, a1
|
|
; RV32IF-NEXT: or a1, a2, a1
|
|
; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: flw fs0, 4(sp) # 4-byte Folded Reload
|
|
; RV32IF-NEXT: addi sp, sp, 16
|
|
; RV32IF-NEXT: ret
|
|
;
|
|
; RV64IF-LABEL: test_roundeven_ui64:
|
|
; RV64IF: # %bb.0:
|
|
; RV64IF-NEXT: fcvt.lu.s a0, fa0, rne
|
|
; RV64IF-NEXT: feq.s a1, fa0, fa0
|
|
; RV64IF-NEXT: seqz a1, a1
|
|
; RV64IF-NEXT: addi a1, a1, -1
|
|
; RV64IF-NEXT: and a0, a1, a0
|
|
; RV64IF-NEXT: ret
|
|
%a = call float @llvm.roundeven.f32(float %x)
|
|
%b = call i64 @llvm.fptoui.sat.i64.f32(float %a)
|
|
ret i64 %b
|
|
}
|
|
|
|
declare float @llvm.floor.f32(float)
|
|
declare float @llvm.ceil.f32(float)
|
|
declare float @llvm.trunc.f32(float)
|
|
declare float @llvm.round.f32(float)
|
|
declare float @llvm.roundeven.f32(float)
|
|
declare i32 @llvm.fptosi.sat.i32.f32(float)
|
|
declare i64 @llvm.fptosi.sat.i64.f32(float)
|
|
declare i32 @llvm.fptoui.sat.i32.f32(float)
|
|
declare i64 @llvm.fptoui.sat.i64.f32(float)
|