mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 23:48:56 +00:00
Broaden optimization of fcmp ([us]itofp x, constant) by instcombine.
The patch extends the optimization to cases where the constant's magnitude is so small or large that the rounding of the conversion is irrelevant. The "so small" case includes negative zero. Differential review: http://reviews.llvm.org/D11210 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247708 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ca857efb5b
commit
5332ea03d1
@ -3734,15 +3734,7 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
|
||||
|
||||
IntegerType *IntTy = cast<IntegerType>(LHSI->getOperand(0)->getType());
|
||||
|
||||
// Check to see that the input is converted from an integer type that is small
|
||||
// enough that preserves all bits. TODO: check here for "known" sign bits.
|
||||
// This would allow us to handle (fptosi (x >>s 62) to float) if x is i64 f.e.
|
||||
unsigned InputSize = IntTy->getScalarSizeInBits();
|
||||
|
||||
// If this is a uitofp instruction, we need an extra bit to hold the sign.
|
||||
bool LHSUnsigned = isa<UIToFPInst>(LHSI);
|
||||
if (LHSUnsigned)
|
||||
++InputSize;
|
||||
|
||||
if (I.isEquality()) {
|
||||
FCmpInst::Predicate P = I.getPredicate();
|
||||
@ -3769,13 +3761,30 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
|
||||
// equality compares as integer?
|
||||
}
|
||||
|
||||
// Comparisons with zero are a special case where we know we won't lose
|
||||
// information.
|
||||
bool IsCmpZero = RHS.isPosZero();
|
||||
// Check to see that the input is converted from an integer type that is small
|
||||
// enough that preserves all bits. TODO: check here for "known" sign bits.
|
||||
// This would allow us to handle (fptosi (x >>s 62) to float) if x is i64 f.e.
|
||||
unsigned InputSize = IntTy->getScalarSizeInBits();
|
||||
|
||||
// If the conversion would lose info, don't hack on this.
|
||||
if ((int)InputSize > MantissaWidth && !IsCmpZero)
|
||||
return nullptr;
|
||||
// Following test does NOT adjust InputSize downwards for signed inputs,
|
||||
// because the most negative value still requires all the mantissa bits
|
||||
// to distinguish it from one less than that value.
|
||||
if ((int)InputSize > MantissaWidth) {
|
||||
// Conversion would lose accuracy. Check if loss can impact comparison.
|
||||
int Exp = ilogb(RHS);
|
||||
if (Exp == APFloat::IEK_Inf) {
|
||||
int MaxExponent = ilogb(APFloat::getLargest(RHS.getSemantics()));
|
||||
if (MaxExponent < (int)InputSize - !LHSUnsigned)
|
||||
// Conversion could create infinity.
|
||||
return nullptr;
|
||||
} else {
|
||||
// Note that if RHS is zero or NaN, then Exp is negative
|
||||
// and first condition is trivially false.
|
||||
if (MantissaWidth <= Exp && Exp <= (int)InputSize - !LHSUnsigned)
|
||||
// Conversion could affect comparison.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we can potentially simplify the comparison. We know that it
|
||||
// will always come through as an integer value and we know the constant is
|
||||
|
@ -10,8 +10,8 @@ define i1 @i32_cast_cmp_oeq_int_0_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp oeq
|
||||
; CHECK-NEXT: icmp eq i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, -0.0
|
||||
@ -28,8 +28,8 @@ define i1 @i32_cast_cmp_oeq_int_0_sitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp oeq
|
||||
; CHECK-NEXT: icmp eq i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_oeq_int_n0_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, -0.0
|
||||
@ -46,8 +46,8 @@ define i1 @i32_cast_cmp_one_int_0_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_one_int_n0_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp one
|
||||
; CHECK-NEXT: icmp ne i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_one_int_n0_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp one float %f, -0.0
|
||||
@ -64,8 +64,8 @@ define i1 @i32_cast_cmp_one_int_0_sitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_one_int_n0_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp one
|
||||
; CHECK-NEXT: icmp ne i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_one_int_n0_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp one float %f, -0.0
|
||||
@ -82,8 +82,8 @@ define i1 @i32_cast_cmp_ueq_int_0_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp ueq
|
||||
; CHECK-NEXT: icmp eq i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_ueq_int_n0_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp ueq float %f, -0.0
|
||||
@ -100,8 +100,8 @@ define i1 @i32_cast_cmp_ueq_int_0_sitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp ueq
|
||||
; CHECK-NEXT: icmp eq i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_ueq_int_n0_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp ueq float %f, -0.0
|
||||
@ -118,8 +118,8 @@ define i1 @i32_cast_cmp_une_int_0_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_une_int_n0_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp une
|
||||
; CHECK-NEXT: icmp ne i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_une_int_n0_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp une float %f, -0.0
|
||||
@ -136,8 +136,8 @@ define i1 @i32_cast_cmp_une_int_0_sitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_une_int_n0_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp une
|
||||
; CHECK-NEXT: icmp ne i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_une_int_n0_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp une float %f, -0.0
|
||||
@ -154,8 +154,8 @@ define i1 @i32_cast_cmp_ogt_int_0_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp ogt
|
||||
; CHECK: icmp ne i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_ogt_int_n0_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp ogt float %f, -0.0
|
||||
@ -172,8 +172,8 @@ define i1 @i32_cast_cmp_ogt_int_0_sitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp ogt
|
||||
; CHECK: icmp sgt i32 %i, 0
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_ogt_int_n0_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp ogt float %f, -0.0
|
||||
@ -261,12 +261,13 @@ define i1 @i32_cast_cmp_oeq_int_0_uitofp_ppcf128(i32 %i) {
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp oeq
|
||||
; Since 0xFFFFFF fits in a float, and one less and
|
||||
; one more than it also fits without rounding, the
|
||||
; test can be optimized to an integer compare.
|
||||
|
||||
; XCHECK: icmp eq i32 %i, 16777215
|
||||
; XCHECK-NEXT: ret
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_uitofp(
|
||||
; CHECK: icmp eq i32 %i, 16777215
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_oeq_int_i24max_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x416FFFFFE0000000
|
||||
@ -274,17 +275,18 @@ define i1 @i32_cast_cmp_oeq_int_i24max_uitofp(i32 %i) {
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp oeq
|
||||
|
||||
; XCHECK: icmp eq i32 %i, 16777215
|
||||
; XCHECK-NEXT: ret
|
||||
; CHECK: icmp eq i32 %i, 16777215
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i32_cast_cmp_oeq_int_i24max_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x416FFFFFE0000000
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; Though 0x1000000 fits in a float, one more than it
|
||||
; would round to it too, hence a single integer comparison
|
||||
; does not suffice.
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp oeq
|
||||
@ -319,10 +321,18 @@ define i1 @i32_cast_cmp_oeq_int_i32umax_uitofp(i32 %i) {
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; 32-bit unsigned integer cannot possibly round up to 1<<33
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_big_uitofp(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
define i1 @i32_cast_cmp_oeq_int_big_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x4200000000000000
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; 32-bit signed integer cannot possibly round up to 1<<32
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32umax_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp oeq
|
||||
; CHECK-NEXT: ret
|
||||
; CHECK-NEXT: ret i1 false
|
||||
define i1 @i32_cast_cmp_oeq_int_i32umax_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x41F0000000000000
|
||||
@ -379,10 +389,9 @@ define i1 @i32_cast_cmp_oeq_int_negi32umax_uitofp(i32 %i) {
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; 32-bit signed integer cannot possibly round to -1<<32
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_negi32umax_sitofp(
|
||||
; CHECK: sitofp
|
||||
; CHECK: fcmp oeq
|
||||
; CHECK-NEXT: ret
|
||||
; CHECK-NEXT: ret i1 false
|
||||
define i1 @i32_cast_cmp_oeq_int_negi32umax_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0xC1F0000000000000
|
||||
@ -452,3 +461,30 @@ define i1 @i32_cast_cmp_une_half_sitofp(i32 %i) {
|
||||
%cmp = fcmp une float %f, 0.5
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_inf_uitofp(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
define i1 @i32_cast_cmp_oeq_int_inf_uitofp(i32 %i) {
|
||||
%f = uitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x7FF0000000000000
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @i32_cast_cmp_oeq_int_inf_sitofp(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
define i1 @i32_cast_cmp_oeq_int_inf_sitofp(i32 %i) {
|
||||
%f = sitofp i32 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x7FF0000000000000
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; An i128 could round to an IEEE single-precision infinity.
|
||||
; CHECK-LABEL: @i128_cast_cmp_oeq_int_inf_uitofp(
|
||||
; CHECK: uitofp
|
||||
; CHECK: fcmp oeq
|
||||
; CHECK-NEXT: ret
|
||||
define i1 @i128_cast_cmp_oeq_int_inf_uitofp(i128 %i) {
|
||||
%f = uitofp i128 %i to float
|
||||
%cmp = fcmp oeq float %f, 0x7FF0000000000000
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user