InstCombine: Check for zero shift amounts before subtracting one causing integer overflow.

PR17026. Also avoid undefined shifts and shift amounts larger than 64 bits
(those are always undef because we can't represent integer types that large).

llvm-svn: 189672
This commit is contained in:
Benjamin Kramer
2013-08-30 14:35:35 +00:00
parent 1790ea000b
commit 010f108382
2 changed files with 51 additions and 10 deletions

View File

@@ -845,21 +845,26 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
Value *InstCombiner::SimplifyShrShlDemandedBits(Instruction *Shr,
Instruction *Shl, APInt DemandedMask, APInt &KnownZero, APInt &KnownOne) {
unsigned ShlAmt = cast<ConstantInt>(Shl->getOperand(1))->getZExtValue();
unsigned ShrAmt = cast<ConstantInt>(Shr->getOperand(1))->getZExtValue();
const APInt &ShlOp1 = cast<ConstantInt>(Shl->getOperand(1))->getValue();
const APInt &ShrOp1 = cast<ConstantInt>(Shr->getOperand(1))->getValue();
if (!ShlOp1 || !ShrOp1)
return 0; // Noop.
Value *VarX = Shr->getOperand(0);
Type *Ty = VarX->getType();
unsigned BitWidth = Ty->getIntegerBitWidth();
if (ShlOp1.uge(BitWidth) || ShrOp1.uge(BitWidth))
return 0; // Undef.
unsigned ShlAmt = ShlOp1.getZExtValue();
unsigned ShrAmt = ShrOp1.getZExtValue();
KnownOne.clearAllBits();
KnownZero = APInt::getBitsSet(KnownZero.getBitWidth(), 0, ShlAmt-1);
KnownZero &= DemandedMask;
if (ShlAmt == 0 || ShrAmt == 0)
return 0;
Value *VarX = Shr->getOperand(0);
Type *Ty = VarX->getType();
APInt BitMask1(APInt::getAllOnesValue(Ty->getIntegerBitWidth()));
APInt BitMask2(APInt::getAllOnesValue(Ty->getIntegerBitWidth()));
APInt BitMask1(APInt::getAllOnesValue(BitWidth));
APInt BitMask2(APInt::getAllOnesValue(BitWidth));
bool isLshr = (Shr->getOpcode() == Instruction::LShr);
BitMask1 = isLshr ? (BitMask1.lshr(ShrAmt) << ShlAmt) :