Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1824,6 +1824,19 @@ 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)) + if (Shift->getLimitedValue() < BitWidth) { + APInt KnownZero(BitWidth, 0); + APInt KnownOne(BitWidth, 0); + computeKnownBits(X, KnownZero, KnownOne, DL, Depth, Q); + APInt LoBits = APInt::getLowBitsSet(BitWidth, Shift->getLimitedValue()); + if ((KnownZero & LoBits).eq(LoBits)) + return KnownOne.getBoolValue() || 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: unittests/Analysis/ValueTrackingTest.cpp =================================================================== --- unittests/Analysis/ValueTrackingTest.cpp +++ unittests/Analysis/ValueTrackingTest.cpp @@ -21,7 +21,7 @@ namespace { -class MatchSelectPatternTest : public testing::Test { +class AssemblyParsingTestHelper { protected: void parseAssembly(const char *Assembly) { SMDiagnostic Error; @@ -50,6 +50,13 @@ report_fatal_error("@test must have an instruction %A"); } + std::unique_ptr M; + Instruction *A; +}; + +class MatchSelectPatternTest : public testing::Test, + public AssemblyParsingTestHelper { +protected: void expectPattern(const SelectPatternResult &P) { Value *LHS, *RHS; Instruction::CastOps CastOp; @@ -58,11 +65,16 @@ EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); EXPECT_EQ(P.Ordered, R.Ordered); } - - std::unique_ptr M; - Instruction *A, *B; }; +class KnownValueTest : public testing::Test, + public AssemblyParsingTestHelper { +protected: + void expectKnownNonZero() { + EXPECT_TRUE(isKnownNonZero(A, M->getDataLayout())); + } +}; + } TEST_F(MatchSelectPatternTest, SimpleFMin) { @@ -187,3 +199,16 @@ // The cast types here aren't the same, so we cannot match an UMIN. expectPattern({SPF_UNKNOWN, SPNB_NA, false}); } + +TEST_F(KnownValueTest, NonZeroShiftRight) { + parseAssembly( + "define i8 @test(i8 %p, i8* %pq) {\n" + " %q = load i8, i8* %pq, !range !0\n" // %q is known nonzero; no known bits + " %1 = or i8 %p, 1\n" // %1[0] = 1, %1 is odd + " %2 = shl i8 %1, %q\n" // %2[0] = 0, rest unknown but cannot be zero + " %A = lshr i8 %2, 1\n" // We should know that %A is nonzero. + " ret i8 %A\n" + "}\n" + "!0 = !{ i8 1, i8 5 }\n"); + expectKnownNonZero(); +}