Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1896,6 +1896,26 @@ isKnownNonZero(SI->getFalseValue(), DL, Depth, Q)) return true; } + // PHI + else if (PHINode *PN = dyn_cast(V)) { + // Try and detect a recurrence that monotonically increases from a + // starting value, as these are common as induction variables. + if (PN->getNumIncomingValues() == 2) { + Value *Op1 = PN->getIncomingValue(0); + Value *Op2 = PN->getIncomingValue(1); + if (isa(Op2) && !isa(Op1)) + std::swap(Op1, Op2); + if (ConstantInt *COp1 = dyn_cast(Op1)) { + if (!COp1->isZero() && !COp1->isNegative()) { + ConstantInt *X; + if (match(Op2, m_NSWAdd(m_Specific(PN), m_ConstantInt(X))) && + match(Op2, m_NUWAdd(m_Specific(PN), m_ConstantInt(X))) && + !X->isNegative()) + return true; + } + } + } + } if (!BitWidth) return false; APInt KnownZero(BitWidth, 0); Index: unittests/Analysis/ValueTrackingTest.cpp =================================================================== --- unittests/Analysis/ValueTrackingTest.cpp +++ unittests/Analysis/ValueTrackingTest.cpp @@ -70,8 +70,8 @@ class KnownValueTest : public testing::Test, public AssemblyParsingTestHelper { protected: - void expectKnownNonZero() { - EXPECT_TRUE(isKnownNonZero(A, M->getDataLayout())); + bool knownNonZero() { + return isKnownNonZero(A, M->getDataLayout()); } }; @@ -210,5 +210,35 @@ " ret i8 %A\n" "}\n" "!0 = !{ i8 1, i8 5 }\n"); - expectKnownNonZero(); + EXPECT_TRUE(knownNonZero()); +} + +TEST_F(KnownValueTest, MonotonicPHI) { + parseAssembly( + "define i8 @test(i8* %pq) {\n" + "entry:\n" + " br label %loop\n" + "loop:\n" + " %A = phi i8 [ 1, %entry ], [ %next, %loop ]\n" + " %next = add nsw nuw i8 %A, 1" + " br label %loop\n" + "exit:\n" + " unreachable\n" + "}\n"); + EXPECT_TRUE(knownNonZero()); +} + +TEST_F(KnownValueTest, MonotonicWrappingPHI) { + parseAssembly( + "define i8 @test(i8* %pq) {\n" + "entry:\n" + " br label %loop\n" + "loop:\n" + " %A = phi i8 [ 1, %entry ], [ %next, %loop ]\n" + " %next = add i8 %A, 1" + " br label %loop\n" + "exit:\n" + " unreachable\n" + "}\n"); + EXPECT_FALSE(knownNonZero()); }