For PR1248:

* Fix some indentation and comments in InsertRangeTest
* Add an "IsSigned" parameter to AddWithOverflow and make it handle signed
  additions. Also, APIntify this function so it works with any bitwidth.
* For the icmp pred ([us]div %X, C1), C2 transforms, exit early if the
  div instruction's RHS is zero.
* Finally, for icmp pred (sdiv %X, C1), -C2, fix an off-by-one error. The
  HiBound needs to be incremented in order to get the range test correct.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35247 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer
2007-03-21 23:19:50 +00:00
parent 3a3aacfe10
commit e4e4003032

View File

@ -3773,7 +3773,7 @@ Instruction *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
// V >= Min && V < Hi --> V < Hi // V >= Min && V < Hi --> V < Hi
if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) { if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) {
ICmpInst::Predicate pred = (isSigned ? ICmpInst::Predicate pred = (isSigned ?
ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT); ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT);
return new ICmpInst(pred, V, Hi); return new ICmpInst(pred, V, Hi);
} }
@ -3789,7 +3789,7 @@ Instruction *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
if (Lo == Hi) // Trivially true. if (Lo == Hi) // Trivially true.
return new ICmpInst(ICmpInst::ICMP_EQ, V, V); return new ICmpInst(ICmpInst::ICMP_EQ, V, V);
// V < Min || V >= Hi ->'V > Hi-1' // V < Min || V >= Hi -> V > Hi-1
Hi = SubOne(cast<ConstantInt>(Hi)); Hi = SubOne(cast<ConstantInt>(Hi));
if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) { if (cast<ConstantInt>(Lo)->isMinValue(isSigned)) {
ICmpInst::Predicate pred = (isSigned ? ICmpInst::Predicate pred = (isSigned ?
@ -3797,8 +3797,9 @@ Instruction *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi,
return new ICmpInst(pred, V, Hi); return new ICmpInst(pred, V, Hi);
} }
// Emit V-Lo > Hi-1-Lo // Emit V-Lo >u Hi-1-Lo
Constant *NegLo = ConstantExpr::getNeg(Lo); // Note that Hi has already had one subtracted from it, above.
ConstantInt *NegLo = cast<ConstantInt>(ConstantExpr::getNeg(Lo));
Instruction *Add = BinaryOperator::createAdd(V, NegLo, V->getName()+".off"); Instruction *Add = BinaryOperator::createAdd(V, NegLo, V->getName()+".off");
InsertNewInstBefore(Add, IB); InsertNewInstBefore(Add, IB);
Constant *LowerBound = ConstantExpr::getAdd(NegLo, Hi); Constant *LowerBound = ConstantExpr::getAdd(NegLo, Hi);
@ -4918,11 +4919,16 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
/// AddWithOverflow - Compute Result = In1+In2, returning true if the result /// AddWithOverflow - Compute Result = In1+In2, returning true if the result
/// overflowed for this type. /// overflowed for this type.
static bool AddWithOverflow(ConstantInt *&Result, ConstantInt *In1, static bool AddWithOverflow(ConstantInt *&Result, ConstantInt *In1,
ConstantInt *In2) { ConstantInt *In2, bool IsSigned = false) {
Result = cast<ConstantInt>(ConstantExpr::getAdd(In1, In2)); Result = cast<ConstantInt>(ConstantExpr::getAdd(In1, In2));
return cast<ConstantInt>(Result)->getZExtValue() < if (IsSigned)
cast<ConstantInt>(In1)->getZExtValue(); if (In2->getValue().isNegative())
return Result->getValue().sgt(In1->getValue());
else
return Result->getValue().slt(In1->getValue());
else
return Result->getValue().ult(In1->getValue());
} }
/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the /// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
@ -5664,6 +5670,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
bool DivIsSigned = LHSI->getOpcode() == Instruction::SDiv; bool DivIsSigned = LHSI->getOpcode() == Instruction::SDiv;
if (!I.isEquality() && DivIsSigned != I.isSignedPredicate()) if (!I.isEquality() && DivIsSigned != I.isSignedPredicate())
break; break;
if (DivRHS->isZero())
break; // Don't hack on div by zero
// Initialize the variables that will indicate the nature of the // Initialize the variables that will indicate the nature of the
// range check. // range check.
@ -5680,19 +5688,17 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
// Determine if the product overflows by seeing if the product is // Determine if the product overflows by seeing if the product is
// not equal to the divide. Make sure we do the same kind of divide // not equal to the divide. Make sure we do the same kind of divide
// as in the LHS instruction that we're folding. // as in the LHS instruction that we're folding.
bool ProdOV = !DivRHS->isNullValue() && bool ProdOV = (DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) :
(DivIsSigned ? ConstantExpr::getSDiv(Prod, DivRHS) : ConstantExpr::getUDiv(Prod, DivRHS)) != CI;
ConstantExpr::getUDiv(Prod, DivRHS)) != CI;
// Get the ICmp opcode // Get the ICmp opcode
ICmpInst::Predicate predicate = I.getPredicate(); ICmpInst::Predicate predicate = I.getPredicate();
if (DivRHS->isNullValue()) { if (!DivIsSigned) { // udiv
// Don't hack on divide by zeros!
} else if (!DivIsSigned) { // udiv
LoBound = Prod; LoBound = Prod;
LoOverflow = ProdOV; LoOverflow = ProdOV;
HiOverflow = ProdOV || AddWithOverflow(HiBound, LoBound, DivRHS); HiOverflow = ProdOV ||
AddWithOverflow(HiBound, LoBound, DivRHS, false);
} else if (DivRHS->getValue().isPositive()) { // Divisor is > 0. } else if (DivRHS->getValue().isPositive()) { // Divisor is > 0.
if (CI->isNullValue()) { // (X / pos) op 0 if (CI->isNullValue()) { // (X / pos) op 0
// Can't overflow. // Can't overflow.
@ -5701,12 +5707,13 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
} else if (CI->getValue().isPositive()) { // (X / pos) op pos } else if (CI->getValue().isPositive()) { // (X / pos) op pos
LoBound = Prod; LoBound = Prod;
LoOverflow = ProdOV; LoOverflow = ProdOV;
HiOverflow = ProdOV || AddWithOverflow(HiBound, Prod, DivRHS); HiOverflow = ProdOV ||
AddWithOverflow(HiBound, Prod, DivRHS, true);
} else { // (X / pos) op neg } else { // (X / pos) op neg
Constant *DivRHSH = ConstantExpr::getNeg(SubOne(DivRHS)); Constant *DivRHSH = ConstantExpr::getNeg(SubOne(DivRHS));
LoOverflow = AddWithOverflow(LoBound, Prod, LoOverflow = AddWithOverflow(LoBound, Prod,
cast<ConstantInt>(DivRHSH)); cast<ConstantInt>(DivRHSH), true);
HiBound = Prod; HiBound = AddOne(Prod);
HiOverflow = ProdOV; HiOverflow = ProdOV;
} }
} else { // Divisor is < 0. } else { // Divisor is < 0.
@ -5718,7 +5725,8 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
} else if (CI->getValue().isPositive()) { // (X / neg) op pos } else if (CI->getValue().isPositive()) { // (X / neg) op pos
HiOverflow = LoOverflow = ProdOV; HiOverflow = LoOverflow = ProdOV;
if (!LoOverflow) if (!LoOverflow)
LoOverflow = AddWithOverflow(LoBound, Prod, AddOne(DivRHS)); LoOverflow = AddWithOverflow(LoBound, Prod, AddOne(DivRHS),
true);
HiBound = AddOne(Prod); HiBound = AddOne(Prod);
} else { // (X / neg) op neg } else { // (X / neg) op neg
LoBound = Prod; LoBound = Prod;