aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-01-02 20:56:45 +0000
committerSanjay Patel <spatel@rotateright.com>2018-01-02 20:56:45 +0000
commit7811430588b390aece10b136fcb3af6d3d8e2722 (patch)
treec6301d8ca6f8bb4b56a60dfa105662fb024736d7 /llvm/lib/Analysis/ValueTracking.cpp
parent4c549c31bbbcc9372a678de45dc5fa5375f43080 (diff)
downloadllvm-7811430588b390aece10b136fcb3af6d3d8e2722.zip
llvm-7811430588b390aece10b136fcb3af6d3d8e2722.tar.gz
llvm-7811430588b390aece10b136fcb3af6d3d8e2722.tar.bz2
[ValueTracking] recognize min/max of min/max patterns
This is part of solving PR35717: https://bugs.llvm.org/show_bug.cgi?id=35717 The larger IR optimization is proposed in D41603, but we can show the improvement in ValueTracking using codegen tests because SelectionDAG creates min/max nodes based on ValueTracking. Any target with min/max ops should show wins here. I chose AArch64 vector ops because they're clean and uniform. Some Alive proofs for the tests (can't put more than 2 tests in 1 page currently because the web app says it's too long): https://rise4fun.com/Alive/WRN https://rise4fun.com/Alive/iPm https://rise4fun.com/Alive/HmY https://rise4fun.com/Alive/CNm https://rise4fun.com/Alive/LYf llvm-svn: 321672
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp79
1 files changed, 79 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 9a4a69c..a0032f9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4161,6 +4161,81 @@ static SelectPatternResult matchClamp(CmpInst::Predicate Pred,
return {SPF_UNKNOWN, SPNB_NA, false};
}
+/// Recognize variations of:
+/// a < c ? min(a,b) : min(b,c) ==> min(min(a,b),min(b,c))
+static SelectPatternResult matchMinMaxOfMinMax(CmpInst::Predicate Pred,
+ Value *CmpLHS, Value *CmpRHS,
+ Value *TrueVal, Value *FalseVal) {
+ // TODO: Allow FP min/max with nnan/nsz.
+ assert(CmpInst::isIntPredicate(Pred) && "Expected integer comparison");
+
+ Value *A, *B;
+ SelectPatternResult L = matchSelectPattern(TrueVal, A, B);
+ if (!SelectPatternResult::isMinOrMax(L.Flavor))
+ return {SPF_UNKNOWN, SPNB_NA, false};
+
+ Value *C, *D;
+ SelectPatternResult R = matchSelectPattern(FalseVal, C, D);
+ if (L.Flavor != R.Flavor)
+ return {SPF_UNKNOWN, SPNB_NA, false};
+
+ // Match the compare to the min/max operations of the select operands.
+ switch (L.Flavor) {
+ case SPF_SMIN:
+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ std::swap(CmpLHS, CmpRHS);
+ }
+ if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
+ break;
+ return {SPF_UNKNOWN, SPNB_NA, false};
+ case SPF_SMAX:
+ if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) {
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ std::swap(CmpLHS, CmpRHS);
+ }
+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE)
+ break;
+ return {SPF_UNKNOWN, SPNB_NA, false};
+ case SPF_UMIN:
+ if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) {
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ std::swap(CmpLHS, CmpRHS);
+ }
+ if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE)
+ break;
+ return {SPF_UNKNOWN, SPNB_NA, false};
+ case SPF_UMAX:
+ if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) {
+ Pred = ICmpInst::getSwappedPredicate(Pred);
+ std::swap(CmpLHS, CmpRHS);
+ }
+ if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE)
+ break;
+ return {SPF_UNKNOWN, SPNB_NA, false};
+ default:
+ llvm_unreachable("Bad flavor while matching min/max");
+ }
+
+ // 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};
+
+ // 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};
+
+ // 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};
+
+ // 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};
+
+ return {SPF_UNKNOWN, SPNB_NA, false};
+}
+
/// Match non-obvious integer minimum and maximum sequences.
static SelectPatternResult matchMinMax(CmpInst::Predicate Pred,
Value *CmpLHS, Value *CmpRHS,
@@ -4174,6 +4249,10 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred,
if (SPR.Flavor != SelectPatternFlavor::SPF_UNKNOWN)
return SPR;
+ SPR = matchMinMaxOfMinMax(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal);
+ if (SPR.Flavor != SelectPatternFlavor::SPF_UNKNOWN)
+ return SPR;
+
if (Pred != CmpInst::ICMP_SGT && Pred != CmpInst::ICMP_SLT)
return {SPF_UNKNOWN, SPNB_NA, false};