Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ include/llvm/Analysis/ValueTracking.h @@ -90,6 +90,13 @@ const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); + /// isKnownNonEqual - Return true if the given values are known to be + /// non-equal when defined. Supports scalar integer types only. + bool isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); + /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be /// zero for bits that V cannot have. Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -193,6 +193,17 @@ return NonNegative; } +static bool isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL, + const Query &Q); + +bool llvm::isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL, + AssumptionCache *AC, const Instruction *CxtI, + const DominatorTree *DT) { + return ::isKnownNonEqual(V1, V2, DL, Query(AC, + safeCxtI(V1, safeCxtI(V2, CxtI)), + DT)); +} + static bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout &DL, unsigned Depth, const Query &Q); @@ -1924,6 +1935,36 @@ return KnownOne != 0; } +/// Return true if V2 == V1 + X, where X is known non-zero. +static bool isAddOfNonZero(Value *V1, Value *V2, const DataLayout &DL, + const Query &Q) { + BinaryOperator *BO = dyn_cast(V1); + if (!BO || BO->getOpcode() != Instruction::Add) + return false; + Value *Op = nullptr; + if (V2 == BO->getOperand(0)) + Op = BO->getOperand(1); + else if (V2 == BO->getOperand(1)) + Op = BO->getOperand(0); + else + return false; + return isKnownNonZero(Op, DL, 0, Q) && + (BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()); +} + +/// Return true if it is known that V1 != V2. +static bool isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL, + const Query &Q) { + if (V1->getType()->isVectorTy() || V1 == V2) + return false; + if (V1->getType() != V2->getType()) + // We can't look through casts yet. + return false; + if (isAddOfNonZero(V1, V2, DL, Q) || isAddOfNonZero(V2, V1, DL, Q)) + return true; + return false; +} + /// Return true if 'V & Mask' is known to be zero. We use this predicate to /// simplify operations downstream. Mask is known to be zero for bits that V /// cannot have. Index: unittests/Analysis/ValueTrackingTest.cpp =================================================================== --- unittests/Analysis/ValueTrackingTest.cpp +++ unittests/Analysis/ValueTrackingTest.cpp @@ -46,12 +46,19 @@ A = &*I; } } + B = nullptr; + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (I->hasName()) { + if (I->getName() == "B") + B = &*I; + } + } if (A == nullptr) report_fatal_error("@test must have an instruction %A"); } std::unique_ptr M; - Instruction *A; + Instruction *A, *B; }; class MatchSelectPatternTest : public testing::Test, @@ -73,6 +80,11 @@ bool knownNonZero() { return isKnownNonZero(A, M->getDataLayout()); } + + bool knownNonEqual() { + assert(B && "B must be defined!"); + return isKnownNonEqual(A, B, M->getDataLayout()); + } }; } @@ -230,7 +242,7 @@ TEST_F(KnownValueTest, MonotonicWrappingPHI) { parseAssembly( - "define i8 @test(i8* %pq) {\n" + "define i8 @test() {\n" "entry:\n" " br label %loop\n" "loop:\n" @@ -242,3 +254,27 @@ "}\n"); EXPECT_FALSE(knownNonZero()); } + +TEST_F(KnownValueTest, KnownNonEqual1) { + parseAssembly( + "define i8 @test(i8* %pq, i8 %rB) {\n" + " %B = add i8 %rB, 0\n" + " %q = load i8, i8* %pq, !range !0\n" // %q is known nonzero; no known bits + " %A = add nsw i8 %B, %q\n" + " ret i8 %A\n" + "}\n" + "!0 = !{ i8 1, i8 5 }\n"); + EXPECT_TRUE(knownNonEqual()); +}; + +TEST_F(KnownValueTest, KnownNonEqualWrapping) { + parseAssembly( + "define i8 @test(i8* %pq, i8 %rB) {\n" + " %B = add i8 %rB, 0\n" + " %q = load i8, i8* %pq, !range !0\n" // %q is known nonzero; no known bits + " %A = add i8 %B, %q\n" + " ret i8 %A\n" + "}\n" + "!0 = !{ i8 1, i8 5 }\n"); + EXPECT_FALSE(knownNonEqual()); +};