From a8517ee7329636e3b2862784f1abf1f8d892fee7 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Fri, 30 Aug 2013 14:35:35 +0000 Subject: [PATCH] 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 --- .../InstCombineSimplifyDemanded.cpp | 25 +++++++------ test/Transforms/InstCombine/shift.ll | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index a7bfe0965b0..a2492d87c01 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -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(Shl->getOperand(1))->getZExtValue(); - unsigned ShrAmt = cast(Shr->getOperand(1))->getZExtValue(); + const APInt &ShlOp1 = cast(Shl->getOperand(1))->getValue(); + const APInt &ShrOp1 = cast(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) : diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 0bdab139b7c..b1082f06ef7 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -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 +}