summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp43
1 files changed, 31 insertions, 12 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index b8f6066bf05..6a322438f5a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4179,7 +4179,9 @@ static SelectPatternResult matchMinMaxOfMinMax(CmpInst::Predicate Pred,
if (L.Flavor != R.Flavor)
return {SPF_UNKNOWN, SPNB_NA, false};
- // Match the compare to the min/max operations of the select operands.
+ // We have something like: x Pred y ? min(a, b) : min(c, d).
+ // Try to match the compare to the min/max operations of the select operands.
+ // First, make sure we have the right compare predicate.
switch (L.Flavor) {
case SPF_SMIN:
if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
@@ -4217,21 +4219,38 @@ static SelectPatternResult matchMinMaxOfMinMax(CmpInst::Predicate Pred,
return {SPF_UNKNOWN, SPNB_NA, false};
}
- // a pred c ? m(a, b) : m(c, b) --> m(m(a, b), m(c, b))
- if (CmpLHS == A && CmpRHS == C && D == B)
- return {L.Flavor, SPNB_NA, false};
+ // If there is a common operand in the already matched min/max and the other
+ // min/max operands match the compare operands (either directly or inverted),
+ // then this is min/max of the same flavor.
+ // a pred c ? m(a, b) : m(c, b) --> m(m(a, b), m(c, b))
+ // ~c pred ~a ? m(a, b) : m(c, b) --> m(m(a, b), m(c, b))
+ if (D == B) {
+ if ((CmpLHS == A && CmpRHS == C) || (match(C, m_Not(m_Specific(CmpLHS))) &&
+ match(A, m_Not(m_Specific(CmpRHS)))))
+ return {L.Flavor, SPNB_NA, false};
+ }
// a pred d ? m(a, b) : m(b, d) --> m(m(a, b), m(b, d))
- if (CmpLHS == A && CmpRHS == D && C == B)
- return {L.Flavor, SPNB_NA, false};
-
+ // ~d pred ~a ? m(a, b) : m(b, d) --> m(m(a, b), m(b, d))
+ if (C == B) {
+ if ((CmpLHS == A && CmpRHS == D) || (match(D, m_Not(m_Specific(CmpLHS))) &&
+ match(A, m_Not(m_Specific(CmpRHS)))))
+ return {L.Flavor, SPNB_NA, false};
+ }
// b pred c ? m(a, b) : m(c, a) --> m(m(a, b), m(c, a))
- if (CmpLHS == B && CmpRHS == C && D == A)
- return {L.Flavor, SPNB_NA, false};
-
+ // ~c pred ~b ? m(a, b) : m(c, a) --> m(m(a, b), m(c, a))
+ if (D == A) {
+ if ((CmpLHS == B && CmpRHS == C) || (match(C, m_Not(m_Specific(CmpLHS))) &&
+ match(B, m_Not(m_Specific(CmpRHS)))))
+ return {L.Flavor, SPNB_NA, false};
+ }
// b pred d ? m(a, b) : m(a, d) --> m(m(a, b), m(a, d))
- if (CmpLHS == B && CmpRHS == D && C == A)
- return {L.Flavor, SPNB_NA, false};
+ // ~d pred ~b ? m(a, b) : m(a, d) --> m(m(a, b), m(a, d))
+ if (C == A) {
+ if ((CmpLHS == B && CmpRHS == D) || (match(D, m_Not(m_Specific(CmpLHS))) &&
+ match(B, m_Not(m_Specific(CmpRHS)))))
+ return {L.Flavor, SPNB_NA, false};
+ }
return {SPF_UNKNOWN, SPNB_NA, false};
}
OpenPOWER on IntegriCloud