[llvm] r252331 - [ValueTracking] Add a framework for encoding implication rules
Sanjoy Das via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 6 11:00:58 PST 2015
Author: sanjoy
Date: Fri Nov 6 13:00:57 2015
New Revision: 252331
URL: http://llvm.org/viewvc/llvm-project?rev=252331&view=rev
Log:
[ValueTracking] Add a framework for encoding implication rules
Summary:
This change adds a framework for adding more smarts to
`isImpliedCondition` around inequalities. Informally,
`isImpliedCondition` will now try to prove "A < B ==> C < D" by proving
"C <= A && B <= D", since then it follows "C <= A < B <= D".
While this change is in principle NFC, I could not think of a way to not
handle cases like "i +_nsw 1 < L ==> i < L +_nsw 1" (that ValueTracking
did not handle before) while keeping the change understandable. I've
added tests for these cases.
Reviewers: reames, majnemer, hfinkel
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D14368
Modified:
llvm/trunk/lib/Analysis/ValueTracking.cpp
llvm/trunk/test/Transforms/InstSimplify/implies.ll
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=252331&r1=252330&r2=252331&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Fri Nov 6 13:00:57 2015
@@ -4082,6 +4082,65 @@ ConstantRange llvm::getConstantRangeFrom
return CR;
}
+/// Return true if "icmp Pred LHS RHS" is always true.
+static bool isTruePredicate(CmpInst::Predicate Pred, Value *LHS, Value *RHS) {
+ if (ICmpInst::isTrueWhenEqual(Pred) && LHS == RHS)
+ return true;
+
+ switch (Pred) {
+ default:
+ return false;
+
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE: {
+ ConstantInt *CI;
+
+ // LHS s< LHS +_{nsw} C if C > 0
+ // LHS s<= LHS +_{nsw} C if C >= 0
+ if (match(RHS, m_NSWAdd(m_Specific(LHS), m_ConstantInt(CI)))) {
+ if (Pred == CmpInst::ICMP_SLT)
+ return CI->getValue().isStrictlyPositive();
+ return !CI->isNegative();
+ }
+ return false;
+ }
+
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE: {
+ ConstantInt *CI;
+
+ // LHS u< LHS +_{nuw} C if C > 0
+ // LHS u<= LHS +_{nuw} C if C >= 0
+ if (match(RHS, m_NUWAdd(m_Specific(LHS), m_ConstantInt(CI)))) {
+ if (Pred == CmpInst::ICMP_ULT)
+ return CI->getValue().isStrictlyPositive();
+ return !CI->isNegative();
+ }
+ return false;
+ }
+ }
+}
+
+/// Return true if "icmp Pred BLHS BRHS" is true whenever "icmp Pred
+/// ALHS ARHS" is true.
+static bool isImpliedCondOperands(CmpInst::Predicate Pred, Value *ALHS,
+ Value *ARHS, Value *BLHS, Value *BRHS) {
+ switch (Pred) {
+ default:
+ return false;
+
+ case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE:
+ return isTruePredicate(CmpInst::ICMP_SLE, BLHS, ALHS) &&
+ isTruePredicate(CmpInst::ICMP_SLE, ARHS, BRHS);
+
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE:
+ return isTruePredicate(CmpInst::ICMP_ULE, BLHS, ALHS) &&
+ isTruePredicate(CmpInst::ICMP_ULE, ARHS, BRHS);
+ }
+}
+
bool llvm::isImpliedCondition(Value *LHS, Value *RHS) {
assert(LHS->getType() == RHS->getType() && "mismatched type");
Type *OpTy = LHS->getType();
@@ -4096,28 +4155,15 @@ bool llvm::isImpliedCondition(Value *LHS
assert(OpTy->isIntegerTy(1) && "implied by above");
ICmpInst::Predicate APred, BPred;
- Value *I;
- Value *L;
- ConstantInt *CI;
- // i +_{nsw} C_{>0} <s L ==> i <s L
- if (match(LHS, m_ICmp(APred,
- m_NSWAdd(m_Value(I), m_ConstantInt(CI)),
- m_Value(L))) &&
- APred == ICmpInst::ICMP_SLT &&
- !CI->isNegative() &&
- match(RHS, m_ICmp(BPred, m_Specific(I), m_Specific(L))) &&
- BPred == ICmpInst::ICMP_SLT)
- return true;
+ Value *ALHS, *ARHS;
+ Value *BLHS, *BRHS;
- // i +_{nuw} C_{>0} <u L ==> i <u L
- if (match(LHS, m_ICmp(APred,
- m_NUWAdd(m_Value(I), m_ConstantInt(CI)),
- m_Value(L))) &&
- APred == ICmpInst::ICMP_ULT &&
- !CI->isNegative() &&
- match(RHS, m_ICmp(BPred, m_Specific(I), m_Specific(L))) &&
- BPred == ICmpInst::ICMP_ULT)
- return true;
+ if (!match(LHS, m_ICmp(APred, m_Value(ALHS), m_Value(ARHS))) ||
+ !match(RHS, m_ICmp(BPred, m_Value(BLHS), m_Value(BRHS))))
+ return false;
+
+ if (APred == BPred)
+ return isImpliedCondOperands(APred, ALHS, ARHS, BLHS, BRHS);
return false;
}
Modified: llvm/trunk/test/Transforms/InstSimplify/implies.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/implies.ll?rev=252331&r1=252330&r2=252331&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/implies.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/implies.ll Fri Nov 6 13:00:57 2015
@@ -92,6 +92,30 @@ define <4 x i1> @test6(<4 x i1> %a, <4 x
ret <4 x i1> %res
}
+; i +_{nsw} 1 <s L ==> i < L +_{nsw} 1
+define i1 @test7(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test7(
+; CHECK: ret i1 true
+ %iplus1 = add nsw i32 %i, 1
+ %len.plus.one = add nsw i32 %length.i, 1
+ %var29 = icmp slt i32 %i, %len.plus.one
+ %var30 = icmp slt i32 %iplus1, %length.i
+ %res = icmp ule i1 %var30, %var29
+ ret i1 %res
+}
+
+; i +_{nuw} 1 <s L ==> i < L +_{nuw} 1
+define i1 @test8(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test8(
+; CHECK: ret i1 true
+ %iplus1 = add nuw i32 %i, 1
+ %len.plus.one = add nuw i32 %length.i, 1
+ %var29 = icmp ult i32 %i, %len.plus.one
+ %var30 = icmp ult i32 %iplus1, %length.i
+ %res = icmp ule i1 %var30, %var29
+ ret i1 %res
+}
+
; X >=(s) Y == X ==> Y (i1 1 becomes -1 for reasoning)
define i1 @test_sge(i32 %length.i, i32 %i) {
; CHECK-LABEL: @test_sge
More information about the llvm-commits
mailing list