diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-01-02 20:56:45 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-01-02 20:56:45 +0000 |
commit | 7811430588b390aece10b136fcb3af6d3d8e2722 (patch) | |
tree | c6301d8ca6f8bb4b56a60dfa105662fb024736d7 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 4c549c31bbbcc9372a678de45dc5fa5375f43080 (diff) | |
download | llvm-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.cpp | 79 |
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}; |