mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Fold FP comparisons where one operand is converted from an integer
type and the other operand is a constant into integer comparisons. This happens surprisingly frequently (e.g. 10 times in 471.omnetpp), which are things like this: %tmp8283 = sitofp i32 %tmp82 to double %tmp1013 = fcmp ult double %tmp8283, 0.0 Clearly comparing tmp82 against i32 0 is cheaper here. this also triggers 8 times in gobmk, including this one: %tmp375376 = sitofp i32 %tmp375 to double %tmp377 = fcmp ogt double %tmp375376, 8.150000e+01 which is comparing an integer against 81.5 :). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51268 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
13d57320bd
commit
a540623ab1
@ -185,6 +185,8 @@ namespace {
|
|||||||
Instruction *visitAShr(BinaryOperator &I);
|
Instruction *visitAShr(BinaryOperator &I);
|
||||||
Instruction *visitLShr(BinaryOperator &I);
|
Instruction *visitLShr(BinaryOperator &I);
|
||||||
Instruction *commonShiftTransforms(BinaryOperator &I);
|
Instruction *commonShiftTransforms(BinaryOperator &I);
|
||||||
|
Instruction *FoldFCmp_IntToFP_Cst(FCmpInst &I, Instruction *LHSI,
|
||||||
|
Constant *RHSC);
|
||||||
Instruction *visitFCmpInst(FCmpInst &I);
|
Instruction *visitFCmpInst(FCmpInst &I);
|
||||||
Instruction *visitICmpInst(ICmpInst &I);
|
Instruction *visitICmpInst(ICmpInst &I);
|
||||||
Instruction *visitICmpInstWithCastAndCast(ICmpInst &ICI);
|
Instruction *visitICmpInstWithCastAndCast(ICmpInst &ICI);
|
||||||
@ -418,6 +420,18 @@ static const Type *getPromotedType(const Type *Ty) {
|
|||||||
return Ty;
|
return Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// GetFPMantissaWidth - Return the width of the mantissa (aka significand) of
|
||||||
|
/// the specified floating point type in bits. This returns -1 if unknown.
|
||||||
|
static int GetFPMantissaWidth(const Type *FPType) {
|
||||||
|
if (FPType == Type::FloatTy)
|
||||||
|
return 24;
|
||||||
|
if (FPType == Type::DoubleTy)
|
||||||
|
return 53;
|
||||||
|
if (FPType == Type::X86_FP80Ty)
|
||||||
|
return 64;
|
||||||
|
return -1; // Unknown/crazy type.
|
||||||
|
}
|
||||||
|
|
||||||
/// getBitCastOperand - If the specified operand is a CastInst or a constant
|
/// getBitCastOperand - If the specified operand is a CastInst or a constant
|
||||||
/// expression bitcast, return the operand value, otherwise return null.
|
/// expression bitcast, return the operand value, otherwise return null.
|
||||||
static Value *getBitCastOperand(Value *V) {
|
static Value *getBitCastOperand(Value *V) {
|
||||||
@ -5228,6 +5242,135 @@ Instruction *InstCombiner::FoldGEPICmp(User *GEPLHS, Value *RHS,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 0;
|
||||||
|
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 = GetFPMantissaWidth(LHSI->getType());
|
||||||
|
if (MantissaWidth == -1) return 0; // Unknown.
|
||||||
|
|
||||||
|
// 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 = LHSI->getOperand(0)->getType()->getPrimitiveSizeInBits();
|
||||||
|
|
||||||
|
// If this is a uitofp instruction, we need an extra bit to hold the sign.
|
||||||
|
if (isa<UIToFPInst>(LHSI))
|
||||||
|
++InputSize;
|
||||||
|
|
||||||
|
// If the conversion would lose info, don't hack on this.
|
||||||
|
if ((int)InputSize > MantissaWidth)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// 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: assert(0 && "Unexpected predicate!");
|
||||||
|
case FCmpInst::FCMP_UEQ:
|
||||||
|
case FCmpInst::FCMP_OEQ: Pred = ICmpInst::ICMP_EQ; break;
|
||||||
|
case FCmpInst::FCMP_UGT:
|
||||||
|
case FCmpInst::FCMP_OGT: Pred = ICmpInst::ICMP_SGT; break;
|
||||||
|
case FCmpInst::FCMP_UGE:
|
||||||
|
case FCmpInst::FCMP_OGE: Pred = ICmpInst::ICMP_SGE; break;
|
||||||
|
case FCmpInst::FCMP_ULT:
|
||||||
|
case FCmpInst::FCMP_OLT: Pred = ICmpInst::ICMP_SLT; break;
|
||||||
|
case FCmpInst::FCMP_ULE:
|
||||||
|
case FCmpInst::FCMP_OLE: Pred = ICmpInst::ICMP_SLE; break;
|
||||||
|
case FCmpInst::FCMP_UNE:
|
||||||
|
case FCmpInst::FCMP_ONE: Pred = ICmpInst::ICMP_NE; break;
|
||||||
|
case FCmpInst::FCMP_ORD:
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
|
||||||
|
case FCmpInst::FCMP_UNO:
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
const IntegerType *IntTy = cast<IntegerType>(LHSI->getOperand(0)->getType());
|
||||||
|
|
||||||
|
// Now we know that the APFloat is a normal number, zero or inf.
|
||||||
|
|
||||||
|
// See if the FP constant is top large for the integer. For example,
|
||||||
|
// comparing an i8 to 300.0.
|
||||||
|
unsigned IntWidth = IntTy->getPrimitiveSizeInBits();
|
||||||
|
|
||||||
|
// If the RHS value is > SignedMax, fold the comparison. This handles +INF
|
||||||
|
// and large values.
|
||||||
|
APFloat SMax(RHS.getSemantics(), APFloat::fcZero, false);
|
||||||
|
SMax.convertFromAPInt(APInt::getSignedMaxValue(IntWidth), true,
|
||||||
|
APFloat::rmNearestTiesToEven);
|
||||||
|
if (SMax.compare(RHS) == APFloat::cmpLessThan) { // smax < 13123.0
|
||||||
|
if (ICmpInst::ICMP_NE || ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the RHS value is < SignedMin.
|
||||||
|
APFloat SMin(RHS.getSemantics(), APFloat::fcZero, false);
|
||||||
|
SMin.convertFromAPInt(APInt::getSignedMinValue(IntWidth), true,
|
||||||
|
APFloat::rmNearestTiesToEven);
|
||||||
|
if (SMin.compare(RHS) == APFloat::cmpGreaterThan) { // smin > 12312.0
|
||||||
|
if (ICmpInst::ICMP_NE || ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE)
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, now we know that the FP constant fits in the range [SMIN, SMAX] but
|
||||||
|
// it may still be fractional. See if it is fractional by casting the FP
|
||||||
|
// value to the integer value and back, checking for equality. Don't do this
|
||||||
|
// for zero, because -0.0 is not fractional.
|
||||||
|
Constant *RHSInt = ConstantExpr::getFPToSI(RHSC, IntTy);
|
||||||
|
if (!RHS.isZero() &&
|
||||||
|
ConstantExpr::getSIToFP(RHSInt, RHSC->getType()) != RHSC) {
|
||||||
|
// If we had a comparison against a fractional value, we have to adjust
|
||||||
|
// the compare predicate and sometimes the value. RHSC is rounded towards
|
||||||
|
// zero at this point.
|
||||||
|
switch (Pred) {
|
||||||
|
default: assert(0 && "Unexpected integer comparison!");
|
||||||
|
case ICmpInst::ICMP_NE: // (float)int != 4.4 --> true
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
|
||||||
|
case ICmpInst::ICMP_EQ: // (float)int == 4.4 --> false
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
|
||||||
|
case ICmpInst::ICMP_SLE:
|
||||||
|
// (float)int <= 4.4 --> int <= 4
|
||||||
|
// (float)int <= -4.4 --> int < -4
|
||||||
|
if (RHS.isNegative())
|
||||||
|
Pred = ICmpInst::ICMP_SLT;
|
||||||
|
break;
|
||||||
|
case ICmpInst::ICMP_SLT:
|
||||||
|
// (float)int < -4.4 --> int < -4
|
||||||
|
// (float)int < 4.4 --> int <= 4
|
||||||
|
if (!RHS.isNegative())
|
||||||
|
Pred = ICmpInst::ICMP_SLE;
|
||||||
|
break;
|
||||||
|
case ICmpInst::ICMP_SGT:
|
||||||
|
// (float)int > 4.4 --> int > 4
|
||||||
|
// (float)int > -4.4 --> int >= -4
|
||||||
|
if (RHS.isNegative())
|
||||||
|
Pred = ICmpInst::ICMP_SGE;
|
||||||
|
break;
|
||||||
|
case ICmpInst::ICMP_SGE:
|
||||||
|
// (float)int >= -4.4 --> int >= -4
|
||||||
|
// (float)int >= 4.4 --> int > 4
|
||||||
|
if (!RHS.isNegative())
|
||||||
|
Pred = ICmpInst::ICMP_SGT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lower this FP comparison into an appropriate integer version of the
|
||||||
|
// comparison.
|
||||||
|
return new ICmpInst(Pred, LHSI->getOperand(0), RHSInt);
|
||||||
|
}
|
||||||
|
|
||||||
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
||||||
bool Changed = SimplifyCompare(I);
|
bool Changed = SimplifyCompare(I);
|
||||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||||
@ -5276,12 +5419,29 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) {
|
|||||||
|
|
||||||
// Handle fcmp with constant RHS
|
// Handle fcmp with constant RHS
|
||||||
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
if (Constant *RHSC = dyn_cast<Constant>(Op1)) {
|
||||||
|
// If the constant is a nan, see if we can fold the comparison based on it.
|
||||||
|
if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
|
||||||
|
if (CFP->getValueAPF().isNaN()) {
|
||||||
|
if (FCmpInst::isOrdered(I.getPredicate())) // True if ordered and...
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
|
||||||
|
if (FCmpInst::isUnordered(I.getPredicate())) // True if unordered or...
|
||||||
|
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
|
||||||
|
if (FCmpInst::isUnordered(I.getPredicate())) // Undef on unordered.
|
||||||
|
return ReplaceInstUsesWith(I, UndefValue::get(Type::Int1Ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
if (Instruction *LHSI = dyn_cast<Instruction>(Op0))
|
||||||
switch (LHSI->getOpcode()) {
|
switch (LHSI->getOpcode()) {
|
||||||
case Instruction::PHI:
|
case Instruction::PHI:
|
||||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||||
return NV;
|
return NV;
|
||||||
break;
|
break;
|
||||||
|
case Instruction::SIToFP:
|
||||||
|
case Instruction::UIToFP:
|
||||||
|
if (Instruction *NV = FoldFCmp_IntToFP_Cst(I, LHSI, RHSC))
|
||||||
|
return NV;
|
||||||
|
break;
|
||||||
case Instruction::Select:
|
case Instruction::Select:
|
||||||
// If either operand of the select is a constant, we can fold the
|
// If either operand of the select is a constant, we can fold the
|
||||||
// comparison into the select arms, which will cause one to be
|
// comparison into the select arms, which will cause one to be
|
||||||
|
25
test/Transforms/InstCombine/sitofp.ll
Normal file
25
test/Transforms/InstCombine/sitofp.ll
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sitofp
|
||||||
|
|
||||||
|
define i1 @test1(i8 %A) {
|
||||||
|
%B = sitofp i8 %A to double
|
||||||
|
%C = fcmp ult double %B, 128.0
|
||||||
|
ret i1 %C ; True!
|
||||||
|
}
|
||||||
|
define i1 @test2(i8 %A) {
|
||||||
|
%B = sitofp i8 %A to double
|
||||||
|
%C = fcmp ugt double %B, -128.1
|
||||||
|
ret i1 %C ; True!
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @test3(i8 %A) {
|
||||||
|
%B = sitofp i8 %A to double
|
||||||
|
%C = fcmp ule double %B, 127.0
|
||||||
|
ret i1 %C ; true!
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @test4(i8 %A) {
|
||||||
|
%B = sitofp i8 %A to double
|
||||||
|
%C = fcmp ult double %B, 127.0
|
||||||
|
ret i1 %C ; A != 127
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user