mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-22 10:24:26 +00:00
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:
@ -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;
|
||||||
|
Reference in New Issue
Block a user