diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -553,11 +553,25 @@ if (SimplifyDemandedBits(I, 0, DemandedMaskIn, Known, Depth + 1)) return I; assert(!Known.hasConflict() && "Bits known to be one AND zero?"); + + bool SignBitZero = Known.Zero.isSignBitSet(); + bool SignBitOne = Known.One.isSignBitSet(); Known.Zero <<= ShiftAmt; Known.One <<= ShiftAmt; // low bits known zero. if (ShiftAmt) Known.Zero.setLowBits(ShiftAmt); + + // If this shift has "nsw" keyword, then the result is either a poison + // value or has the same sign bit as the first operand. + if (IOp->hasNoSignedWrap()) { + if (SignBitZero) + Known.Zero.setSignBit(); + else if (SignBitOne) + Known.One.setSignBit(); + if (Known.hasConflict()) + return UndefValue::get(I->getType()); + } } else { computeKnownBits(I, Known, Depth, CxtI); } diff --git a/llvm/test/Transforms/InstCombine/known-signbit-shift.ll b/llvm/test/Transforms/InstCombine/known-signbit-shift.ll --- a/llvm/test/Transforms/InstCombine/known-signbit-shift.ll +++ b/llvm/test/Transforms/InstCombine/known-signbit-shift.ll @@ -31,8 +31,7 @@ ; This test should not crash opt. The shift produces poison. define i32 @test_no_sign_bit_conflict1(i1 %b) { ; EXPENSIVE-OFF-LABEL: @test_no_sign_bit_conflict1( -; EXPENSIVE-OFF-NEXT: [[SEL:%.*]] = select i1 [[B:%.*]], i32 -2147221504, i32 -2147483648 -; EXPENSIVE-OFF-NEXT: ret i32 [[SEL]] +; EXPENSIVE-OFF-NEXT: ret i32 undef ; ; EXPENSIVE-ON-LABEL: @test_no_sign_bit_conflict1( ; EXPENSIVE-ON-NEXT: ret i32 0 @@ -46,8 +45,7 @@ ; This test should not crash opt. The shift produces poison. define i32 @test_no_sign_bit_conflict2(i1 %b) { ; EXPENSIVE-OFF-LABEL: @test_no_sign_bit_conflict2( -; EXPENSIVE-OFF-NEXT: [[SEL:%.*]] = select i1 [[B:%.*]], i32 2147221504, i32 2146959360 -; EXPENSIVE-OFF-NEXT: ret i32 [[SEL]] +; EXPENSIVE-OFF-NEXT: ret i32 undef ; ; EXPENSIVE-ON-LABEL: @test_no_sign_bit_conflict2( ; EXPENSIVE-ON-NEXT: ret i32 0