[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / sub-minmax.ll
blobccc3483ce95bf702fc6fb15d1ddb609a61bd564d
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define i32 @max_na_b_minux_na(i32 %A, i32 %B) {
5 ; CHECK-LABEL: @max_na_b_minux_na(
6 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
7 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], [[B:%.*]]
8 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 [[B]]
9 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
10 ; CHECK-NEXT:    ret i32 [[X]]
12   %not = xor i32 %A, -1
13   %l0 = icmp ult i32 %not, %B
14   %l1 = select i1 %l0, i32 %not, i32 %B
15   %x = sub i32 %l1, %not
16   ret i32 %x
19 define i32 @na_minus_max_na_b(i32 %A, i32 %B) {
20 ; CHECK-LABEL: @na_minus_max_na_b(
21 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
22 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], [[B:%.*]]
23 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 [[B]]
24 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]
25 ; CHECK-NEXT:    ret i32 [[X]]
27   %not = xor i32 %A, -1
28   %l0 = icmp ult i32 %not, %B
29   %l1 = select i1 %l0, i32 %not, i32 %B
30   %x = sub i32 %not, %l1
31   ret i32 %x
34 define i32 @max_b_na_minus_na(i32 %A, i32 %B) {
35 ; CHECK-LABEL: @max_b_na_minus_na(
36 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
37 ; CHECK-NEXT:    [[L0:%.*]] = icmp ugt i32 [[NOT]], [[B:%.*]]
38 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[B]], i32 [[NOT]]
39 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
40 ; CHECK-NEXT:    ret i32 [[X]]
42   %not = xor i32 %A, -1
43   %l0 = icmp ugt i32 %not, %B
44   %l1 = select i1 %l0, i32 %B, i32 %not
45   %x = sub i32 %l1, %not
46   ret i32 %x
49 define i32 @na_minus_max_b_na(i32 %A, i32 %B) {
50 ; CHECK-LABEL: @na_minus_max_b_na(
51 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
52 ; CHECK-NEXT:    [[L0:%.*]] = icmp ugt i32 [[NOT]], [[B:%.*]]
53 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[B]], i32 [[NOT]]
54 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]
55 ; CHECK-NEXT:    ret i32 [[X]]
57   %not = xor i32 %A, -1
58   %l0 = icmp ugt i32 %not, %B
59   %l1 = select i1 %l0, i32 %B, i32 %not
60   %x = sub i32 %not, %l1
61   ret i32 %x
65 define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) {
66 ; CHECK-LABEL: @max_na_bi_minux_na(
67 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
68 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
69 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
70 ; CHECK-NEXT:    ret i32 [[X]]
72   %B =  xor i32 %Bi, -1
73   %not = xor i32 %A, -1
74   %l0 = icmp ult i32 %not, %B
75   %l1 = select i1 %l0, i32 %not, i32 %B
76   %x = sub i32 %l1, %not
77   ret i32 %x
80 define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) {
81 ; CHECK-LABEL: @na_minus_max_na_bi(
82 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
83 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
84 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
85 ; CHECK-NEXT:    ret i32 [[X]]
87   %B =  xor i32 %Bi, -1
88   %not = xor i32 %A, -1
89   %l0 = icmp ult i32 %not, %B
90   %l1 = select i1 %l0, i32 %not, i32 %B
91   %x = sub i32 %not, %l1
92   ret i32 %x
95 define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) {
96 ; CHECK-LABEL: @max_bi_na_minus_na(
97 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
98 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
99 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
100 ; CHECK-NEXT:    ret i32 [[X]]
102   %B =  xor i32 %Bi, -1
103   %not = xor i32 %A, -1
104   %l0 = icmp ugt i32 %not, %B
105   %l1 = select i1 %l0, i32 %B, i32 %not
106   %x = sub i32 %l1, %not
107   ret i32 %x
110 define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) {
111 ; CHECK-LABEL: @na_minus_max_bi_na(
112 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
113 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
114 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
115 ; CHECK-NEXT:    ret i32 [[X]]
117   %B =  xor i32 %Bi, -1
118   %not = xor i32 %A, -1
119   %l0 = icmp ugt i32 %not, %B
120   %l1 = select i1 %l0, i32 %B, i32 %not
121   %x = sub i32 %not, %l1
122   ret i32 %x
126 define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) {
127 ; CHECK-LABEL: @max_na_bi_minux_na_use(
128 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32
129 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32
130 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
131 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
132 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
133 ; CHECK-NEXT:    ret i32 [[X]]
135   %not = xor i32 %A, -1
136   %l0 = icmp ult i32 %not, 31
137   %l1 = select i1 %l0, i32 %not, i32 31
138   %x = sub i32 %l1, %not
139   call void @use32(i32 %l1)
140   ret i32 %x
143 define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) {
144 ; CHECK-LABEL: @na_minus_max_na_bi_use(
145 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32
146 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32
147 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
148 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
149 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
150 ; CHECK-NEXT:    ret i32 [[X]]
152   %not = xor i32 %A, -1
153   %l0 = icmp ult i32 %not, 31
154   %l1 = select i1 %l0, i32 %not, i32 31
155   %x = sub i32 %not, %l1
156   call void @use32(i32 %l1)
157   ret i32 %x
160 define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) {
161 ; CHECK-LABEL: @max_bi_na_minus_na_use(
162 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
163 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
164 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
165 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
166 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
167 ; CHECK-NEXT:    ret i32 [[X]]
169   %not = xor i32 %A, -1
170   %B = xor i32 %Bi, -1
171   %l0 = icmp ult i32 %B, %not
172   %l1 = select i1 %l0, i32 %B, i32 %not
173   %x = sub i32 %l1, %not
174   call void @use32(i32 %l1)
175   ret i32 %x
178 define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) {
179 ; CHECK-LABEL: @na_minus_max_bi_na_use(
180 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A:%.*]], [[BI:%.*]]
181 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
182 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
183 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
184 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
185 ; CHECK-NEXT:    ret i32 [[X]]
187   %not = xor i32 %A, -1
188   %B = xor i32 %Bi, -1
189   %l0 = icmp ult i32 %B, %not
190   %l1 = select i1 %l0, i32 %B, i32 %not
191   %x = sub i32 %not, %l1
192   call void @use32(i32 %l1)
193   ret i32 %x
197 define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) {
198 ; CHECK-LABEL: @max_na_bi_minux_na_use2(
199 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
200 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], 31
201 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31
202 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
203 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
204 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
205 ; CHECK-NEXT:    ret i32 [[X]]
207   %not = xor i32 %A, -1
208   %l0 = icmp ult i32 %not, 31
209   %l1 = select i1 %l0, i32 %not, i32 31
210   %x = sub i32 %l1, %not
211   call void @use32(i32 %l1)
212   call void @use32(i32 %not)
213   ret i32 %x
216 define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) {
217 ; CHECK-LABEL: @na_minus_max_na_bi_use2(
218 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
219 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], 31
220 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31
221 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]
222 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
223 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
224 ; CHECK-NEXT:    ret i32 [[X]]
226   %not = xor i32 %A, -1
227   %l0 = icmp ult i32 %not, 31
228   %l1 = select i1 %l0, i32 %not, i32 31
229   %x = sub i32 %not, %l1
230   call void @use32(i32 %l1)
231   call void @use32(i32 %not)
232   ret i32 %x
235 define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) {
236 ; CHECK-LABEL: @max_bi_na_minus_na_use2(
237 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
238 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A]], [[BI:%.*]]
239 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
240 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
241 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
242 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
243 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
244 ; CHECK-NEXT:    ret i32 [[X]]
246   %not = xor i32 %A, -1
247   %B = xor i32 %Bi, -1
248   %l0 = icmp ult i32 %B, %not
249   %l1 = select i1 %l0, i32 %B, i32 %not
250   %x = sub i32 %l1, %not
251   call void @use32(i32 %l1)
252   call void @use32(i32 %not)
253   ret i32 %x
256 define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) {
257 ; CHECK-LABEL: @na_minus_max_bi_na_use2(
258 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
259 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[A]], [[BI:%.*]]
260 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
261 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
262 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
263 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
264 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
265 ; CHECK-NEXT:    ret i32 [[X]]
267   %not = xor i32 %A, -1
268   %B = xor i32 %Bi, -1
269   %l0 = icmp ult i32 %B, %not
270   %l1 = select i1 %l0, i32 %B, i32 %not
271   %x = sub i32 %not, %l1
272   call void @use32(i32 %l1)
273   call void @use32(i32 %not)
274   ret i32 %x
277 define i8 @umin_not_sub(i8 %x, i8 %y) {
278 ; CHECK-LABEL: @umin_not_sub(
279 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[Y:%.*]], [[X:%.*]]
280 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]]
281 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP2]], -1
282 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP2]], [[X]]
283 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[TMP2]], [[Y]]
284 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
285 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
286 ; CHECK-NEXT:    ret i8 [[MINXY]]
288   %nx = xor i8 %x, -1
289   %ny = xor i8 %y, -1
290   %cmpxy = icmp ult i8 %nx, %ny
291   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
292   %subx = sub i8 %nx, %minxy
293   %suby = sub i8 %ny, %minxy
294   call void @use8(i8 %subx)
295   call void @use8(i8 %suby)
296   ret i8 %minxy
299 define i8 @umin_not_sub_rev(i8 %x, i8 %y) {
300 ; CHECK-LABEL: @umin_not_sub_rev(
301 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[Y:%.*]], [[X:%.*]]
302 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]]
303 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP2]], -1
304 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP2]]
305 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[Y]], [[TMP2]]
306 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
307 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
308 ; CHECK-NEXT:    ret i8 [[MINXY]]
310   %nx = xor i8 %x, -1
311   %ny = xor i8 %y, -1
312   %cmpxy = icmp ult i8 %nx, %ny
313   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
314   %subx = sub i8 %minxy, %nx
315   %suby = sub i8 %minxy, %ny
316   call void @use8(i8 %subx)
317   call void @use8(i8 %suby)
318   ret i8 %minxy
321 define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) {
322 ; CHECK-LABEL: @umin3_not_all_ops_extra_uses_invert_subs(
323 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Z:%.*]]
324 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Z]]
325 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[Y:%.*]]
326 ; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[Y]]
327 ; CHECK-NEXT:    [[TMP5:%.*]] = xor i8 [[TMP4]], -1
328 ; CHECK-NEXT:    [[XMIN:%.*]] = sub i8 [[TMP4]], [[X]]
329 ; CHECK-NEXT:    [[YMIN:%.*]] = sub i8 [[TMP4]], [[Y]]
330 ; CHECK-NEXT:    [[ZMIN:%.*]] = sub i8 [[TMP4]], [[Z]]
331 ; CHECK-NEXT:    call void @use8(i8 [[TMP5]])
332 ; CHECK-NEXT:    call void @use8(i8 [[XMIN]])
333 ; CHECK-NEXT:    call void @use8(i8 [[YMIN]])
334 ; CHECK-NEXT:    call void @use8(i8 [[ZMIN]])
335 ; CHECK-NEXT:    ret void
337   %xn = xor i8 %x, -1
338   %yn = xor i8 %y, -1
339   %zn = xor i8 %z, -1
340   %cmpxz = icmp ult i8 %xn, %zn
341   %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
342   %cmpxyz = icmp ult i8 %minxz, %yn
343   %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
344   %xmin = sub i8 %xn, %minxyz
345   %ymin = sub i8 %yn, %minxyz
346   %zmin = sub i8 %zn, %minxyz
347   call void @use8(i8 %minxyz)
348   call void @use8(i8 %xmin)
349   call void @use8(i8 %ymin)
350   call void @use8(i8 %zmin)
351   ret void
354 declare void @use8(i8)
355 declare void @use32(i32 %u)