Skip to content

Commit 36eeb6d

Browse files
committedOct 29, 2016
[ValueTracking] recognize more variants of smin/smax
Try harder to detect obfuscated min/max patterns: the initial pattern was added with D9352 / rL236202. There was a bug fix for PR27137 at rL264996, but I think we can do better by folding the corresponding smax pattern and commuted variants. The codegen tests demonstrate the effect of ValueTracking on the backend via SelectionDAGBuilder. We can't expose these differences minimally in IR because we don't have smin/smax intrinsics for IR. Differential Revision: https://reviews.llvm.org/D26091 llvm-svn: 285499
1 parent e9fa95e commit 36eeb6d

File tree

4 files changed

+33
-49
lines changed

4 files changed

+33
-49
lines changed
 

‎llvm/lib/Analysis/ValueTracking.cpp

+18-10
Original file line numberDiff line numberDiff line change
@@ -3969,17 +3969,25 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
39693969
}
39703970
}
39713971

3972-
// Y >s C ? ~Y : ~C == ~Y <s ~C ? ~Y : ~C = SMIN(~Y, ~C)
3972+
// (X >s C) ? ~X : ~C ==> (~X <s ~C) ? ~X : ~C ==> SMIN(~X, ~C)
3973+
// (X <s C) ? ~X : ~C ==> (~X >s ~C) ? ~X : ~C ==> SMAX(~X, ~C)
39733974
const APInt *C2;
3974-
if (match(FalseVal, m_APInt(C2))) {
3975-
if (Pred == ICmpInst::ICMP_SGT &&
3976-
CmpRHS->getType() == FalseVal->getType() && ~(*C1) == *C2 &&
3977-
(match(TrueVal, m_Not(m_Specific(CmpLHS))) ||
3978-
match(CmpLHS, m_Not(m_Specific(TrueVal))))) {
3979-
LHS = TrueVal;
3980-
RHS = FalseVal;
3981-
return {SPF_SMIN, SPNB_NA, false};
3982-
}
3975+
if (match(TrueVal, m_Not(m_Specific(CmpLHS))) &&
3976+
match(FalseVal, m_APInt(C2)) && ~(*C1) == *C2 &&
3977+
(Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) {
3978+
LHS = TrueVal;
3979+
RHS = FalseVal;
3980+
return {Pred == CmpInst::ICMP_SGT ? SPF_SMIN : SPF_SMAX, SPNB_NA, false};
3981+
}
3982+
3983+
// (X >s C) ? ~C : ~X ==> (~X <s ~C) ? ~C : ~X ==> SMAX(~C, ~X)
3984+
// (X <s C) ? ~C : ~X ==> (~X >s ~C) ? ~C : ~X ==> SMIN(~C, ~X)
3985+
if (match(FalseVal, m_Not(m_Specific(CmpLHS))) &&
3986+
match(TrueVal, m_APInt(C2)) && ~(*C1) == *C2 &&
3987+
(Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) {
3988+
LHS = TrueVal;
3989+
RHS = FalseVal;
3990+
return {Pred == CmpInst::ICMP_SGT ? SPF_SMAX : SPF_SMIN, SPNB_NA, false};
39833991
}
39843992
}
39853993

‎llvm/test/CodeGen/X86/vec_minmax_match.ll

+5-14
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,12 @@ define <4 x i32> @smin_vec1(<4 x i32> %x) {
1818
ret <4 x i32> %sel
1919
}
2020

21-
; FIXME: These are signed min/max ops.
22-
2321
define <4 x i32> @smin_vec2(<4 x i32> %x) {
2422
; CHECK-LABEL: smin_vec2:
2523
; CHECK: # BB#0:
2624
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
27-
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm1
28-
; CHECK-NEXT: vpxor %xmm2, %xmm2, %xmm2
29-
; CHECK-NEXT: vpcmpgtd %xmm0, %xmm2, %xmm0
30-
; CHECK-NEXT: vpor %xmm1, %xmm0, %xmm0
25+
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
26+
; CHECK-NEXT: vpminsd %xmm1, %xmm0, %xmm0
3127
; CHECK-NEXT: retq
3228
;
3329
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -40,11 +36,8 @@ define <4 x i32> @smax_vec1(<4 x i32> %x) {
4036
; CHECK-LABEL: smax_vec1:
4137
; CHECK: # BB#0:
4238
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
43-
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm2
44-
; CHECK-NEXT: vpxor %xmm3, %xmm3, %xmm3
45-
; CHECK-NEXT: vpcmpgtd %xmm0, %xmm3, %xmm0
4639
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
47-
; CHECK-NEXT: vpor %xmm2, %xmm0, %xmm0
40+
; CHECK-NEXT: vpmaxsd %xmm1, %xmm0, %xmm0
4841
; CHECK-NEXT: retq
4942
;
5043
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>
@@ -57,10 +50,8 @@ define <4 x i32> @smax_vec2(<4 x i32> %x) {
5750
; CHECK-LABEL: smax_vec2:
5851
; CHECK: # BB#0:
5952
; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1
60-
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm1
61-
; CHECK-NEXT: vpxor %xmm2, %xmm2, %xmm2
62-
; CHECK-NEXT: vpcmpgtd %xmm2, %xmm0, %xmm0
63-
; CHECK-NEXT: vpor %xmm1, %xmm0, %xmm0
53+
; CHECK-NEXT: vpxor %xmm1, %xmm0, %xmm0
54+
; CHECK-NEXT: vpmaxsd %xmm1, %xmm0, %xmm0
6455
; CHECK-NEXT: retq
6556
;
6657
%not_x = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1>

‎llvm/test/Transforms/InstCombine/max-of-nots.ll

+3-18
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,7 @@ define i32 @max_of_min(i32 %a) {
140140
; max(min(%a, -1), -1) == -1 (swap predicate and select ops)
141141
define i32 @max_of_min_swap(i32 %a) {
142142
; CHECK-LABEL: @max_of_min_swap(
143-
; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
144-
; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
145-
; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 -1, i32 [[NOT_A]]
146-
; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[S0]], -1
147-
; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
148-
; CHECK-NEXT: ret i32 [[S1]]
143+
; CHECK-NEXT: ret i32 -1
149144
;
150145
%not_a = xor i32 %a, -1
151146
%c0 = icmp slt i32 %a, 0
@@ -158,12 +153,7 @@ define i32 @max_of_min_swap(i32 %a) {
158153
; min(max(%a, -1), -1) == -1
159154
define i32 @min_of_max(i32 %a) {
160155
; CHECK-LABEL: @min_of_max(
161-
; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
162-
; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
163-
; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 [[NOT_A]], i32 -1
164-
; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[S0]], -1
165-
; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
166-
; CHECK-NEXT: ret i32 [[S1]]
156+
; CHECK-NEXT: ret i32 -1
167157
;
168158
%not_a = xor i32 %a, -1
169159
%c0 = icmp slt i32 %a, 0
@@ -176,12 +166,7 @@ define i32 @min_of_max(i32 %a) {
176166
; min(max(%a, -1), -1) == -1 (swap predicate and select ops)
177167
define i32 @min_of_max_swap(i32 %a) {
178168
; CHECK-LABEL: @min_of_max_swap(
179-
; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
180-
; CHECK-NEXT: [[C0:%.*]] = icmp sgt i32 %a, 0
181-
; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 -1, i32 [[NOT_A]]
182-
; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[S0]], -1
183-
; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i32 [[S0]], i32 -1
184-
; CHECK-NEXT: ret i32 [[S1]]
169+
; CHECK-NEXT: ret i32 -1
185170
;
186171
%not_a = xor i32 %a, -1
187172
%c0 = icmp sgt i32 %a, 0

‎llvm/test/Transforms/InstCombine/select.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
21
; RUN: opt < %s -instcombine -S | FileCheck %s
32

43
; PR1822
@@ -1765,14 +1764,15 @@ define i32 @PR23757(i32 %x) {
17651764
ret i32 %sel
17661765
}
17671766

1767+
; max(max(~a, -1), -1) --> max(~a, -1)
1768+
17681769
define i32 @PR27137(i32 %a) {
17691770
; CHECK-LABEL: @PR27137(
1770-
; CHECK-NEXT: %not_a = xor i32 %a, -1
1771-
; CHECK-NEXT: %c0 = icmp slt i32 %a, 0
1772-
; CHECK-NEXT: %s0 = select i1 %c0, i32 %not_a, i32 -1
1773-
; CHECK-NEXT: %c1 = icmp sgt i32 %s0, -1
1774-
; CHECK-NEXT: %s1 = select i1 %c1, i32 %s0, i32 -1
1775-
; CHECK-NEXT: ret i32 %s1
1771+
; CHECK-NEXT: [[NOT_A:%.*]] = xor i32 %a, -1
1772+
; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 %a, 0
1773+
; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], i32 [[NOT_A]], i32 -1
1774+
; CHECK-NEXT: ret i32 [[S0]]
1775+
;
17761776

17771777
%not_a = xor i32 %a, -1
17781778
%c0 = icmp slt i32 %a, 0

0 commit comments

Comments
 (0)
Please sign in to comment.