mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Improved fix for PR17827 (instcombine of shift/and/compare).
This change fixes the case of arithmetic shift right - do not attempt to fold that case. This change also relaxes the conditions when attempting to fold the logical shift right and shift left cases. No additional IR-level test cases included at this time. See http://llvm.org/bugs/show_bug.cgi?id=17827 for proofs that these are correct transformations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197705 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
23b7879584
commit
79b37835f9
@ -1195,33 +1195,43 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
|
||||
ConstantInt *ShAmt;
|
||||
ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : 0;
|
||||
|
||||
// We can fold this as long as we can't shift unknown bits
|
||||
// into the mask. This can happen with signed shift
|
||||
// rights, as they sign-extend. With logical shifts,
|
||||
// we must still make sure the comparison is not signed
|
||||
// because we are effectively changing the
|
||||
// position of the sign bit (PR17827).
|
||||
// TODO: We can relax these constraints a bit more.
|
||||
// This seemingly simple opportunity to fold away a shift turns out to
|
||||
// be rather complicated. See PR17827
|
||||
// ( http://llvm.org/bugs/show_bug.cgi?id=17827 ) for details.
|
||||
if (ShAmt) {
|
||||
bool CanFold = false;
|
||||
unsigned ShiftOpcode = Shift->getOpcode();
|
||||
if (ShiftOpcode == Instruction::AShr) {
|
||||
// To test for the bad case of the signed shr, see if any
|
||||
// of the bits shifted in could be tested after the mask.
|
||||
Type *ShiftType = Shift->getType();
|
||||
Type *AndType = AndCst->getType();
|
||||
|
||||
unsigned ShiftBitWidth = ShiftType->getPrimitiveSizeInBits();
|
||||
unsigned AndBitWidth = AndType->getPrimitiveSizeInBits();
|
||||
|
||||
int ShAmtVal = ShiftBitWidth - ShAmt->getLimitedValue(ShiftBitWidth);
|
||||
|
||||
if ((APInt::getHighBitsSet(AndBitWidth, AndBitWidth - ShAmtVal) &
|
||||
AndCst->getValue()) == 0)
|
||||
// There may be some constraints that make this possible,
|
||||
// but nothing simple has been discovered yet.
|
||||
CanFold = false;
|
||||
} else if (ShiftOpcode == Instruction::Shl) {
|
||||
// For a left shift, we can fold if the comparison is not signed.
|
||||
// We can also fold a signed comparison if the mask value and
|
||||
// comparison value are not negative. These constraints may not be
|
||||
// obvious, but we can prove that they are correct using an SMT
|
||||
// solver such as "Z3" :
|
||||
// http://rise4fun.com/Z3/DyMp
|
||||
if (!ICI.isSigned() || (!AndCst->isNegative() && !RHS->isNegative()))
|
||||
CanFold = true;
|
||||
} else if (ShiftOpcode == Instruction::Shl ||
|
||||
ShiftOpcode == Instruction::LShr) {
|
||||
CanFold = !ICI.isSigned();
|
||||
} else if (ShiftOpcode == Instruction::LShr) {
|
||||
// For a logical right shift, we can fold if the comparison is not
|
||||
// signed. We can also fold a signed comparison if the shifted mask
|
||||
// value and the shifted comparison value are not negative.
|
||||
// These constraints may not be obvious, but we can prove that they
|
||||
// are correct using an SMT solver such as "Z3" :
|
||||
// http://rise4fun.com/Z3/Tslfh
|
||||
if (!ICI.isSigned())
|
||||
CanFold = true;
|
||||
else {
|
||||
ConstantInt *ShiftedAndCst =
|
||||
cast<ConstantInt>(ConstantExpr::getShl(AndCst, ShAmt));
|
||||
ConstantInt *ShiftedRHSCst =
|
||||
cast<ConstantInt>(ConstantExpr::getShl(RHS, ShAmt));
|
||||
|
||||
if (!ShiftedAndCst->isNegative() && !ShiftedRHSCst->isNegative())
|
||||
CanFold = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (CanFold) {
|
||||
|
Loading…
Reference in New Issue
Block a user