summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-03-18 20:44:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-03-18 20:44:40 +0000
commite39dad62a8554a48fed27bf81f5e43c0d42e727a (patch)
treeccdaf66a137580596ee7fc4388797f278d7503ef
parent5a0c326f6389b80a22ccc7fbb8cabef47d0e3b71 (diff)
Notes
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp51
1 files changed, 44 insertions, 7 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index 40c1ba88354f..55d3761c036f 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -152,13 +152,50 @@ static bool matchSelectWithOptionalNotCond(Value *V, Value *&Cond, Value *&A,
std::swap(A, B);
}
- // Set flavor if we find a match, or set it to unknown otherwise; in
- // either case, return true to indicate that this is a select we can
- // process.
- if (auto *CmpI = dyn_cast<ICmpInst>(Cond))
- Flavor = matchDecomposedSelectPattern(CmpI, A, B, A, B).Flavor;
- else
- Flavor = SPF_UNKNOWN;
+ // Match canonical forms of abs/nabs/min/max. We are not using ValueTracking's
+ // more powerful matchSelectPattern() because it may rely on instruction flags
+ // such as "nsw". That would be incompatible with the current hashing
+ // mechanism that may remove flags to increase the likelihood of CSE.
+
+ // These are the canonical forms of abs(X) and nabs(X) created by instcombine:
+ // %N = sub i32 0, %X
+ // %C = icmp slt i32 %X, 0
+ // %ABS = select i1 %C, i32 %N, i32 %X
+ //
+ // %N = sub i32 0, %X
+ // %C = icmp slt i32 %X, 0
+ // %NABS = select i1 %C, i32 %X, i32 %N
+ Flavor = SPF_UNKNOWN;
+ CmpInst::Predicate Pred;
+ if (match(Cond, m_ICmp(Pred, m_Specific(B), m_ZeroInt())) &&
+ Pred == ICmpInst::ICMP_SLT && match(A, m_Neg(m_Specific(B)))) {
+ // ABS: B < 0 ? -B : B
+ Flavor = SPF_ABS;
+ return true;
+ }
+ if (match(Cond, m_ICmp(Pred, m_Specific(A), m_ZeroInt())) &&
+ Pred == ICmpInst::ICMP_SLT && match(B, m_Neg(m_Specific(A)))) {
+ // NABS: A < 0 ? A : -A
+ Flavor = SPF_NABS;
+ return true;
+ }
+
+ if (!match(Cond, m_ICmp(Pred, m_Specific(A), m_Specific(B)))) {
+ // Check for commuted variants of min/max by swapping predicate.
+ // If we do not match the standard or commuted patterns, this is not a
+ // recognized form of min/max, but it is still a select, so return true.
+ if (!match(Cond, m_ICmp(Pred, m_Specific(B), m_Specific(A))))
+ return true;
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ }
+
+ switch (Pred) {
+ case CmpInst::ICMP_UGT: Flavor = SPF_UMAX; break;
+ case CmpInst::ICMP_ULT: Flavor = SPF_UMIN; break;
+ case CmpInst::ICMP_SGT: Flavor = SPF_SMAX; break;
+ case CmpInst::ICMP_SLT: Flavor = SPF_SMIN; break;
+ default: break;
+ }
return true;
}