Created
July 15, 2015 02:02
-
-
Save ArchRobison/1de1aa692f7c9e466004 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: InstCombine/InstCombineCompares.cpp | |
=================================================================== | |
--- InstCombine/InstCombineCompares.cpp (revision 242211) | |
+++ InstCombine/InstCombineCompares.cpp (working copy) | |
@@ -3687,70 +3687,79 @@ | |
/// FoldFCmp_IntToFP_Cst - Fold fcmp ([us]itofp x, cst) if possible. | |
Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I, | |
Instruction *LHSI, | |
Constant *RHSC) { | |
if (!isa<ConstantFP>(RHSC)) return nullptr; | |
const APFloat &RHS = cast<ConstantFP>(RHSC)->getValueAPF(); | |
// Get the width of the mantissa. We don't want to hack on conversions that | |
// might lose information from the integer, e.g. "i64 -> float" | |
int MantissaWidth = LHSI->getType()->getFPMantissaWidth(); | |
if (MantissaWidth == -1) return nullptr; // Unknown. | |
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(); | |
bool IsExact = false; | |
APSInt RHSCvt(IntTy->getBitWidth(), LHSUnsigned); | |
RHS.convertToInteger(RHSCvt, APFloat::rmNearestTiesToEven, &IsExact); | |
// If the floating point constant isn't an integer value, we know if we will | |
// ever compare equal / not equal to it. | |
if (!IsExact) { | |
// TODO: Can never be -0.0 and other non-representable values | |
APFloat RHSRoundInt(RHS); | |
RHSRoundInt.roundToIntegral(APFloat::rmNearestTiesToEven); | |
if (RHS.compare(RHSRoundInt) != APFloat::cmpEqual) { | |
if (P == FCmpInst::FCMP_OEQ || P == FCmpInst::FCMP_UEQ) | |
return ReplaceInstUsesWith(I, Builder->getFalse()); | |
assert(P == FCmpInst::FCMP_ONE || P == FCmpInst::FCMP_UNE); | |
return ReplaceInstUsesWith(I, Builder->getTrue()); | |
} | |
} | |
// TODO: If the constant is exactly representable, is it always OK to do | |
// equality compares as integer? | |
} | |
- // Comparisons with zero are a special case where we know we won't lose | |
- // information. | |
- bool IsCmpZero = RHS.isPosZero(); | |
- | |
- // If the conversion would lose info, don't hack on this. | |
- if ((int)InputSize > MantissaWidth && !IsCmpZero) | |
- return nullptr; | |
+ // 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(); | |
+ | |
+ // 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 | |
// not a NAN (it would have been previously simplified). | |
assert(!RHS.isNaN() && "NaN comparison not already folded!"); | |
ICmpInst::Predicate Pred; | |
switch (I.getPredicate()) { | |
default: llvm_unreachable("Unexpected predicate!"); | |
case FCmpInst::FCMP_UEQ: | |
case FCmpInst::FCMP_OEQ: | |
Pred = ICmpInst::ICMP_EQ; | |
break; | |
case FCmpInst::FCMP_UGT: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment