mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
9f472d8e96
Fix several several additional problems with the int <-> FP conversion logic both in common code and in the X86 target. In particular: - The STRICT_FP_TO_UINT expansion emits a floating-point compare. This compare can raise exceptions and therefore needs to be a strict compare. I've made it signaling (even though quiet would also be correct) as signaling is the more usual default for an LT. This code exists both in common code and in the X86 target. - The STRICT_UINT_TO_FP expansion algorithm was incorrect for strict mode: it emitted two STRICT_SINT_TO_FP nodes and then used a select to choose one of the results. This can cause spurious exceptions by the STRICT_SINT_TO_FP that ends up not chosen. I've fixed the algorithm to use only a single STRICT_SINT_TO_FP instead. - The !isStrictFPEnabled logic in DoInstructionSelection would sometimes do the wrong thing because it calls getOperationAction using the result VT. But for some opcodes, incuding [SU]INT_TO_FP, getOperationAction needs to be called using the operand VT. - Remove some (obsolete) code in X86DAGToDAGISel::Select that would mutate STRICT_FP_TO_[SU]INT to non-strict versions unnecessarily. Reviewed by: craig.topper Differential Revision: https://reviews.llvm.org/D71840
92 lines
3.0 KiB
LLVM
92 lines
3.0 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; Test strict conversion of floating-point values to unsigned i32s (z10 only).
|
|
;
|
|
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
|
|
|
|
; z10 doesn't have native support for unsigned fp-to-i32 conversions;
|
|
; they were added in z196 as the Convert to Logical family of instructions.
|
|
; Promoting to i64 doesn't generate an inexact condition for values that are
|
|
; outside the i32 range but in the i64 range, so use the default expansion.
|
|
; Note that the strict expansion sequence must be used.
|
|
|
|
declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata)
|
|
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
|
|
declare i32 @llvm.experimental.constrained.fptoui.i32.f128(fp128, metadata)
|
|
|
|
; Test f32->i32.
|
|
define i32 @f1(float %f) #0 {
|
|
; CHECK-LABEL: f1:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: larl %r1, .LCPI0_0
|
|
; CHECK-NEXT: le %f1, 0(%r1)
|
|
; CHECK-NEXT: kebr %f0, %f1
|
|
; CHECK-NEXT: jnl .LBB0_2
|
|
; CHECK-NEXT: # %bb.1:
|
|
; CHECK-NEXT: lhi %r0, 0
|
|
; CHECK-NEXT: lzer %f1
|
|
; CHECK-NEXT: j .LBB0_3
|
|
; CHECK-NEXT: .LBB0_2:
|
|
; CHECK-NEXT: llilh %r0, 32768
|
|
; CHECK-NEXT: .LBB0_3:
|
|
; CHECK-NEXT: sebr %f0, %f1
|
|
; CHECK-NEXT: cfebr %r2, 5, %f0
|
|
; CHECK-NEXT: xr %r2, %r0
|
|
; CHECK-NEXT: br %r14
|
|
%conv = call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %f,
|
|
metadata !"fpexcept.strict") #0
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test f64->i32.
|
|
define i32 @f2(double %f) #0 {
|
|
; CHECK-LABEL: f2:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: larl %r1, .LCPI1_0
|
|
; CHECK-NEXT: ldeb %f1, 0(%r1)
|
|
; CHECK-NEXT: kdbr %f0, %f1
|
|
; CHECK-NEXT: jnl .LBB1_2
|
|
; CHECK-NEXT: # %bb.1:
|
|
; CHECK-NEXT: lhi %r0, 0
|
|
; CHECK-NEXT: lzdr %f1
|
|
; CHECK-NEXT: j .LBB1_3
|
|
; CHECK-NEXT: .LBB1_2:
|
|
; CHECK-NEXT: llilh %r0, 32768
|
|
; CHECK-NEXT: .LBB1_3:
|
|
; CHECK-NEXT: sdbr %f0, %f1
|
|
; CHECK-NEXT: cfdbr %r2, 5, %f0
|
|
; CHECK-NEXT: xr %r2, %r0
|
|
; CHECK-NEXT: br %r14
|
|
%conv = call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %f,
|
|
metadata !"fpexcept.strict") #0
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Test f128->i32.
|
|
define i32 @f3(fp128 *%src) #0 {
|
|
; CHECK-LABEL: f3:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: ld %f0, 0(%r2)
|
|
; CHECK-NEXT: ld %f2, 8(%r2)
|
|
; CHECK-NEXT: larl %r1, .LCPI2_0
|
|
; CHECK-NEXT: lxeb %f1, 0(%r1)
|
|
; CHECK-NEXT: kxbr %f0, %f1
|
|
; CHECK-NEXT: jnl .LBB2_2
|
|
; CHECK-NEXT: # %bb.1:
|
|
; CHECK-NEXT: lhi %r0, 0
|
|
; CHECK-NEXT: lzxr %f1
|
|
; CHECK-NEXT: j .LBB2_3
|
|
; CHECK-NEXT: .LBB2_2:
|
|
; CHECK-NEXT: llilh %r0, 32768
|
|
; CHECK-NEXT: .LBB2_3:
|
|
; CHECK-NEXT: sxbr %f0, %f1
|
|
; CHECK-NEXT: cfxbr %r2, 5, %f0
|
|
; CHECK-NEXT: xr %r2, %r0
|
|
; CHECK-NEXT: br %r14
|
|
%f = load fp128, fp128 *%src
|
|
%conv = call i32 @llvm.experimental.constrained.fptoui.i32.f128(fp128 %f,
|
|
metadata !"fpexcept.strict") #0
|
|
ret i32 %conv
|
|
}
|
|
|
|
attributes #0 = { strictfp }
|