[llvm] fbb1b43 - [ValueTracking] enhance matching of umin/umax with 'not' operands
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 6 08:52:06 PDT 2020
Author: Sanjay Patel
Date: 2020-04-06T11:51:59-04:00
New Revision: fbb1b43f135a1af24cecbc7243d52fe6f85b7082
URL: https://github.com/llvm/llvm-project/commit/fbb1b43f135a1af24cecbc7243d52fe6f85b7082
DIFF: https://github.com/llvm/llvm-project/commit/fbb1b43f135a1af24cecbc7243d52fe6f85b7082.diff
LOG: [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
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/CodeGen/X86/vec_minmax_match.ll
llvm/test/Transforms/InstCombine/max-of-nots.ll
llvm/unittests/Analysis/ValueTrackingTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 01025ab71d75..4fa43a320031 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};
diff --git a/llvm/test/CodeGen/X86/vec_minmax_match.ll b/llvm/test/CodeGen/X86/vec_minmax_match.ll
index 4d6bb799fe3e..526503ce4bfe 100644
--- a/llvm/test/CodeGen/X86/vec_minmax_match.ll
+++ b/llvm/test/CodeGen/X86/vec_minmax_match.ll
@@ -219,15 +219,12 @@ define <4 x i32> @clamp_unsigned2(<4 x i32> %x) {
ret <4 x i32> %r
}
-define <4 x i32> @wrong_pred_for_smin_with_not(<4 x i32> %x) {
-; CHECK-LABEL: wrong_pred_for_smin_with_not:
+define <4 x i32> @umin_not_ops(<4 x i32> %x) {
+; CHECK-LABEL: umin_not_ops:
; CHECK: # %bb.0:
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
-; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm1
-; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm2
-; CHECK-NEXT: vpcmpeqd %xmm2, %xmm0, %xmm0
-; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [4294967291,4294967291,4294967291,4294967291]
-; CHECK-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
+; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
+; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: retq
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
%cmp = icmp ugt <4 x i32> %x, <i32 4, i32 4, i32 4, i32 4>
diff --git a/llvm/test/Transforms/InstCombine/max-of-nots.ll b/llvm/test/Transforms/InstCombine/max-of-nots.ll
index 3f4bd02b85c7..e6649d70946b 100644
--- a/llvm/test/Transforms/InstCombine/max-of-nots.ll
+++ b/llvm/test/Transforms/InstCombine/max-of-nots.ll
@@ -507,18 +507,14 @@ define void @cmyk5(i8 %r, i8 %g, i8 %b) {
define void @cmyk6(i8 %r, i8 %g, i8 %b) {
; CHECK-LABEL: @cmyk6(
-; CHECK-NEXT: [[NOTR:%.*]] = xor i8 [[R:%.*]], -1
-; CHECK-NEXT: [[NOTG:%.*]] = xor i8 [[G:%.*]], -1
-; CHECK-NEXT: [[NOTB:%.*]] = xor i8 [[B:%.*]], -1
-; CHECK-NEXT: [[CMP_GR:%.*]] = icmp ult i8 [[G]], [[R]]
-; CHECK-NEXT: [[CMP_BR:%.*]] = icmp ult i8 [[B]], [[R]]
-; CHECK-NEXT: [[SEL_RB:%.*]] = select i1 [[CMP_BR]], i8 [[NOTR]], i8 [[NOTB]]
-; CHECK-NEXT: [[CMP_BG:%.*]] = icmp ult i8 [[B]], [[G]]
-; CHECK-NEXT: [[SEL_GB:%.*]] = select i1 [[CMP_BG]], i8 [[NOTG]], i8 [[NOTB]]
-; CHECK-NEXT: [[K:%.*]] = select i1 [[CMP_GR]], i8 [[SEL_RB]], i8 [[SEL_GB]]
-; CHECK-NEXT: [[CK:%.*]] = sub i8 [[NOTR]], [[K]]
-; CHECK-NEXT: [[MK:%.*]] = sub i8 [[NOTG]], [[K]]
-; CHECK-NEXT: [[YK:%.*]] = sub i8 [[NOTB]], [[K]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[R:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[R]], i8 [[B]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[G:%.*]]
+; CHECK-NEXT: [[K_V:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[G]]
+; CHECK-NEXT: [[K:%.*]] = xor i8 [[K_V]], -1
+; CHECK-NEXT: [[CK:%.*]] = sub i8 [[K_V]], [[R]]
+; CHECK-NEXT: [[MK:%.*]] = sub i8 [[K_V]], [[G]]
+; CHECK-NEXT: [[YK:%.*]] = sub i8 [[K_V]], [[B]]
; CHECK-NEXT: tail call void @use(i8 [[CK]], i8 [[MK]], i8 [[YK]], i8 [[K]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index 34d9716b5fc5..775ff3a0bb45 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -519,7 +519,7 @@ TEST_F(MatchSelectPatternTest, NotNotUMin) {
" %A = select <2 x i1> %cmp, <2 x i8> %an, <2 x i8> %bn\n"
" ret <2 x i8> %A\n"
"}\n");
- expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+ expectPattern({SPF_UMIN, SPNB_NA, false});
}
TEST_F(MatchSelectPatternTest, NotNotUMinSwap) {
@@ -531,7 +531,7 @@ TEST_F(MatchSelectPatternTest, NotNotUMinSwap) {
" %A = select i1 %cmp, i8 %bn, i8 %an\n"
" ret i8 %A\n"
"}\n");
- expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+ expectPattern({SPF_UMIN, SPNB_NA, false});
}
TEST_F(MatchSelectPatternTest, NotNotUMax) {
@@ -543,7 +543,7 @@ TEST_F(MatchSelectPatternTest, NotNotUMax) {
" %A = select <2 x i1> %cmp, <2 x i8> %an, <2 x i8> %bn\n"
" ret <2 x i8> %A\n"
"}\n");
- expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+ expectPattern({SPF_UMAX, SPNB_NA, false});
}
TEST_F(MatchSelectPatternTest, NotNotUMaxSwap) {
@@ -555,7 +555,7 @@ TEST_F(MatchSelectPatternTest, NotNotUMaxSwap) {
" %A = select i1 %cmp, i8 %bn, i8 %an\n"
" ret i8 %A\n"
"}\n");
- expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+ expectPattern({SPF_UMAX, SPNB_NA, false});
}
TEST_F(MatchSelectPatternTest, NotNotEq) {
More information about the llvm-commits
mailing list