Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1824,6 +1824,23 @@ ComputeSignBit(X, XKnownNonNegative, XKnownNegative, DL, Depth, Q); if (XKnownNegative) return true; + + // If the shifter operand is a constant, and all of the bits shifted + // out are known to be zero, and X is known non-zero then at least one + // non-zero bit must remain. + if (ConstantInt *Shift = dyn_cast(Y)) { + APInt KnownZero(BitWidth, 0); + APInt KnownOne(BitWidth, 0); + computeKnownBits(X, KnownZero, KnownOne, DL, Depth, Q); + + auto ShiftVal = Shift->getLimitedValue(BitWidth - 1); + // Is there a known one in the portion not shifted out? + if (KnownOne.countLeadingZeros() < BitWidth - ShiftVal) + return true; + // Are all the bits to be shifted out known zero? + if (KnownZero.countTrailingOnes() >= ShiftVal) + return isKnownNonZero(X, DL, Depth, Q); + } } // div exact can only produce a zero if the dividend is zero. else if (match(V, m_Exact(m_IDiv(m_Value(X), m_Value())))) { Index: test/Analysis/ValueTracking/knownzero-shift.ll =================================================================== --- /dev/null +++ test/Analysis/ValueTracking/knownzero-shift.ll @@ -0,0 +1,15 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s + +; CHECK-LABEL: @test +define i8 @test(i8 %p, i8* %pq) { + %q = load i8, i8* %pq, !range !0 ; %q is known nonzero; no known bits + %1 = or i8 %p, 1 ; %1[0] = 1, %1 is odd + %2 = shl i8 %1, %q ; %2[0] = 0, rest unknown but cannot be zero + %A = lshr i8 %2, 1 ; We should know that %A is nonzero. + %x = icmp eq i8 %A, 0 + %y = select i1 %x, i8 6, i8 7 ; ... and should return i8 7. + ; CHECK: ret i8 7 + ret i8 %y +} + +!0 = !{ i8 1, i8 5 }