diff options
author | Sanjay Patel <spatel@rotateright.com> | 2020-04-06 11:40:45 -0400 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2020-04-06 11:51:59 -0400 |
commit | fbb1b43f135a1af24cecbc7243d52fe6f85b7082 (patch) | |
tree | 7018e4dadd8d5ae6f8a4ba404eeadb765837b85f /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 2aa593be5486a9c5d3092647f2576273f84f3159 (diff) | |
download | llvm-fbb1b43f135a1af24cecbc7243d52fe6f85b7082.zip llvm-fbb1b43f135a1af24cecbc7243d52fe6f85b7082.tar.gz llvm-fbb1b43f135a1af24cecbc7243d52fe6f85b7082.tar.bz2 |
[ValueTracking] enhance matching of umin/umax with 'not' operands
The cmyk test is based on the known regression that resulted from:
rGf2fbdf76d8d0
This improves on the equivalent signed min/max change:
rG867f0c3c4d8c
The underlying icmp equivalence is:
~X pred ~Y --> Y pred X
For an icmp with constant, canonicalization results in a swapped pred:
~X < C --> X > ~C
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 01025ab..4fa43a3 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5157,6 +5157,31 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, if (SPR.Flavor != SelectPatternFlavor::SPF_UNKNOWN) return SPR; + // Look through 'not' ops to find disguised min/max. + // (X > Y) ? ~X : ~Y ==> (~X < ~Y) ? ~X : ~Y ==> MIN(~X, ~Y) + // (X < Y) ? ~X : ~Y ==> (~X > ~Y) ? ~X : ~Y ==> MAX(~X, ~Y) + if (CmpLHS == getNotValue(TrueVal) && CmpRHS == getNotValue(FalseVal)) { + switch (Pred) { + case CmpInst::ICMP_SGT: return {SPF_SMIN, SPNB_NA, false}; + case CmpInst::ICMP_SLT: return {SPF_SMAX, SPNB_NA, false}; + case CmpInst::ICMP_UGT: return {SPF_UMIN, SPNB_NA, false}; + case CmpInst::ICMP_ULT: return {SPF_UMAX, SPNB_NA, false}; + default: break; + } + } + + // (X > Y) ? ~Y : ~X ==> (~X < ~Y) ? ~Y : ~X ==> MAX(~Y, ~X) + // (X < Y) ? ~Y : ~X ==> (~X > ~Y) ? ~Y : ~X ==> MIN(~Y, ~X) + if (CmpLHS == getNotValue(FalseVal) && CmpRHS == getNotValue(TrueVal)) { + switch (Pred) { + case CmpInst::ICMP_SGT: return {SPF_SMAX, SPNB_NA, false}; + case CmpInst::ICMP_SLT: return {SPF_SMIN, SPNB_NA, false}; + case CmpInst::ICMP_UGT: return {SPF_UMAX, SPNB_NA, false}; + case CmpInst::ICMP_ULT: return {SPF_UMIN, SPNB_NA, false}; + default: break; + } + } + if (Pred != CmpInst::ICMP_SGT && Pred != CmpInst::ICMP_SLT) return {SPF_UNKNOWN, SPNB_NA, false}; @@ -5174,17 +5199,6 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred, match(TrueVal, m_NSWSub(m_Specific(CmpLHS), m_Specific(CmpRHS)))) return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false}; - // Look through 'not' ops to find disguised signed min/max. - // (X >s Y) ? ~X : ~Y ==> (~X <s ~Y) ? ~X : ~Y ==> SMIN(~X, ~Y) - // (X <s Y) ? ~X : ~Y ==> (~X >s ~Y) ? ~X : ~Y ==> SMAX(~X, ~Y) - if (CmpLHS == getNotValue(TrueVal) && CmpRHS == getNotValue(FalseVal)) - return {Pred == CmpInst::ICMP_SGT ? SPF_SMIN : SPF_SMAX, SPNB_NA, false}; - - // (X >s Y) ? ~Y : ~X ==> (~X <s ~Y) ? ~Y : ~X ==> SMAX(~Y, ~X) - // (X <s Y) ? ~Y : ~X ==> (~X >s ~Y) ? ~Y : ~X ==> SMIN(~Y, ~X) - if (CmpLHS == getNotValue(FalseVal) && CmpRHS == getNotValue(TrueVal)) - return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false}; - const APInt *C1; if (!match(CmpRHS, m_APInt(C1))) return {SPF_UNKNOWN, SPNB_NA, false}; |