[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InstCombine / sub-minmax.ll
blob83b210929ec1aa43ebc69f74b91add75d4904e2e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 declare i5 @llvm.umin.i5(i5, i5)
5 declare <2 x i8> @llvm.umin.v2i8(<2 x i8>, <2 x i8>)
7 define i32 @max_na_b_minux_na(i32 %A, i32 %B) {
8 ; CHECK-LABEL: @max_na_b_minux_na(
9 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
10 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
11 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
12 ; CHECK-NEXT:    ret i32 [[TMP2]]
14   %not = xor i32 %A, -1
15   %l0 = icmp ult i32 %not, %B
16   %l1 = select i1 %l0, i32 %not, i32 %B
17   %x = sub i32 %l1, %not
18   ret i32 %x
21 define i32 @na_minus_max_na_b(i32 %A, i32 %B) {
22 ; CHECK-LABEL: @na_minus_max_na_b(
23 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
24 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
25 ; CHECK-NEXT:    ret i32 [[TMP1]]
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 i5 @sub_umin(i5 %a, i5 %b) {
35 ; CHECK-LABEL: @sub_umin(
36 ; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A:%.*]], i5 [[B:%.*]])
37 ; CHECK-NEXT:    [[R:%.*]] = sub i5 [[A]], [[UMIN]]
38 ; CHECK-NEXT:    ret i5 [[R]]
40   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
41   %r = sub i5 %a, %umin
42   ret i5 %r
45 define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) {
46 ; CHECK-LABEL: @sub_umin_commute_vec(
47 ; CHECK-NEXT:    [[UMIN:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[B:%.*]], <2 x i8> [[A:%.*]])
48 ; CHECK-NEXT:    [[R:%.*]] = sub <2 x i8> [[B]], [[UMIN]]
49 ; CHECK-NEXT:    ret <2 x i8> [[R]]
51   %umin = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %b, <2 x i8> %a)
52   %r = sub <2 x i8> %b, %umin
53   ret <2 x i8> %r
56 define i5 @sub_umin_uses(i5 %a, i5 %b, i5* %p) {
57 ; CHECK-LABEL: @sub_umin_uses(
58 ; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A:%.*]], i5 [[B:%.*]])
59 ; CHECK-NEXT:    store i5 [[UMIN]], i5* [[P:%.*]], align 1
60 ; CHECK-NEXT:    [[R:%.*]] = sub i5 [[A]], [[UMIN]]
61 ; CHECK-NEXT:    ret i5 [[R]]
63   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
64   store i5 %umin, i5* %p
65   %r = sub i5 %a, %umin
66   ret i5 %r
69 define i5 @sub_umin_no_common_op(i5 %a, i5 %b, i5 %c) {
70 ; CHECK-LABEL: @sub_umin_no_common_op(
71 ; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A:%.*]], i5 [[B:%.*]])
72 ; CHECK-NEXT:    [[R:%.*]] = sub i5 [[C:%.*]], [[UMIN]]
73 ; CHECK-NEXT:    ret i5 [[R]]
75   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
76   %r = sub i5 %c, %umin
77   ret i5 %r
80 define i32 @max_b_na_minus_na(i32 %A, i32 %B) {
81 ; CHECK-LABEL: @max_b_na_minus_na(
82 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
83 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
84 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
85 ; CHECK-NEXT:    ret i32 [[TMP2]]
87   %not = xor i32 %A, -1
88   %l0 = icmp ugt i32 %not, %B
89   %l1 = select i1 %l0, i32 %B, i32 %not
90   %x = sub i32 %l1, %not
91   ret i32 %x
94 define i32 @na_minus_max_b_na(i32 %A, i32 %B) {
95 ; CHECK-LABEL: @na_minus_max_b_na(
96 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
97 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]])
98 ; CHECK-NEXT:    ret i32 [[TMP1]]
100   %not = xor i32 %A, -1
101   %l0 = icmp ugt i32 %not, %B
102   %l1 = select i1 %l0, i32 %B, i32 %not
103   %x = sub i32 %not, %l1
104   ret i32 %x
108 define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) {
109 ; CHECK-LABEL: @max_na_bi_minux_na(
110 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
111 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
112 ; CHECK-NEXT:    ret i32 [[TMP2]]
114   %B =  xor i32 %Bi, -1
115   %not = xor i32 %A, -1
116   %l0 = icmp ult i32 %not, %B
117   %l1 = select i1 %l0, i32 %not, i32 %B
118   %x = sub i32 %l1, %not
119   ret i32 %x
122 define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) {
123 ; CHECK-LABEL: @na_minus_max_na_bi(
124 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
125 ; CHECK-NEXT:    ret i32 [[TMP1]]
127   %B =  xor i32 %Bi, -1
128   %not = xor i32 %A, -1
129   %l0 = icmp ult i32 %not, %B
130   %l1 = select i1 %l0, i32 %not, i32 %B
131   %x = sub i32 %not, %l1
132   ret i32 %x
135 define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) {
136 ; CHECK-LABEL: @max_bi_na_minus_na(
137 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
138 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 0, [[TMP1]]
139 ; CHECK-NEXT:    ret i32 [[TMP2]]
141   %B =  xor i32 %Bi, -1
142   %not = xor i32 %A, -1
143   %l0 = icmp ugt i32 %not, %B
144   %l1 = select i1 %l0, i32 %B, i32 %not
145   %x = sub i32 %l1, %not
146   ret i32 %x
149 define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) {
150 ; CHECK-LABEL: @na_minus_max_bi_na(
151 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]])
152 ; CHECK-NEXT:    ret i32 [[TMP1]]
154   %B =  xor i32 %Bi, -1
155   %not = xor i32 %A, -1
156   %l0 = icmp ugt i32 %not, %B
157   %l1 = select i1 %l0, i32 %B, i32 %not
158   %x = sub i32 %not, %l1
159   ret i32 %x
163 define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) {
164 ; CHECK-LABEL: @max_na_bi_minux_na_use(
165 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32
166 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32
167 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
168 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
169 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
170 ; CHECK-NEXT:    ret i32 [[X]]
172   %not = xor i32 %A, -1
173   %l0 = icmp ult i32 %not, 31
174   %l1 = select i1 %l0, i32 %not, i32 31
175   %x = sub i32 %l1, %not
176   call void @use32(i32 %l1)
177   ret i32 %x
180 define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) {
181 ; CHECK-LABEL: @na_minus_max_na_bi_use(
182 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32
183 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32
184 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
185 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
186 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
187 ; CHECK-NEXT:    ret i32 [[X]]
189   %not = xor i32 %A, -1
190   %l0 = icmp ult i32 %not, 31
191   %l1 = select i1 %l0, i32 %not, i32 31
192   %x = sub i32 %not, %l1
193   call void @use32(i32 %l1)
194   ret i32 %x
197 define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) {
198 ; CHECK-LABEL: @max_bi_na_minus_na_use(
199 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A:%.*]]
200 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
201 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
202 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
203 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
204 ; CHECK-NEXT:    ret i32 [[X]]
206   %not = xor i32 %A, -1
207   %B = xor i32 %Bi, -1
208   %l0 = icmp ult i32 %B, %not
209   %l1 = select i1 %l0, i32 %B, i32 %not
210   %x = sub i32 %l1, %not
211   call void @use32(i32 %l1)
212   ret i32 %x
215 define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) {
216 ; CHECK-LABEL: @na_minus_max_bi_na_use(
217 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A:%.*]]
218 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
219 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
220 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
221 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
222 ; CHECK-NEXT:    ret i32 [[X]]
224   %not = xor i32 %A, -1
225   %B = xor i32 %Bi, -1
226   %l0 = icmp ult i32 %B, %not
227   %l1 = select i1 %l0, i32 %B, i32 %not
228   %x = sub i32 %not, %l1
229   call void @use32(i32 %l1)
230   ret i32 %x
234 define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) {
235 ; CHECK-LABEL: @max_na_bi_minux_na_use2(
236 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
237 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], 31
238 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31
239 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
240 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
241 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
242 ; CHECK-NEXT:    ret i32 [[X]]
244   %not = xor i32 %A, -1
245   %l0 = icmp ult i32 %not, 31
246   %l1 = select i1 %l0, i32 %not, i32 31
247   %x = sub i32 %l1, %not
248   call void @use32(i32 %l1)
249   call void @use32(i32 %not)
250   ret i32 %x
253 define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) {
254 ; CHECK-LABEL: @na_minus_max_na_bi_use2(
255 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
256 ; CHECK-NEXT:    [[L0:%.*]] = icmp ult i32 [[NOT]], 31
257 ; CHECK-NEXT:    [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31
258 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]
259 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
260 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
261 ; CHECK-NEXT:    ret i32 [[X]]
263   %not = xor i32 %A, -1
264   %l0 = icmp ult i32 %not, 31
265   %l1 = select i1 %l0, i32 %not, i32 31
266   %x = sub i32 %not, %l1
267   call void @use32(i32 %l1)
268   call void @use32(i32 %not)
269   ret i32 %x
272 define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) {
273 ; CHECK-LABEL: @max_bi_na_minus_na_use2(
274 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
275 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A]]
276 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
277 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
278 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP2]]
279 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
280 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
281 ; CHECK-NEXT:    ret i32 [[X]]
283   %not = xor i32 %A, -1
284   %B = xor i32 %Bi, -1
285   %l0 = icmp ult i32 %B, %not
286   %l1 = select i1 %l0, i32 %B, i32 %not
287   %x = sub i32 %l1, %not
288   call void @use32(i32 %l1)
289   call void @use32(i32 %not)
290   ret i32 %x
293 define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) {
294 ; CHECK-LABEL: @na_minus_max_bi_na_use2(
295 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A:%.*]], -1
296 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A]]
297 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]]
298 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP2]], -1
299 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP2]], [[A]]
300 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
301 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
302 ; CHECK-NEXT:    ret i32 [[X]]
304   %not = xor i32 %A, -1
305   %B = xor i32 %Bi, -1
306   %l0 = icmp ult i32 %B, %not
307   %l1 = select i1 %l0, i32 %B, i32 %not
308   %x = sub i32 %not, %l1
309   call void @use32(i32 %l1)
310   call void @use32(i32 %not)
311   ret i32 %x
314 define i8 @umin_not_sub(i8 %x, i8 %y) {
315 ; CHECK-LABEL: @umin_not_sub(
316 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
317 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]]
318 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP2]], -1
319 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP2]], [[X]]
320 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[TMP2]], [[Y]]
321 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
322 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
323 ; CHECK-NEXT:    ret i8 [[MINXY]]
325   %nx = xor i8 %x, -1
326   %ny = xor i8 %y, -1
327   %cmpxy = icmp ult i8 %nx, %ny
328   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
329   %subx = sub i8 %nx, %minxy
330   %suby = sub i8 %ny, %minxy
331   call void @use8(i8 %subx)
332   call void @use8(i8 %suby)
333   ret i8 %minxy
336 define i8 @umin_not_sub_rev(i8 %x, i8 %y) {
337 ; CHECK-LABEL: @umin_not_sub_rev(
338 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]]
339 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]]
340 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP2]], -1
341 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP2]]
342 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[Y]], [[TMP2]]
343 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
344 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
345 ; CHECK-NEXT:    ret i8 [[MINXY]]
347   %nx = xor i8 %x, -1
348   %ny = xor i8 %y, -1
349   %cmpxy = icmp ult i8 %nx, %ny
350   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
351   %subx = sub i8 %minxy, %nx
352   %suby = sub i8 %minxy, %ny
353   call void @use8(i8 %subx)
354   call void @use8(i8 %suby)
355   ret i8 %minxy
358 define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) {
359 ; CHECK-LABEL: @umin3_not_all_ops_extra_uses_invert_subs(
360 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Z:%.*]]
361 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Z]]
362 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[Y:%.*]]
363 ; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[Y]]
364 ; CHECK-NEXT:    [[TMP5:%.*]] = xor i8 [[TMP4]], -1
365 ; CHECK-NEXT:    [[XMIN:%.*]] = sub i8 [[TMP4]], [[X]]
366 ; CHECK-NEXT:    [[YMIN:%.*]] = sub i8 [[TMP4]], [[Y]]
367 ; CHECK-NEXT:    [[ZMIN:%.*]] = sub i8 [[TMP4]], [[Z]]
368 ; CHECK-NEXT:    call void @use8(i8 [[TMP5]])
369 ; CHECK-NEXT:    call void @use8(i8 [[XMIN]])
370 ; CHECK-NEXT:    call void @use8(i8 [[YMIN]])
371 ; CHECK-NEXT:    call void @use8(i8 [[ZMIN]])
372 ; CHECK-NEXT:    ret void
374   %xn = xor i8 %x, -1
375   %yn = xor i8 %y, -1
376   %zn = xor i8 %z, -1
377   %cmpxz = icmp ult i8 %xn, %zn
378   %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
379   %cmpxyz = icmp ult i8 %minxz, %yn
380   %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
381   %xmin = sub i8 %xn, %minxyz
382   %ymin = sub i8 %yn, %minxyz
383   %zmin = sub i8 %zn, %minxyz
384   call void @use8(i8 %minxyz)
385   call void @use8(i8 %xmin)
386   call void @use8(i8 %ymin)
387   call void @use8(i8 %zmin)
388   ret void
391 declare void @use8(i8)
392 declare void @use32(i32 %u)