mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-06 18:46:18 +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;
|
ConstantInt *ShAmt;
|
||||||
ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : 0;
|
ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : 0;
|
||||||
|
|
||||||
// We can fold this as long as we can't shift unknown bits
|
// This seemingly simple opportunity to fold away a shift turns out to
|
||||||
// into the mask. This can happen with signed shift
|
// be rather complicated. See PR17827
|
||||||
// rights, as they sign-extend. With logical shifts,
|
// ( http://llvm.org/bugs/show_bug.cgi?id=17827 ) for details.
|
||||||
// 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.
|
|
||||||
if (ShAmt) {
|
if (ShAmt) {
|
||||||
bool CanFold = false;
|
bool CanFold = false;
|
||||||
unsigned ShiftOpcode = Shift->getOpcode();
|
unsigned ShiftOpcode = Shift->getOpcode();
|
||||||
if (ShiftOpcode == Instruction::AShr) {
|
if (ShiftOpcode == Instruction::AShr) {
|
||||||
// To test for the bad case of the signed shr, see if any
|
// There may be some constraints that make this possible,
|
||||||
// of the bits shifted in could be tested after the mask.
|
// but nothing simple has been discovered yet.
|
||||||
Type *ShiftType = Shift->getType();
|
CanFold = false;
|
||||||
Type *AndType = AndCst->getType();
|
} else if (ShiftOpcode == Instruction::Shl) {
|
||||||
|
// For a left shift, we can fold if the comparison is not signed.
|
||||||
unsigned ShiftBitWidth = ShiftType->getPrimitiveSizeInBits();
|
// We can also fold a signed comparison if the mask value and
|
||||||
unsigned AndBitWidth = AndType->getPrimitiveSizeInBits();
|
// comparison value are not negative. These constraints may not be
|
||||||
|
// obvious, but we can prove that they are correct using an SMT
|
||||||
int ShAmtVal = ShiftBitWidth - ShAmt->getLimitedValue(ShiftBitWidth);
|
// solver such as "Z3" :
|
||||||
|
// http://rise4fun.com/Z3/DyMp
|
||||||
if ((APInt::getHighBitsSet(AndBitWidth, AndBitWidth - ShAmtVal) &
|
if (!ICI.isSigned() || (!AndCst->isNegative() && !RHS->isNegative()))
|
||||||
AndCst->getValue()) == 0)
|
|
||||||
CanFold = true;
|
CanFold = true;
|
||||||
} else if (ShiftOpcode == Instruction::Shl ||
|
} else if (ShiftOpcode == Instruction::LShr) {
|
||||||
ShiftOpcode == Instruction::LShr) {
|
// For a logical right shift, we can fold if the comparison is not
|
||||||
CanFold = !ICI.isSigned();
|
// 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) {
|
if (CanFold) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user