aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2020-04-05 08:51:29 -0400
committerSanjay Patel <spatel@rotateright.com>2020-04-05 08:54:12 -0400
commit867f0c3c4d8c25c5cded2dd290a3fcfd92d98557 (patch)
tree96fbf29150c6371a00609b47cda82103670b92d6 /llvm/lib/Analysis/ValueTracking.cpp
parent59d10dc703357631e9a13000ef15930b86a93335 (diff)
downloadllvm-867f0c3c4d8c25c5cded2dd290a3fcfd92d98557.zip
llvm-867f0c3c4d8c25c5cded2dd290a3fcfd92d98557.tar.gz
llvm-867f0c3c4d8c25c5cded2dd290a3fcfd92d98557.tar.bz2
[ValueTracking] enhance matching of smin/smax with 'not' operands
The cmyk tests are based on the known regression that resulted from: rGf2fbdf76d8d0 So this improvement in analysis might be enough to restore that commit.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp39
1 files changed, 26 insertions, 13 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index d7ea47e..01025ab 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5124,6 +5124,21 @@ static SelectPatternResult matchMinMaxOfMinMax(CmpInst::Predicate Pred,
return {SPF_UNKNOWN, SPNB_NA, false};
}
+/// If the input value is the result of a 'not' op, constant integer, or vector
+/// splat of a constant integer, return the bitwise-not source value.
+/// TODO: This could be extended to handle non-splat vector integer constants.
+static Value *getNotValue(Value *V) {
+ Value *NotV;
+ if (match(V, m_Not(m_Value(NotV))))
+ return NotV;
+
+ const APInt *C;
+ if (match(V, m_APInt(C)))
+ return ConstantInt::get(V->getType(), ~(*C));
+
+ return nullptr;
+}
+
/// Match non-obvious integer minimum and maximum sequences.
static SelectPatternResult matchMinMax(CmpInst::Predicate Pred,
Value *CmpLHS, Value *CmpRHS,
@@ -5159,6 +5174,17 @@ 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};
@@ -5182,19 +5208,6 @@ static SelectPatternResult matchMinMax(CmpInst::Predicate Pred,
return {CmpLHS == FalseVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false};
}
- // Look through 'not' ops to find disguised signed min/max.
- // (X >s C) ? ~X : ~C ==> (~X <s ~C) ? ~X : ~C ==> SMIN(~X, ~C)
- // (X <s C) ? ~X : ~C ==> (~X >s ~C) ? ~X : ~C ==> SMAX(~X, ~C)
- if (match(TrueVal, m_Not(m_Specific(CmpLHS))) &&
- match(FalseVal, m_APInt(C2)) && ~(*C1) == *C2)
- return {Pred == CmpInst::ICMP_SGT ? SPF_SMIN : SPF_SMAX, SPNB_NA, false};
-
- // (X >s C) ? ~C : ~X ==> (~X <s ~C) ? ~C : ~X ==> SMAX(~C, ~X)
- // (X <s C) ? ~C : ~X ==> (~X >s ~C) ? ~C : ~X ==> SMIN(~C, ~X)
- if (match(FalseVal, m_Not(m_Specific(CmpLHS))) &&
- match(TrueVal, m_APInt(C2)) && ~(*C1) == *C2)
- return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false};
-
return {SPF_UNKNOWN, SPNB_NA, false};
}