aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2020-04-06 11:40:45 -0400
committerSanjay Patel <spatel@rotateright.com>2020-04-06 11:51:59 -0400
commitfbb1b43f135a1af24cecbc7243d52fe6f85b7082 (patch)
tree7018e4dadd8d5ae6f8a4ba404eeadb765837b85f /llvm/lib/Analysis/ValueTracking.cpp
parent2aa593be5486a9c5d3092647f2576273f84f3159 (diff)
downloadllvm-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.cpp36
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};