-
Notifications
You must be signed in to change notification settings - Fork 13.5k
IR: introduce ICmpInst::isImpliedByMatchingCmp #122597
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: Ramkumar Ramachandra (artagnon) ChangesCreate an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information. Full diff: https://github.com/llvm/llvm-project/pull/122597.diff 5 Files Affected:
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 59eb5040988378..9a41971b63373c 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -1266,15 +1266,10 @@ class ICmpInst: public CmpInst {
return getFlippedSignednessPredicate(getPredicate());
}
- /// Determine if Pred1 implies Pred2 is true when two compares have matching
- /// operands.
- static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2);
-
- /// Determine if Pred1 implies Pred2 is false when two compares have matching
- /// operands.
- static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2);
+ /// Determine if Pred1 implies Pred2 is true, false, or if nothing can be
+ /// inferred about the implication, when two compares have matching operands.
+ static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2);
void setSameSign(bool B = true) {
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
index d7c1eda81c0060..34a7feb63bec45 100644
--- a/llvm/include/llvm/SandboxIR/Instruction.h
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -2547,13 +2547,9 @@ class ICmpInst : public CmpInst {
WRAP_STATIC_PREDICATE(isGE);
WRAP_STATIC_PREDICATE(isLE);
- static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return llvm::ICmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
- }
- static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return llvm::ICmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
+ static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ return llvm::ICmpInst::isImpliedByMatchingCmp(Pred1, Pred2);
}
static auto predicates() { return llvm::ICmpInst::predicates(); }
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 92338d33b27a43..554f05be84ae1c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9384,19 +9384,6 @@ isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
}
}
-/// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true.
-/// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false.
-/// Otherwise, return std::nullopt if we can't infer anything.
-static std::optional<bool> isImpliedCondMatchingOperands(CmpPredicate LPred,
- CmpPredicate RPred) {
- if (ICmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
- return true;
- if (ICmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
- return false;
-
- return std::nullopt;
-}
-
/// Return true if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is true.
/// Return false if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is false.
/// Otherwise, return std::nullopt if we can't infer anything.
@@ -9489,7 +9476,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
// Can we infer anything when the two compares have matching operands?
if (L0 == R0 && L1 == R1)
- return isImpliedCondMatchingOperands(LPred, RPred);
+ return ICmpInst::isImpliedByMatchingCmp(LPred, RPred);
// It only really makes sense in the context of signed comparison for "X - Y
// must be positive if X >= Y and no overflow".
@@ -9498,7 +9485,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
if ((LPred == ICmpInst::ICMP_SGT || LPred == ICmpInst::ICMP_SGE) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonPositive()) &&
- isImpliedCondMatchingOperands(LPred, RPred) == false)
+ ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == false)
return false;
}
@@ -9507,7 +9494,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
if ((LPred == ICmpInst::ICMP_SLT || LPred == ICmpInst::ICMP_SLE) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonNegative()) &&
- isImpliedCondMatchingOperands(LPred, RPred) == true)
+ ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == true)
return true;
}
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 49c148bb68a4d3..b8b2c1d7f9a859 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3886,8 +3886,7 @@ bool CmpInst::isFalseWhenEqual(Predicate predicate) {
}
}
-bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
+static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1, CmpPredicate Pred2) {
// If the predicates match, then we know the first condition implies the
// second is true.
if (CmpPredicate::getMatching(Pred1, Pred2))
@@ -3901,25 +3900,35 @@ bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
switch (Pred1) {
default:
break;
- case ICMP_EQ:
+ case CmpInst::ICMP_EQ:
// A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are true.
- return Pred2 == ICMP_UGE || Pred2 == ICMP_ULE || Pred2 == ICMP_SGE ||
- Pred2 == ICMP_SLE;
- case ICMP_UGT: // A >u B implies A != B and A >=u B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_UGE;
- case ICMP_ULT: // A <u B implies A != B and A <=u B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_ULE;
- case ICMP_SGT: // A >s B implies A != B and A >=s B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_SGE;
- case ICMP_SLT: // A <s B implies A != B and A <=s B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_SLE;
+ return Pred2 == CmpInst::ICMP_UGE || Pred2 == CmpInst::ICMP_ULE ||
+ Pred2 == CmpInst::ICMP_SGE || Pred2 == CmpInst::ICMP_SLE;
+ case CmpInst::ICMP_UGT: // A >u B implies A != B and A >=u B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_UGE;
+ case CmpInst::ICMP_ULT: // A <u B implies A != B and A <=u B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_ULE;
+ case CmpInst::ICMP_SGT: // A >s B implies A != B and A >=s B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SGE;
+ case CmpInst::ICMP_SLT: // A <s B implies A != B and A <=s B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SLE;
}
return false;
}
-bool ICmpInst::isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
+static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ return isImpliedTrueByMatchingCmp(Pred1,
+ ICmpInst::getInverseCmpPredicate(Pred2));
+}
+
+std::optional<bool> ICmpInst::isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ if (isImpliedTrueByMatchingCmp(Pred1, Pred2))
+ return true;
+ if (isImpliedFalseByMatchingCmp(Pred1, Pred2))
+ return false;
+ return std::nullopt;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 3812e99508f738..580d93068b7215 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -1964,18 +1964,11 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
if (PBranch->TrueEdge) {
// If we know the previous predicate is true and we are in the true
// edge then we may be implied true or false.
- if (ICmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
- OurPredicate)) {
- return ExprResult::some(
- createConstantExpression(ConstantInt::getTrue(CI->getType())),
- PI);
- }
-
- if (ICmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
- OurPredicate)) {
- return ExprResult::some(
- createConstantExpression(ConstantInt::getFalse(CI->getType())),
- PI);
+ if (auto R = ICmpInst::isImpliedByMatchingCmp(BranchPredicate,
+ OurPredicate)) {
+ auto *C = *R ? ConstantInt::getTrue(CI->getType())
+ : ConstantInt::getFalse(CI->getType());
+ return ExprResult::some(createConstantExpression(C), PI);
}
} else {
// Just handle the ne and eq cases, where if we have the same
|
@llvm/pr-subscribers-llvm-ir Author: Ramkumar Ramachandra (artagnon) ChangesCreate an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information. Full diff: https://github.com/llvm/llvm-project/pull/122597.diff 5 Files Affected:
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 59eb5040988378..9a41971b63373c 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -1266,15 +1266,10 @@ class ICmpInst: public CmpInst {
return getFlippedSignednessPredicate(getPredicate());
}
- /// Determine if Pred1 implies Pred2 is true when two compares have matching
- /// operands.
- static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2);
-
- /// Determine if Pred1 implies Pred2 is false when two compares have matching
- /// operands.
- static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2);
+ /// Determine if Pred1 implies Pred2 is true, false, or if nothing can be
+ /// inferred about the implication, when two compares have matching operands.
+ static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2);
void setSameSign(bool B = true) {
SubclassOptionalData = (SubclassOptionalData & ~SameSign) | (B * SameSign);
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
index d7c1eda81c0060..34a7feb63bec45 100644
--- a/llvm/include/llvm/SandboxIR/Instruction.h
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -2547,13 +2547,9 @@ class ICmpInst : public CmpInst {
WRAP_STATIC_PREDICATE(isGE);
WRAP_STATIC_PREDICATE(isLE);
- static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return llvm::ICmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
- }
- static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return llvm::ICmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
+ static std::optional<bool> isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ return llvm::ICmpInst::isImpliedByMatchingCmp(Pred1, Pred2);
}
static auto predicates() { return llvm::ICmpInst::predicates(); }
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 92338d33b27a43..554f05be84ae1c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9384,19 +9384,6 @@ isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
}
}
-/// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true.
-/// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false.
-/// Otherwise, return std::nullopt if we can't infer anything.
-static std::optional<bool> isImpliedCondMatchingOperands(CmpPredicate LPred,
- CmpPredicate RPred) {
- if (ICmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
- return true;
- if (ICmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
- return false;
-
- return std::nullopt;
-}
-
/// Return true if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is true.
/// Return false if "icmp LPred X, LCR" implies "icmp RPred X, RCR" is false.
/// Otherwise, return std::nullopt if we can't infer anything.
@@ -9489,7 +9476,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
// Can we infer anything when the two compares have matching operands?
if (L0 == R0 && L1 == R1)
- return isImpliedCondMatchingOperands(LPred, RPred);
+ return ICmpInst::isImpliedByMatchingCmp(LPred, RPred);
// It only really makes sense in the context of signed comparison for "X - Y
// must be positive if X >= Y and no overflow".
@@ -9498,7 +9485,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
if ((LPred == ICmpInst::ICMP_SGT || LPred == ICmpInst::ICMP_SGE) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonPositive()) &&
- isImpliedCondMatchingOperands(LPred, RPred) == false)
+ ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == false)
return false;
}
@@ -9507,7 +9494,7 @@ isImpliedCondICmps(const ICmpInst *LHS, CmpPredicate RPred, const Value *R0,
if ((LPred == ICmpInst::ICMP_SLT || LPred == ICmpInst::ICMP_SLE) &&
match(R0, m_NSWSub(m_Specific(L0), m_Specific(L1)))) {
if (match(R1, m_NonNegative()) &&
- isImpliedCondMatchingOperands(LPred, RPred) == true)
+ ICmpInst::isImpliedByMatchingCmp(LPred, RPred) == true)
return true;
}
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 49c148bb68a4d3..b8b2c1d7f9a859 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3886,8 +3886,7 @@ bool CmpInst::isFalseWhenEqual(Predicate predicate) {
}
}
-bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
+static bool isImpliedTrueByMatchingCmp(CmpPredicate Pred1, CmpPredicate Pred2) {
// If the predicates match, then we know the first condition implies the
// second is true.
if (CmpPredicate::getMatching(Pred1, Pred2))
@@ -3901,25 +3900,35 @@ bool ICmpInst::isImpliedTrueByMatchingCmp(CmpPredicate Pred1,
switch (Pred1) {
default:
break;
- case ICMP_EQ:
+ case CmpInst::ICMP_EQ:
// A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are true.
- return Pred2 == ICMP_UGE || Pred2 == ICMP_ULE || Pred2 == ICMP_SGE ||
- Pred2 == ICMP_SLE;
- case ICMP_UGT: // A >u B implies A != B and A >=u B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_UGE;
- case ICMP_ULT: // A <u B implies A != B and A <=u B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_ULE;
- case ICMP_SGT: // A >s B implies A != B and A >=s B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_SGE;
- case ICMP_SLT: // A <s B implies A != B and A <=s B are true.
- return Pred2 == ICMP_NE || Pred2 == ICMP_SLE;
+ return Pred2 == CmpInst::ICMP_UGE || Pred2 == CmpInst::ICMP_ULE ||
+ Pred2 == CmpInst::ICMP_SGE || Pred2 == CmpInst::ICMP_SLE;
+ case CmpInst::ICMP_UGT: // A >u B implies A != B and A >=u B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_UGE;
+ case CmpInst::ICMP_ULT: // A <u B implies A != B and A <=u B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_ULE;
+ case CmpInst::ICMP_SGT: // A >s B implies A != B and A >=s B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SGE;
+ case CmpInst::ICMP_SLT: // A <s B implies A != B and A <=s B are true.
+ return Pred2 == CmpInst::ICMP_NE || Pred2 == CmpInst::ICMP_SLE;
}
return false;
}
-bool ICmpInst::isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
- CmpPredicate Pred2) {
- return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
+static bool isImpliedFalseByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ return isImpliedTrueByMatchingCmp(Pred1,
+ ICmpInst::getInverseCmpPredicate(Pred2));
+}
+
+std::optional<bool> ICmpInst::isImpliedByMatchingCmp(CmpPredicate Pred1,
+ CmpPredicate Pred2) {
+ if (isImpliedTrueByMatchingCmp(Pred1, Pred2))
+ return true;
+ if (isImpliedFalseByMatchingCmp(Pred1, Pred2))
+ return false;
+ return std::nullopt;
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 3812e99508f738..580d93068b7215 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -1964,18 +1964,11 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
if (PBranch->TrueEdge) {
// If we know the previous predicate is true and we are in the true
// edge then we may be implied true or false.
- if (ICmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
- OurPredicate)) {
- return ExprResult::some(
- createConstantExpression(ConstantInt::getTrue(CI->getType())),
- PI);
- }
-
- if (ICmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
- OurPredicate)) {
- return ExprResult::some(
- createConstantExpression(ConstantInt::getFalse(CI->getType())),
- PI);
+ if (auto R = ICmpInst::isImpliedByMatchingCmp(BranchPredicate,
+ OurPredicate)) {
+ auto *C = *R ? ConstantInt::getTrue(CI->getType())
+ : ConstantInt::getFalse(CI->getType());
+ return ExprResult::some(createConstantExpression(C), PI);
}
} else {
// Just handle the ne and eq cases, where if we have the same
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add some positive tests (this patch is not a NFC).
You can extract tests from https://github.com/dtcxzyw/llvm-opt-benchmark/pull/1956/files.
Create an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information.
0247dae
to
9afe0c4
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/27/builds/4581 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/12728 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/11002 Here is the relevant piece of the build log for the reference
|
Create an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information.
Create an abstraction over isImplied{True,False}ByMatchingCmp to faithfully communicate the result of both functions, cleaning up code in callsites. While at it, fix a bug in the implied-false version of the function, which was inadvertedenly dropping samesign information.