[llvm] r251012 - [ValueTracking] Add a new predicate: isKnownNonEqual()
James Molloy via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 22 06:18:44 PDT 2015
Author: jamesm
Date: Thu Oct 22 08:18:42 2015
New Revision: 251012
URL: http://llvm.org/viewvc/llvm-project?rev=251012&view=rev
Log:
[ValueTracking] Add a new predicate: isKnownNonEqual()
isKnownNonEqual(A, B) returns true if it can be determined that A != B.
At the moment it only knows two facts, that a non-wrapping add of nonzero to a value cannot be that value:
A + B != A [where B != 0, addition is nsw or nuw]
and that contradictory known bits imply two values are not equal.
This patch also hooks this up to InstSimplify; InstSimplify had a peephole for the first fact but not the second so this teaches InstSimplify a new trick too (alas no measured performance impact!)
Added:
llvm/trunk/test/Analysis/ValueTracking/known-non-equal.ll
Modified:
llvm/trunk/include/llvm/Analysis/ValueTracking.h
llvm/trunk/lib/Analysis/InstructionSimplify.cpp
llvm/trunk/lib/Analysis/ValueTracking.cpp
Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=251012&r1=251011&r2=251012&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original)
+++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Thu Oct 22 08:18:42 2015
@@ -90,6 +90,13 @@ namespace llvm {
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.
Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=251012&r1=251011&r2=251012&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Oct 22 08:18:42 2015
@@ -2642,6 +2642,14 @@ static Value *SimplifyICmpInst(unsigned
}
}
+ // icmp eq|ne X, Y -> false|true if X != Y
+ if ((Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE) &&
+ isKnownNonEqual(LHS, RHS, Q.DL, Q.AC, Q.CxtI, Q.DT)) {
+ LLVMContext &Ctx = LHS->getType()->getContext();
+ return Pred == ICmpInst::ICMP_NE ?
+ ConstantInt::getTrue(Ctx) : ConstantInt::getFalse(Ctx);
+ }
+
// Special logic for binary operators.
BinaryOperator *LBO = dyn_cast<BinaryOperator>(LHS);
BinaryOperator *RBO = dyn_cast<BinaryOperator>(RHS);
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=251012&r1=251011&r2=251012&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Thu Oct 22 08:18:42 2015
@@ -193,6 +193,17 @@ bool llvm::isKnownNonNegative(Value *V,
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);
@@ -1950,6 +1961,51 @@ bool isKnownNonZero(Value *V, const Data
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<BinaryOperator>(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);
+}
+
+/// 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;
+
+ if (IntegerType *Ty = dyn_cast<IntegerType>(V1->getType())) {
+ // Are any known bits in V1 contradictory to known bits in V2? If V1
+ // has a known zero where V2 has a known one, they must not be equal.
+ auto BitWidth = Ty->getBitWidth();
+ APInt KnownZero1(BitWidth, 0);
+ APInt KnownOne1(BitWidth, 0);
+ computeKnownBits(V1, KnownZero1, KnownOne1, DL, 0, Q);
+ APInt KnownZero2(BitWidth, 0);
+ APInt KnownOne2(BitWidth, 0);
+ computeKnownBits(V2, KnownZero2, KnownOne2, DL, 0, Q);
+
+ auto OppositeBits = (KnownZero1 & KnownOne2) | (KnownZero2 & KnownOne1);
+ if (OppositeBits.getBoolValue())
+ 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.
Added: llvm/trunk/test/Analysis/ValueTracking/known-non-equal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ValueTracking/known-non-equal.ll?rev=251012&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ValueTracking/known-non-equal.ll (added)
+++ llvm/trunk/test/Analysis/ValueTracking/known-non-equal.ll Thu Oct 22 08:18:42 2015
@@ -0,0 +1,21 @@
+; RUN: opt -instsimplify < %s -S | FileCheck %s
+
+; CHECK: define i1 @test
+define i1 @test(i8* %pq, i8 %B) {
+ %q = load i8, i8* %pq, !range !0 ; %q is known nonzero; no known bits
+ %A = add nsw i8 %B, %q
+ %cmp = icmp eq i8 %A, %B
+ ; CHECK: ret i1 false
+ ret i1 %cmp
+}
+
+; CHECK: define i1 @test2
+define i1 @test2(i8 %a, i8 %b) {
+ %A = or i8 %a, 2 ; %A[1] = 1
+ %B = and i8 %b, -3 ; %B[1] = 0
+ %cmp = icmp eq i8 %A, %B ; %A[1] and %B[1] are contradictory.
+ ; CHECK: ret i1 false
+ ret i1 %cmp
+}
+
+!0 = !{ i8 1, i8 5 }
More information about the llvm-commits
mailing list