mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
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:
parent
d7a178eee3
commit
a8517ee732
@ -845,21 +845,26 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
|||||||
Value *InstCombiner::SimplifyShrShlDemandedBits(Instruction *Shr,
|
Value *InstCombiner::SimplifyShrShlDemandedBits(Instruction *Shr,
|
||||||
Instruction *Shl, APInt DemandedMask, APInt &KnownZero, APInt &KnownOne) {
|
Instruction *Shl, APInt DemandedMask, APInt &KnownZero, APInt &KnownOne) {
|
||||||
|
|
||||||
unsigned ShlAmt = cast<ConstantInt>(Shl->getOperand(1))->getZExtValue();
|
const APInt &ShlOp1 = cast<ConstantInt>(Shl->getOperand(1))->getValue();
|
||||||
unsigned ShrAmt = cast<ConstantInt>(Shr->getOperand(1))->getZExtValue();
|
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();
|
KnownOne.clearAllBits();
|
||||||
KnownZero = APInt::getBitsSet(KnownZero.getBitWidth(), 0, ShlAmt-1);
|
KnownZero = APInt::getBitsSet(KnownZero.getBitWidth(), 0, ShlAmt-1);
|
||||||
KnownZero &= DemandedMask;
|
KnownZero &= DemandedMask;
|
||||||
|
|
||||||
if (ShlAmt == 0 || ShrAmt == 0)
|
APInt BitMask1(APInt::getAllOnesValue(BitWidth));
|
||||||
return 0;
|
APInt BitMask2(APInt::getAllOnesValue(BitWidth));
|
||||||
|
|
||||||
Value *VarX = Shr->getOperand(0);
|
|
||||||
Type *Ty = VarX->getType();
|
|
||||||
|
|
||||||
APInt BitMask1(APInt::getAllOnesValue(Ty->getIntegerBitWidth()));
|
|
||||||
APInt BitMask2(APInt::getAllOnesValue(Ty->getIntegerBitWidth()));
|
|
||||||
|
|
||||||
bool isLshr = (Shr->getOpcode() == Instruction::LShr);
|
bool isLshr = (Shr->getOpcode() == Instruction::LShr);
|
||||||
BitMask1 = isLshr ? (BitMask1.lshr(ShrAmt) << ShlAmt) :
|
BitMask1 = isLshr ? (BitMask1.lshr(ShrAmt) << ShlAmt) :
|
||||||
|
@ -744,3 +744,39 @@ define i32 @test62(i32 %x) {
|
|||||||
; CHECK-LABEL: @test62(
|
; CHECK-LABEL: @test62(
|
||||||
; CHECK: ashr exact i32 %x, 3
|
; 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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user