llvm.org GIT mirror llvm / 78c322d
[ValueTracking] recognize obfuscated variants of umin/umax The smallest tests that expose this are codegen tests (because SelectionDAGBuilder::visitSelect() uses matchSelectPattern to create UMAX/UMIN nodes), but it's also possible to see the effects in IR alone with folds of min/max pairs. If these were written as unsigned compares in IR, InstCombine canonicalizes the unsigned compares to signed compares. Ie, running the optimizer pessimizes the codegen for this case without this patch: define <4 x i32> @umax_vec(<4 x i32> %x) { %cmp = icmp ugt <4 x i32> %x, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647> %sel = select <4 x i1> %cmp, <4 x i32> %x, <4 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647> ret <4 x i32> %sel } $ ./opt umax.ll -S | ./llc -o - -mattr=avx vpmaxud LCPI0_0(%rip), %xmm0, %xmm0 $ ./opt -instcombine umax.ll -S | ./llc -o - -mattr=avx vpxor %xmm1, %xmm1, %xmm1 vpcmpgtd %xmm0, %xmm1, %xmm1 vmovaps LCPI0_0(%rip), %xmm2 ## xmm2 = [2147483647,2147483647,2147483647,2147483647] vblendvps %xmm1, %xmm0, %xmm2, %xmm0 Differential Revision: https://reviews.llvm.org/D26096 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286318 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 3 years ago
2 changed file(s) with 29 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
39683968 }
39693969 }
39703970
3971 // An unsigned min/max can be written with a signed compare.
3972 const APInt *C2;
3973 if ((CmpLHS == TrueVal && match(FalseVal, m_APInt(C2))) ||
3974 (CmpLHS == FalseVal && match(TrueVal, m_APInt(C2)))) {
3975 // Is the sign bit set?
3976 // (X (X >u MAXVAL) ? X : MAXVAL ==> UMAX
3977 // (X (X >u MAXVAL) ? MAXVAL : X ==> UMIN
3978 if (Pred == CmpInst::ICMP_SLT && *C1 == 0 && C2->isMaxSignedValue()) {
3979 LHS = TrueVal;
3980 RHS = FalseVal;
3981 return {CmpLHS == TrueVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false};
3982 }
3983
3984 // Is the sign bit clear?
3985 // (X >s -1) ? MINVAL : X ==> (X UMAX
3986 // (X >s -1) ? X : MINVAL ==> (X UMIN
3987 if (Pred == CmpInst::ICMP_SGT && C1->isAllOnesValue() &&
3988 C2->isMinSignedValue()) {
3989 LHS = TrueVal;
3990 RHS = FalseVal;
3991 return {CmpLHS == FalseVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false};
3992 }
3993 }
3994
3995 // Look through 'not' ops to find disguised signed min/max.
39713996 // (X >s C) ? ~X : ~C ==> (~X SMIN(~X, ~C)
39723997 // (X (~X >s ~C) ? ~X : ~C ==> SMAX(~X, ~C)
3973 const APInt *C2;
39743998 if (match(TrueVal, m_Not(m_Specific(CmpLHS))) &&
39753999 match(FalseVal, m_APInt(C2)) && ~(*C1) == *C2 &&
39764000 (Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) {
5959 ret <4 x i32> %sel
6060 }
6161
62 ; FIXME: These are unsigned min/max ops.
63
6462 define <4 x i32> @umax_vec1(<4 x i32> %x) {
6563 ; CHECK-LABEL: umax_vec1:
6664 ; CHECK: # BB#0:
67 ; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1
68 ; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1
69 ; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483647,2147483647,2147483647,2147483647]
70 ; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
65 ; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0
7166 ; CHECK-NEXT: retq
7267 ;
7368 %cmp = icmp slt <4 x i32> %x, zeroinitializer
7873 define <4 x i32> @umax_vec2(<4 x i32> %x) {
7974 ; CHECK-LABEL: umax_vec2:
8075 ; CHECK: # BB#0:
81 ; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
82 ; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1
83 ; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0
76 ; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0
8477 ; CHECK-NEXT: retq
8578 ;
8679 %cmp = icmp sgt <4 x i32> %x,
9184 define <4 x i32> @umin_vec1(<4 x i32> %x) {
9285 ; CHECK-LABEL: umin_vec1:
9386 ; CHECK: # BB#0:
94 ; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1
95 ; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1
96 ; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0
87 ; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0
9788 ; CHECK-NEXT: retq
9889 ;
9990 %cmp = icmp slt <4 x i32> %x, zeroinitializer
10495 define <4 x i32> @umin_vec2(<4 x i32> %x) {
10596 ; CHECK-LABEL: umin_vec2:
10697 ; CHECK: # BB#0:
107 ; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
108 ; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1
109 ; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648]
110 ; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0
98 ; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0
11199 ; CHECK-NEXT: retq
112100 ;
113101 %cmp = icmp sgt <4 x i32> %x,