If the LHS of the FCMP is coming from a UIToFP instruction, then we don't want

to generate signed ICMP instructions to replace the FCMP. This would violate
the following:

define i1 @test1(i32 %val) {
  %1 = uitofp i32 %val to double
  %2 = fcmp ole double %1, 0.000000e+00
  ret i1 %2
}

would be transformed into:

define i1 @test1(i32 %val) {
  %1 = icmp slt i33 %val, 1
  ret i1 %1
}

which is obviously wrong. This patch modifes InstCombiner::FoldFCmp_IntToFP_Cst
to handle when the LHS comes from UIToFP.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58929 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2008-11-09 04:26:50 +00:00
parent b0714dbc0d
commit c143bcf9ac
2 changed files with 134 additions and 33 deletions

View File

@ -5317,7 +5317,8 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
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))
bool LHSUnsigned = isa<UIToFPInst>(LHSI);
if (LHSUnsigned)
++InputSize;
// If the conversion would lose info, don't hack on this.
@ -5333,17 +5334,29 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
switch (I.getPredicate()) {
default: assert(0 && "Unexpected predicate!");
case FCmpInst::FCMP_UEQ:
case FCmpInst::FCMP_OEQ: Pred = ICmpInst::ICMP_EQ; break;
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_OGT:
Pred = LHSUnsigned ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_SGT;
break;
case FCmpInst::FCMP_UGE:
case FCmpInst::FCMP_OGE: Pred = ICmpInst::ICMP_SGE; break;
case FCmpInst::FCMP_OGE:
Pred = LHSUnsigned ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE;
break;
case FCmpInst::FCMP_ULT:
case FCmpInst::FCMP_OLT: Pred = ICmpInst::ICMP_SLT; break;
case FCmpInst::FCMP_OLT:
Pred = LHSUnsigned ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_SLT;
break;
case FCmpInst::FCMP_ULE:
case FCmpInst::FCMP_OLE: Pred = ICmpInst::ICMP_SLE; break;
case FCmpInst::FCMP_OLE:
Pred = LHSUnsigned ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_SLE;
break;
case FCmpInst::FCMP_UNE:
case FCmpInst::FCMP_ONE: Pred = ICmpInst::ICMP_NE; break;
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:
@ -5358,63 +5371,105 @@ Instruction *InstCombiner::FoldFCmp_IntToFP_Cst(FCmpInst &I,
// 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 (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT ||
Pred == ICmpInst::ICMP_SLE)
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
if (!LHSUnsigned) {
// 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 (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SLT ||
Pred == ICmpInst::ICMP_SLE)
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
}
} else {
// If the RHS value is > UnsignedMax, fold the comparison. This handles
// +INF and large values.
APFloat UMax(RHS.getSemantics(), APFloat::fcZero, false);
UMax.convertFromAPInt(APInt::getMaxValue(IntWidth), false,
APFloat::rmNearestTiesToEven);
if (UMax.compare(RHS) == APFloat::cmpLessThan) { // umax < 13123.0
if (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_ULT ||
Pred == ICmpInst::ICMP_ULE)
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 (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_SGT ||
Pred == ICmpInst::ICMP_SGE)
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
if (!LHSUnsigned) {
// 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 (Pred == ICmpInst::ICMP_NE || Pred == 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.
// Okay, now we know that the FP constant fits in the range [SMIN, SMAX] or
// [0, UMAX], 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.
// 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_ULE:
// (float)int <= 4.4 --> int <= 4
// (float)int <= -4.4 --> false
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
break;
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_ULT:
// (float)int < -4.4 --> false
// (float)int < 4.4 --> int <= 4
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 0));
Pred = ICmpInst::ICMP_ULE;
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_UGT:
// (float)int > 4.4 --> int > 4
// (float)int > -4.4 --> true
if (RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
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_UGE:
// (float)int >= -4.4 --> true
// (float)int >= 4.4 --> int > 4
if (!RHS.isNegative())
return ReplaceInstUsesWith(I, ConstantInt::get(Type::Int1Ty, 1));
Pred = ICmpInst::ICMP_UGT;
break;
case ICmpInst::ICMP_SGE:
// (float)int >= -4.4 --> int >= -4
// (float)int >= 4.4 --> int > 4

View File

@ -0,0 +1,46 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t
; RUN: grep {icmp eq} %t
; RUN: grep {ret i1 false} %t | count 2
; RUN: grep {ret i1 true} %t | count 2
; RUN: grep {icmp ne} %t
; RUN: not grep {icmp slt} %t
; PR3021
; When inst combining an FCMP with the LHS coming from a uitofp instruction, we
; can't lower it to signed ICMP instructions.
define i1 @test1(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp ole double %1, 0.000000e+00
ret i1 %2
}
define i1 @test2(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp olt double %1, 0.000000e+00
ret i1 %2
}
define i1 @test3(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp oge double %1, 0.000000e+00
ret i1 %2
}
define i1 @test4(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp ogt double %1, 0.000000e+00
ret i1 %2
}
define i1 @test5(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp ogt double %1, -4.400000e+00
ret i1 %2
}
define i1 @test6(i32 %val) {
%1 = uitofp i32 %val to double
%2 = fcmp olt double %1, -4.400000e+00
ret i1 %2
}