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};
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};
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>
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
;
" %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) {
" %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) {
" %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) {
" %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) {