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).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189672 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2013-08-30 14:35:35 +00:00
parent d7a178eee3
commit a8517ee732
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) :

View File

@ -744,3 +744,39 @@ define i32 @test62(i32 %x) {
; CHECK-LABEL: @test62(
; CHECK: ashr exact i32 %x, 3
}
; PR17026
; CHECK-LABEL: @test63(
; CHECK-NOT: sh
; CHECK: ret
define void @test63(i128 %arg) {
bb:
br i1 undef, label %bb1, label %bb12
bb1: ; preds = %bb11, %bb
br label %bb2
bb2: ; preds = %bb7, %bb1
br i1 undef, label %bb3, label %bb7
bb3: ; preds = %bb2
%tmp = lshr i128 %arg, 36893488147419103232
%tmp4 = shl i128 %tmp, 0
%tmp5 = or i128 %tmp4, undef
%tmp6 = trunc i128 %tmp5 to i16
br label %bb8
bb7: ; preds = %bb2
br i1 undef, label %bb8, label %bb2
bb8: ; preds = %bb7, %bb3
%tmp9 = phi i16 [ %tmp6, %bb3 ], [ undef, %bb7 ]
%tmp10 = icmp eq i16 %tmp9, 0
br i1 %tmp10, label %bb11, label %bb12
bb11: ; preds = %bb8
br i1 undef, label %bb1, label %bb12
bb12: ; preds = %bb11, %bb8, %bb
ret void
}