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
742 lines
21 KiB
LLVM
742 lines
21 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
|
|
; RUN: -target-abi=ilp32d | FileCheck -check-prefixes=CHECKIFD,RV32IFD %s
|
|
; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
|
|
; RUN: -target-abi=lp64d | FileCheck -check-prefixes=CHECKIFD,RV64IFD %s
|
|
|
|
define signext i8 @test_floor_si8(double %x) {
|
|
; RV32IFD-LABEL: test_floor_si8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rdn
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_si8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptosi double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define signext i16 @test_floor_si16(double %x) {
|
|
; RV32IFD-LABEL: test_floor_si16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rdn
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_si16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptosi double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_floor_si32(double %x) {
|
|
; CHECKIFD-LABEL: test_floor_si32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rdn
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptosi double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_floor_si64(double %x) {
|
|
; RV32IFD-LABEL: test_floor_si64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call floor@plt
|
|
; RV32IFD-NEXT: call __fixdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_si64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptosi double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define zeroext i8 @test_floor_ui8(double %x) {
|
|
; RV32IFD-LABEL: test_floor_ui8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rdn
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_ui8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptoui double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define zeroext i16 @test_floor_ui16(double %x) {
|
|
; RV32IFD-LABEL: test_floor_ui16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rdn
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_ui16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptoui double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_floor_ui32(double %x) {
|
|
; CHECKIFD-LABEL: test_floor_ui32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rdn
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptoui double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_floor_ui64(double %x) {
|
|
; RV32IFD-LABEL: test_floor_ui64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call floor@plt
|
|
; RV32IFD-NEXT: call __fixunsdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_floor_ui64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
%b = fptoui double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i8 @test_ceil_si8(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_si8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rup
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_si8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptosi double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define signext i16 @test_ceil_si16(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_si16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rup
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_si16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptosi double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_ceil_si32(double %x) {
|
|
; CHECKIFD-LABEL: test_ceil_si32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rup
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptosi double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_ceil_si64(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_si64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call ceil@plt
|
|
; RV32IFD-NEXT: call __fixdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_si64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptosi double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define zeroext i8 @test_ceil_ui8(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_ui8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rup
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_ui8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptoui double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define zeroext i16 @test_ceil_ui16(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_ui16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rup
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_ui16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptoui double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_ceil_ui32(double %x) {
|
|
; CHECKIFD-LABEL: test_ceil_ui32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rup
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptoui double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_ceil_ui64(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_ui64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call ceil@plt
|
|
; RV32IFD-NEXT: call __fixunsdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_ui64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rup
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
%b = fptoui double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i8 @test_trunc_si8(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_si8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rtz
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_si8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptosi double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define signext i16 @test_trunc_si16(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_si16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rtz
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_si16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptosi double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_trunc_si32(double %x) {
|
|
; CHECKIFD-LABEL: test_trunc_si32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rtz
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptosi double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_trunc_si64(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_si64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call trunc@plt
|
|
; RV32IFD-NEXT: call __fixdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_si64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptosi double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define zeroext i8 @test_trunc_ui8(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_ui8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rtz
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_ui8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptoui double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define zeroext i16 @test_trunc_ui16(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_ui16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rtz
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_ui16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptoui double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_trunc_ui32(double %x) {
|
|
; CHECKIFD-LABEL: test_trunc_ui32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rtz
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptoui double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_trunc_ui64(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_ui64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call trunc@plt
|
|
; RV32IFD-NEXT: call __fixunsdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_ui64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
%b = fptoui double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i8 @test_round_si8(double %x) {
|
|
; RV32IFD-LABEL: test_round_si8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rmm
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_si8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptosi double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define signext i16 @test_round_si16(double %x) {
|
|
; RV32IFD-LABEL: test_round_si16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rmm
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_si16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptosi double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_round_si32(double %x) {
|
|
; CHECKIFD-LABEL: test_round_si32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rmm
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptosi double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_round_si64(double %x) {
|
|
; RV32IFD-LABEL: test_round_si64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call round@plt
|
|
; RV32IFD-NEXT: call __fixdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_si64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptosi double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define zeroext i8 @test_round_ui8(double %x) {
|
|
; RV32IFD-LABEL: test_round_ui8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rmm
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_ui8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptoui double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define zeroext i16 @test_round_ui16(double %x) {
|
|
; RV32IFD-LABEL: test_round_ui16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rmm
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_ui16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptoui double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_round_ui32(double %x) {
|
|
; CHECKIFD-LABEL: test_round_ui32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rmm
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptoui double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_round_ui64(double %x) {
|
|
; RV32IFD-LABEL: test_round_ui64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call round@plt
|
|
; RV32IFD-NEXT: call __fixunsdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_round_ui64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
%b = fptoui double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define signext i8 @test_roundeven_si8(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_si8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rne
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_si8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptosi double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define signext i16 @test_roundeven_si16(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_si16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.w.d a0, fa0, rne
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_si16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptosi double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_roundeven_si32(double %x) {
|
|
; CHECKIFD-LABEL: test_roundeven_si32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.w.d a0, fa0, rne
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptosi double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_roundeven_si64(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_si64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call roundeven@plt
|
|
; RV32IFD-NEXT: call __fixdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_si64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptosi double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define zeroext i8 @test_roundeven_ui8(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_ui8:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rne
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_ui8:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptoui double %a to i8
|
|
ret i8 %b
|
|
}
|
|
|
|
define zeroext i16 @test_roundeven_ui16(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_ui16:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: fcvt.wu.d a0, fa0, rne
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_ui16:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptoui double %a to i16
|
|
ret i16 %b
|
|
}
|
|
|
|
define signext i32 @test_roundeven_ui32(double %x) {
|
|
; CHECKIFD-LABEL: test_roundeven_ui32:
|
|
; CHECKIFD: # %bb.0:
|
|
; CHECKIFD-NEXT: fcvt.wu.d a0, fa0, rne
|
|
; CHECKIFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptoui double %a to i32
|
|
ret i32 %b
|
|
}
|
|
|
|
define i64 @test_roundeven_ui64(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_ui64:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: addi sp, sp, -16
|
|
; RV32IFD-NEXT: .cfi_def_cfa_offset 16
|
|
; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
|
|
; RV32IFD-NEXT: .cfi_offset ra, -4
|
|
; RV32IFD-NEXT: call roundeven@plt
|
|
; RV32IFD-NEXT: call __fixunsdfdi@plt
|
|
; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
|
|
; RV32IFD-NEXT: addi sp, sp, 16
|
|
; RV32IFD-NEXT: ret
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_ui64:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: fcvt.lu.d a0, fa0, rne
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
%b = fptoui double %a to i64
|
|
ret i64 %b
|
|
}
|
|
|
|
define double @test_floor_double(double %x) {
|
|
; RV32IFD-LABEL: test_floor_double:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: tail floor@plt
|
|
;
|
|
; RV64IFD-LABEL: test_floor_double:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: lui a0, %hi(.LCPI40_0)
|
|
; RV64IFD-NEXT: fld ft0, %lo(.LCPI40_0)(a0)
|
|
; RV64IFD-NEXT: fabs.d ft1, fa0
|
|
; RV64IFD-NEXT: flt.d a0, ft1, ft0
|
|
; RV64IFD-NEXT: beqz a0, .LBB40_2
|
|
; RV64IFD-NEXT: # %bb.1:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rdn
|
|
; RV64IFD-NEXT: fcvt.d.l ft0, a0, rdn
|
|
; RV64IFD-NEXT: fsgnj.d fa0, ft0, fa0
|
|
; RV64IFD-NEXT: .LBB40_2:
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.floor.f64(double %x)
|
|
ret double %a
|
|
}
|
|
|
|
define double @test_ceil_double(double %x) {
|
|
; RV32IFD-LABEL: test_ceil_double:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: tail ceil@plt
|
|
;
|
|
; RV64IFD-LABEL: test_ceil_double:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: lui a0, %hi(.LCPI41_0)
|
|
; RV64IFD-NEXT: fld ft0, %lo(.LCPI41_0)(a0)
|
|
; RV64IFD-NEXT: fabs.d ft1, fa0
|
|
; RV64IFD-NEXT: flt.d a0, ft1, ft0
|
|
; RV64IFD-NEXT: beqz a0, .LBB41_2
|
|
; RV64IFD-NEXT: # %bb.1:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rup
|
|
; RV64IFD-NEXT: fcvt.d.l ft0, a0, rup
|
|
; RV64IFD-NEXT: fsgnj.d fa0, ft0, fa0
|
|
; RV64IFD-NEXT: .LBB41_2:
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.ceil.f64(double %x)
|
|
ret double %a
|
|
}
|
|
|
|
define double @test_trunc_double(double %x) {
|
|
; RV32IFD-LABEL: test_trunc_double:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: tail trunc@plt
|
|
;
|
|
; RV64IFD-LABEL: test_trunc_double:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: lui a0, %hi(.LCPI42_0)
|
|
; RV64IFD-NEXT: fld ft0, %lo(.LCPI42_0)(a0)
|
|
; RV64IFD-NEXT: fabs.d ft1, fa0
|
|
; RV64IFD-NEXT: flt.d a0, ft1, ft0
|
|
; RV64IFD-NEXT: beqz a0, .LBB42_2
|
|
; RV64IFD-NEXT: # %bb.1:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rtz
|
|
; RV64IFD-NEXT: fcvt.d.l ft0, a0, rtz
|
|
; RV64IFD-NEXT: fsgnj.d fa0, ft0, fa0
|
|
; RV64IFD-NEXT: .LBB42_2:
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.trunc.f64(double %x)
|
|
ret double %a
|
|
}
|
|
|
|
define double @test_round_double(double %x) {
|
|
; RV32IFD-LABEL: test_round_double:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: tail round@plt
|
|
;
|
|
; RV64IFD-LABEL: test_round_double:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: lui a0, %hi(.LCPI43_0)
|
|
; RV64IFD-NEXT: fld ft0, %lo(.LCPI43_0)(a0)
|
|
; RV64IFD-NEXT: fabs.d ft1, fa0
|
|
; RV64IFD-NEXT: flt.d a0, ft1, ft0
|
|
; RV64IFD-NEXT: beqz a0, .LBB43_2
|
|
; RV64IFD-NEXT: # %bb.1:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rmm
|
|
; RV64IFD-NEXT: fcvt.d.l ft0, a0, rmm
|
|
; RV64IFD-NEXT: fsgnj.d fa0, ft0, fa0
|
|
; RV64IFD-NEXT: .LBB43_2:
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.round.f64(double %x)
|
|
ret double %a
|
|
}
|
|
|
|
define double @test_roundeven_double(double %x) {
|
|
; RV32IFD-LABEL: test_roundeven_double:
|
|
; RV32IFD: # %bb.0:
|
|
; RV32IFD-NEXT: tail roundeven@plt
|
|
;
|
|
; RV64IFD-LABEL: test_roundeven_double:
|
|
; RV64IFD: # %bb.0:
|
|
; RV64IFD-NEXT: lui a0, %hi(.LCPI44_0)
|
|
; RV64IFD-NEXT: fld ft0, %lo(.LCPI44_0)(a0)
|
|
; RV64IFD-NEXT: fabs.d ft1, fa0
|
|
; RV64IFD-NEXT: flt.d a0, ft1, ft0
|
|
; RV64IFD-NEXT: beqz a0, .LBB44_2
|
|
; RV64IFD-NEXT: # %bb.1:
|
|
; RV64IFD-NEXT: fcvt.l.d a0, fa0, rne
|
|
; RV64IFD-NEXT: fcvt.d.l ft0, a0, rne
|
|
; RV64IFD-NEXT: fsgnj.d fa0, ft0, fa0
|
|
; RV64IFD-NEXT: .LBB44_2:
|
|
; RV64IFD-NEXT: ret
|
|
%a = call double @llvm.roundeven.f64(double %x)
|
|
ret double %a
|
|
}
|
|
|
|
declare double @llvm.floor.f64(double)
|
|
declare double @llvm.ceil.f64(double)
|
|
declare double @llvm.trunc.f64(double)
|
|
declare double @llvm.round.f64(double)
|
|
declare double @llvm.roundeven.f64(double)
|