Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / sub-minmax.ll
blobc9ce165c3898865f46fec8a2defbc67ad8079516
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 declare i5 @llvm.umin.i5(i5, i5)
5 declare <2 x i8> @llvm.smin.v2i8(<2 x i8>, <2 x i8>)
6 declare <2 x i8> @llvm.smax.v2i8(<2 x i8>, <2 x i8>)
7 declare <2 x i8> @llvm.umin.v2i8(<2 x i8>, <2 x i8>)
8 declare <2 x i8> @llvm.umax.v2i8(<2 x i8>, <2 x i8>)
10 declare i8 @llvm.smax.i8(i8, i8)
11 declare i8 @llvm.smin.i8(i8, i8)
12 declare i8 @llvm.umax.i8(i8, i8)
13 declare i8 @llvm.umin.i8(i8, i8)
15 define i32 @max_na_b_minux_na(i32 %A, i32 %B) {
16 ; CHECK-LABEL: define {{[^@]+}}@max_na_b_minux_na
17 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
18 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
19 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])
20 ; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]
21 ; CHECK-NEXT:    ret i32 [[X]]
23   %not = xor i32 %A, -1
24   %l0 = icmp ult i32 %not, %B
25   %l1 = select i1 %l0, i32 %not, i32 %B
26   %x = sub i32 %l1, %not
27   ret i32 %x
30 define i32 @na_minus_max_na_b(i32 %A, i32 %B) {
31 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_b
32 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
33 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
34 ; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])
35 ; CHECK-NEXT:    ret i32 [[X]]
37   %not = xor i32 %A, -1
38   %l0 = icmp ult i32 %not, %B
39   %l1 = select i1 %l0, i32 %not, i32 %B
40   %x = sub i32 %not, %l1
41   ret i32 %x
44 define i5 @sub_umin(i5 %a, i5 %b) {
45 ; CHECK-LABEL: define {{[^@]+}}@sub_umin
46 ; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]]) {
47 ; CHECK-NEXT:    [[R:%.*]] = call i5 @llvm.usub.sat.i5(i5 [[A]], i5 [[B]])
48 ; CHECK-NEXT:    ret i5 [[R]]
50   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
51   %r = sub i5 %a, %umin
52   ret i5 %r
55 define <2 x i8> @sub_umin_commute_vec(<2 x i8> %a, <2 x i8> %b) {
56 ; CHECK-LABEL: define {{[^@]+}}@sub_umin_commute_vec
57 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
58 ; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> [[A]])
59 ; CHECK-NEXT:    ret <2 x i8> [[R]]
61   %umin = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %b, <2 x i8> %a)
62   %r = sub <2 x i8> %b, %umin
63   ret <2 x i8> %r
66 define i5 @sub_umin_uses(i5 %a, i5 %b, ptr %p) {
67 ; CHECK-LABEL: define {{[^@]+}}@sub_umin_uses
68 ; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]], ptr [[P:%.*]]) {
69 ; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A]], i5 [[B]])
70 ; CHECK-NEXT:    store i5 [[UMIN]], ptr [[P]], align 1
71 ; CHECK-NEXT:    [[R:%.*]] = sub i5 [[A]], [[UMIN]]
72 ; CHECK-NEXT:    ret i5 [[R]]
74   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
75   store i5 %umin, ptr %p
76   %r = sub i5 %a, %umin
77   ret i5 %r
80 define i5 @sub_umin_no_common_op(i5 %a, i5 %b, i5 %c) {
81 ; CHECK-LABEL: define {{[^@]+}}@sub_umin_no_common_op
82 ; CHECK-SAME: (i5 [[A:%.*]], i5 [[B:%.*]], i5 [[C:%.*]]) {
83 ; CHECK-NEXT:    [[UMIN:%.*]] = call i5 @llvm.umin.i5(i5 [[A]], i5 [[B]])
84 ; CHECK-NEXT:    [[R:%.*]] = sub i5 [[C]], [[UMIN]]
85 ; CHECK-NEXT:    ret i5 [[R]]
87   %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
88   %r = sub i5 %c, %umin
89   ret i5 %r
92 define i32 @max_b_na_minus_na(i32 %A, i32 %B) {
93 ; CHECK-LABEL: define {{[^@]+}}@max_b_na_minus_na
94 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
95 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
96 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])
97 ; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]
98 ; CHECK-NEXT:    ret i32 [[X]]
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 %l1, %not
104   ret i32 %x
107 define i32 @na_minus_max_b_na(i32 %A, i32 %B) {
108 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_b_na
109 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
110 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
111 ; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B]])
112 ; CHECK-NEXT:    ret i32 [[X]]
114   %not = xor i32 %A, -1
115   %l0 = icmp ugt i32 %not, %B
116   %l1 = select i1 %l0, i32 %B, i32 %not
117   %x = sub i32 %not, %l1
118   ret i32 %x
122 define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) {
123 ; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na
124 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
125 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])
126 ; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]
127 ; CHECK-NEXT:    ret i32 [[X]]
129   %B =  xor i32 %Bi, -1
130   %not = xor i32 %A, -1
131   %l0 = icmp ult i32 %not, %B
132   %l1 = select i1 %l0, i32 %not, i32 %B
133   %x = sub i32 %l1, %not
134   ret i32 %x
137 define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) {
138 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi
139 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
140 ; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])
141 ; CHECK-NEXT:    ret i32 [[X]]
143   %B =  xor i32 %Bi, -1
144   %not = xor i32 %A, -1
145   %l0 = icmp ult i32 %not, %B
146   %l1 = select i1 %l0, i32 %not, i32 %B
147   %x = sub i32 %not, %l1
148   ret i32 %x
151 define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) {
152 ; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na
153 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
154 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])
155 ; CHECK-NEXT:    [[X:%.*]] = sub i32 0, [[TMP1]]
156 ; CHECK-NEXT:    ret i32 [[X]]
158   %B =  xor i32 %Bi, -1
159   %not = xor i32 %A, -1
160   %l0 = icmp ugt i32 %not, %B
161   %l1 = select i1 %l0, i32 %B, i32 %not
162   %x = sub i32 %l1, %not
163   ret i32 %x
166 define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) {
167 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na
168 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
169 ; CHECK-NEXT:    [[X:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI]], i32 [[A]])
170 ; CHECK-NEXT:    ret i32 [[X]]
172   %B =  xor i32 %Bi, -1
173   %not = xor i32 %A, -1
174   %l0 = icmp ugt i32 %not, %B
175   %l1 = select i1 %l0, i32 %B, i32 %not
176   %x = sub i32 %not, %l1
177   ret i32 %x
181 define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) {
182 ; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use
183 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
184 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 -32)
185 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
186 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]
187 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
188 ; CHECK-NEXT:    ret i32 [[X]]
190   %not = xor i32 %A, -1
191   %l0 = icmp ult i32 %not, 31
192   %l1 = select i1 %l0, i32 %not, i32 31
193   %x = sub i32 %l1, %not
194   call void @use32(i32 %l1)
195   ret i32 %x
198 define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) {
199 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use
200 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
201 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 -32)
202 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
203 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]
204 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
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 %not, %l1
211   call void @use32(i32 %l1)
212   ret i32 %x
215 define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) {
216 ; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use
217 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
218 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])
219 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
220 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]
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 %l1, %not
229   call void @use32(i32 %l1)
230   ret i32 %x
233 define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) {
234 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use
235 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
236 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])
237 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
238 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]
239 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
240 ; CHECK-NEXT:    ret i32 [[X]]
242   %not = xor i32 %A, -1
243   %B = xor i32 %Bi, -1
244   %l0 = icmp ult i32 %B, %not
245   %l1 = select i1 %l0, i32 %B, i32 %not
246   %x = sub i32 %not, %l1
247   call void @use32(i32 %l1)
248   ret i32 %x
252 define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) {
253 ; CHECK-LABEL: define {{[^@]+}}@max_na_bi_minux_na_use2
254 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
255 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
256 ; CHECK-NEXT:    [[L1:%.*]] = call i32 @llvm.umin.i32(i32 [[NOT]], i32 31)
257 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[L1]], [[NOT]]
258 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
259 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
260 ; CHECK-NEXT:    ret i32 [[X]]
262   %not = xor i32 %A, -1
263   %l0 = icmp ult i32 %not, 31
264   %l1 = select i1 %l0, i32 %not, i32 31
265   %x = sub i32 %l1, %not
266   call void @use32(i32 %l1)
267   call void @use32(i32 %not)
268   ret i32 %x
271 define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) {
272 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_na_bi_use2
273 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
274 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
275 ; CHECK-NEXT:    [[L1:%.*]] = call i32 @llvm.umin.i32(i32 [[NOT]], i32 31)
276 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[NOT]], [[L1]]
277 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
278 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
279 ; CHECK-NEXT:    ret i32 [[X]]
281   %not = xor i32 %A, -1
282   %l0 = icmp ult i32 %not, 31
283   %l1 = select i1 %l0, i32 %not, i32 31
284   %x = sub i32 %not, %l1
285   call void @use32(i32 %l1)
286   call void @use32(i32 %not)
287   ret i32 %x
290 define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) {
291 ; CHECK-LABEL: define {{[^@]+}}@max_bi_na_minus_na_use2
292 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
293 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
294 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])
295 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
296 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[A]], [[TMP1]]
297 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
298 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
299 ; CHECK-NEXT:    ret i32 [[X]]
301   %not = xor i32 %A, -1
302   %B = xor i32 %Bi, -1
303   %l0 = icmp ult i32 %B, %not
304   %l1 = select i1 %l0, i32 %B, i32 %not
305   %x = sub i32 %l1, %not
306   call void @use32(i32 %l1)
307   call void @use32(i32 %not)
308   ret i32 %x
311 define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) {
312 ; CHECK-LABEL: define {{[^@]+}}@na_minus_max_bi_na_use2
313 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[BI:%.*]]) {
314 ; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[A]], -1
315 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[BI]], i32 [[A]])
316 ; CHECK-NEXT:    [[L1:%.*]] = xor i32 [[TMP1]], -1
317 ; CHECK-NEXT:    [[X:%.*]] = sub i32 [[TMP1]], [[A]]
318 ; CHECK-NEXT:    call void @use32(i32 [[L1]])
319 ; CHECK-NEXT:    call void @use32(i32 [[NOT]])
320 ; CHECK-NEXT:    ret i32 [[X]]
322   %not = xor i32 %A, -1
323   %B = xor i32 %Bi, -1
324   %l0 = icmp ult i32 %B, %not
325   %l1 = select i1 %l0, i32 %B, i32 %not
326   %x = sub i32 %not, %l1
327   call void @use32(i32 %l1)
328   call void @use32(i32 %not)
329   ret i32 %x
332 define i8 @umin_not_sub(i8 %x, i8 %y) {
333 ; CHECK-LABEL: define {{[^@]+}}@umin_not_sub
334 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
335 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
336 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP1]], -1
337 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]
338 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[TMP1]], [[Y]]
339 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
340 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
341 ; CHECK-NEXT:    ret i8 [[MINXY]]
343   %nx = xor i8 %x, -1
344   %ny = xor i8 %y, -1
345   %cmpxy = icmp ult i8 %nx, %ny
346   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
347   %subx = sub i8 %nx, %minxy
348   %suby = sub i8 %ny, %minxy
349   call void @use8(i8 %subx)
350   call void @use8(i8 %suby)
351   ret i8 %minxy
354 define i8 @umin_not_sub_rev(i8 %x, i8 %y) {
355 ; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_rev
356 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
357 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
358 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP1]], -1
359 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]
360 ; CHECK-NEXT:    [[SUBY:%.*]] = sub i8 [[Y]], [[TMP1]]
361 ; CHECK-NEXT:    call void @use8(i8 [[SUBX]])
362 ; CHECK-NEXT:    call void @use8(i8 [[SUBY]])
363 ; CHECK-NEXT:    ret i8 [[MINXY]]
365   %nx = xor i8 %x, -1
366   %ny = xor i8 %y, -1
367   %cmpxy = icmp ult i8 %nx, %ny
368   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
369   %subx = sub i8 %minxy, %nx
370   %suby = sub i8 %minxy, %ny
371   call void @use8(i8 %subx)
372   call void @use8(i8 %suby)
373   ret i8 %minxy
376 define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) {
377 ; CHECK-LABEL: define {{[^@]+}}@umin3_not_all_ops_extra_uses_invert_subs
378 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
379 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Z]])
380 ; CHECK-NEXT:    [[TMP2:%.*]] = call i8 @llvm.umax.i8(i8 [[Y]], i8 [[TMP1]])
381 ; CHECK-NEXT:    [[MINXYZ:%.*]] = xor i8 [[TMP2]], -1
382 ; CHECK-NEXT:    [[XMIN:%.*]] = sub i8 [[TMP2]], [[X]]
383 ; CHECK-NEXT:    [[YMIN:%.*]] = sub i8 [[TMP2]], [[Y]]
384 ; CHECK-NEXT:    [[ZMIN:%.*]] = sub i8 [[TMP2]], [[Z]]
385 ; CHECK-NEXT:    call void @use8(i8 [[MINXYZ]])
386 ; CHECK-NEXT:    call void @use8(i8 [[XMIN]])
387 ; CHECK-NEXT:    call void @use8(i8 [[YMIN]])
388 ; CHECK-NEXT:    call void @use8(i8 [[ZMIN]])
389 ; CHECK-NEXT:    ret void
391   %xn = xor i8 %x, -1
392   %yn = xor i8 %y, -1
393   %zn = xor i8 %z, -1
394   %cmpxz = icmp ult i8 %xn, %zn
395   %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
396   %cmpxyz = icmp ult i8 %minxz, %yn
397   %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
398   %xmin = sub i8 %xn, %minxyz
399   %ymin = sub i8 %yn, %minxyz
400   %zmin = sub i8 %zn, %minxyz
401   call void @use8(i8 %minxyz)
402   call void @use8(i8 %xmin)
403   call void @use8(i8 %ymin)
404   call void @use8(i8 %zmin)
405   ret void
408 ; Handle this pattern with extra uses because it shows up in benchmarks.
409 ; ~X - Min/Max(~X, Y) -> ~Min/Max(X, ~Y) - X
410 ; ~X - Min/Max(Y, ~X) -> ~Min/Max(X, ~Y) - X
411 ; Min/Max(~X, Y) - ~X -> X - ~Min/Max(X, ~Y)
412 ; Min/Max(Y, ~X) - ~X -> X - ~Min/Max(X, ~Y)
414 define i8 @umin_not_sub_intrinsic_commute0(i8 %x, i8 %y) {
415 ; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_intrinsic_commute0
416 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
417 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1
418 ; CHECK-NEXT:    call void @use8(i8 [[NY]])
419 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
420 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
421 ; CHECK-NEXT:    call void @use8(i8 [[M]])
422 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]
423 ; CHECK-NEXT:    ret i8 [[SUBX]]
425   %nx = xor i8 %x, -1
426   %ny = xor i8 %y, -1
427   call void @use8(i8 %ny)
428   %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
429   call void @use8(i8 %m)
430   %subx = sub i8 %nx, %m
431   ret i8 %subx
434 define i8 @umax_not_sub_intrinsic_commute1(i8 %x, i8 %y) {
435 ; CHECK-LABEL: define {{[^@]+}}@umax_not_sub_intrinsic_commute1
436 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
437 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1
438 ; CHECK-NEXT:    call void @use8(i8 [[NY]])
439 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
440 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
441 ; CHECK-NEXT:    call void @use8(i8 [[M]])
442 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[TMP1]], [[X]]
443 ; CHECK-NEXT:    ret i8 [[SUBX]]
445   %nx = xor i8 %x, -1
446   %ny = xor i8 %y, -1
447   call void @use8(i8 %ny)
448   %m = call i8 @llvm.umax.i8(i8 %ny, i8 %nx)
449   call void @use8(i8 %m)
450   %subx = sub i8 %nx, %m
451   ret i8 %subx
454 define i8 @smin_not_sub_intrinsic_commute2(i8 %x, i8 %y) {
455 ; CHECK-LABEL: define {{[^@]+}}@smin_not_sub_intrinsic_commute2
456 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
457 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1
458 ; CHECK-NEXT:    call void @use8(i8 [[NY]])
459 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])
460 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
461 ; CHECK-NEXT:    call void @use8(i8 [[M]])
462 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]
463 ; CHECK-NEXT:    ret i8 [[SUBX]]
465   %nx = xor i8 %x, -1
466   %ny = xor i8 %y, -1
467   call void @use8(i8 %ny)
468   %m = call i8 @llvm.smin.i8(i8 %nx, i8 %ny)
469   call void @use8(i8 %m)
470   %subx = sub i8 %m, %nx
471   ret i8 %subx
474 define i8 @smax_not_sub_intrinsic_commute3(i8 %x, i8 %y) {
475 ; CHECK-LABEL: define {{[^@]+}}@smax_not_sub_intrinsic_commute3
476 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
477 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1
478 ; CHECK-NEXT:    call void @use8(i8 [[NY]])
479 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
480 ; CHECK-NEXT:    [[M:%.*]] = xor i8 [[TMP1]], -1
481 ; CHECK-NEXT:    call void @use8(i8 [[M]])
482 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[X]], [[TMP1]]
483 ; CHECK-NEXT:    ret i8 [[SUBX]]
485   %nx = xor i8 %x, -1
486   %ny = xor i8 %y, -1
487   call void @use8(i8 %ny)
488   %m = call i8 @llvm.smax.i8(i8 %ny, i8 %nx)
489   call void @use8(i8 %m)
490   %subx = sub i8 %m, %nx
491   ret i8 %subx
494 ; negative test - don't increase instruction count
496 define i8 @umin_not_sub_intrinsic_uses(i8 %x, i8 %y) {
497 ; CHECK-LABEL: define {{[^@]+}}@umin_not_sub_intrinsic_uses
498 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
499 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X]], -1
500 ; CHECK-NEXT:    call void @use8(i8 [[NX]])
501 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y]], -1
502 ; CHECK-NEXT:    call void @use8(i8 [[NY]])
503 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[NX]], i8 [[NY]])
504 ; CHECK-NEXT:    call void @use8(i8 [[M]])
505 ; CHECK-NEXT:    [[SUBX:%.*]] = sub i8 [[NX]], [[M]]
506 ; CHECK-NEXT:    ret i8 [[SUBX]]
508   %nx = xor i8 %x, -1
509   call void @use8(i8 %nx)
510   %ny = xor i8 %y, -1
511   call void @use8(i8 %ny)
512   %m = call i8 @llvm.umin.i8(i8 %nx, i8 %ny)
513   call void @use8(i8 %m)
514   %subx = sub i8 %nx, %m
515   ret i8 %subx
518 define i8 @umax_sub_op0(i8 %x, i8 %y) {
519 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0
520 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
521 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X]], i8 [[Y]])
522 ; CHECK-NEXT:    ret i8 [[R]]
524   %u = call i8 @llvm.umax.i8(i8 %y, i8 %x)
525   %r = sub i8 %u, %y
526   ret i8 %r
529 define <2 x i8> @umax_sub_op0_vec_commute(<2 x i8> %x, <2 x i8> %y) {
530 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0_vec_commute
531 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
532 ; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
533 ; CHECK-NEXT:    ret <2 x i8> [[R]]
535   %u = call <2 x i8> @llvm.umax.v2i8(<2 x i8> %x, <2 x i8> %y)
536   %r = sub <2 x i8> %u, %y
537   ret <2 x i8> %r
540 define i8 @umax_sub_op0_use(i8 %x, i8 %y) {
541 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op0_use
542 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
543 ; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
544 ; CHECK-NEXT:    call void @use8(i8 [[U]])
545 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[U]], [[Y]]
546 ; CHECK-NEXT:    ret i8 [[R]]
548   %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)
549   call void @use8(i8 %u)
550   %r = sub i8 %u, %y
551   ret i8 %r
554 define i8 @umax_sub_op1(i8 %x, i8 %y) {
555 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1
556 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
557 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X]], i8 [[Y]])
558 ; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]
559 ; CHECK-NEXT:    ret i8 [[R]]
561   %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)
562   %r = sub i8 %y, %u
563   ret i8 %r
566 define <2 x i8> @umax_sub_op1_vec_commute(<2 x i8> %x, <2 x i8> %y) {
567 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1_vec_commute
568 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
569 ; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
570 ; CHECK-NEXT:    [[R:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
571 ; CHECK-NEXT:    ret <2 x i8> [[R]]
573   %u = call <2 x i8> @llvm.umax.v2i8(<2 x i8> %y, <2 x i8> %x)
574   %r = sub <2 x i8> %y, %u
575   ret <2 x i8> %r
578 define i8 @umax_sub_op1_use(i8 %x, i8 %y) {
579 ; CHECK-LABEL: define {{[^@]+}}@umax_sub_op1_use
580 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
581 ; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
582 ; CHECK-NEXT:    call void @use8(i8 [[U]])
583 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[U]]
584 ; CHECK-NEXT:    ret i8 [[R]]
586   %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)
587   call void @use8(i8 %u)
588   %r = sub i8 %y, %u
589   ret i8 %r
592 define i8 @umin_sub_op1(i8 %x, i8 %y) {
593 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1
594 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
595 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])
596 ; CHECK-NEXT:    ret i8 [[R]]
598   %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
599   %r = sub i8 %y, %u
600   ret i8 %r
603 define i8 @umin_sub_op1_commute(i8 %x, i8 %y) {
604 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_commute
605 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
606 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])
607 ; CHECK-NEXT:    ret i8 [[R]]
609   %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
610   %r = sub i8 %y, %u
611   ret i8 %r
614 define i8 @umin_sub_op0(i8 %x, i8 %y) {
615 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0
616 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
617 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])
618 ; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]
619 ; CHECK-NEXT:    ret i8 [[R]]
621   %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
622   %r = sub i8 %u, %y
623   ret i8 %r
626 define i8 @umin_sub_op0_commute(i8 %x, i8 %y) {
627 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_commute
628 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
629 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[X]])
630 ; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[TMP1]]
631 ; CHECK-NEXT:    ret i8 [[R]]
633   %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
634   %r = sub i8 %u, %y
635   ret i8 %r
638 define i8 @umin_sub_op1_use(i8 %x, i8 %y) {
639 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op1_use
640 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
641 ; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
642 ; CHECK-NEXT:    call void @use8(i8 [[U]])
643 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[U]]
644 ; CHECK-NEXT:    ret i8 [[R]]
646   %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
647   call void @use8(i8 %u)
648   %r = sub i8 %y, %u
649   ret i8 %r
652 define i8 @umin_sub_op0_use(i8 %x, i8 %y) {
653 ; CHECK-LABEL: define {{[^@]+}}@umin_sub_op0_use
654 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
655 ; CHECK-NEXT:    [[U:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
656 ; CHECK-NEXT:    call void @use8(i8 [[U]])
657 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[U]], [[Y]]
658 ; CHECK-NEXT:    ret i8 [[R]]
660   %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
661   call void @use8(i8 %u)
662   %r = sub i8 %u, %y
663   ret i8 %r
667 ; sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y)
668 ; sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y)
671 define i8 @diff_add_smin(i8 %x, i8 %y) {
672 ; CHECK-LABEL: define {{[^@]+}}@diff_add_smin
673 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
674 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])
675 ; CHECK-NEXT:    ret i8 [[S]]
677   %a = add i8 %x, %y
678   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
679   %s = sub i8 %a, %m
680   ret i8 %s
683 define i8 @diff_add_smax(i8 %x, i8 %y) {
684 ; CHECK-LABEL: define {{[^@]+}}@diff_add_smax
685 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
686 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
687 ; CHECK-NEXT:    ret i8 [[S]]
689   %a = add i8 %x, %y
690   %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)
691   %s = sub i8 %a, %m
692   ret i8 %s
695 define i8 @diff_add_umin(i8 %x, i8 %y) {
696 ; CHECK-LABEL: define {{[^@]+}}@diff_add_umin
697 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
698 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]])
699 ; CHECK-NEXT:    ret i8 [[S]]
701   %a = add i8 %x, %y
702   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
703   %s = sub i8 %a, %m
704   ret i8 %s
707 define i8 @diff_add_umax(i8 %x, i8 %y) {
708 ; CHECK-LABEL: define {{[^@]+}}@diff_add_umax
709 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
710 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[X]])
711 ; CHECK-NEXT:    ret i8 [[S]]
713   %a = add i8 %x, %y
714   %m = call i8 @llvm.umax.i8(i8 %y, i8 %x)
715   %s = sub i8 %a, %m
716   ret i8 %s
719 define i8 @diff_add_smin_use(i8 %x, i8 %y) {
720 ; CHECK-LABEL: define {{[^@]+}}@diff_add_smin_use
721 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
722 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
723 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])
724 ; CHECK-NEXT:    call void @use8(i8 [[M]])
725 ; CHECK-NEXT:    ret i8 [[S]]
727   %a = add i8 %x, %y
728   %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
729   %s = sub i8 %a, %m
730   call void @use8(i8 %m)
731   ret i8 %s
734 define i8 @diff_add_use_smax(i8 %x, i8 %y) {
735 ; CHECK-LABEL: define {{[^@]+}}@diff_add_use_smax
736 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
737 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]
738 ; CHECK-NEXT:    [[S:%.*]] = call i8 @llvm.smin.i8(i8 [[Y]], i8 [[X]])
739 ; CHECK-NEXT:    call void @use8(i8 [[A]])
740 ; CHECK-NEXT:    ret i8 [[S]]
742   %a = add i8 %x, %y
743   %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)
744   %s = sub i8 %a, %m
745   call void @use8(i8 %a)
746   ret i8 %s
749 define i8 @diff_add_use_umin_use(i8 %x, i8 %y) {
750 ; CHECK-LABEL: define {{[^@]+}}@diff_add_use_umin_use
751 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
752 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]
753 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]])
754 ; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]
755 ; CHECK-NEXT:    call void @use8(i8 [[A]])
756 ; CHECK-NEXT:    call void @use8(i8 [[M]])
757 ; CHECK-NEXT:    ret i8 [[S]]
759   %a = add i8 %x, %y
760   %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
761   %s = sub i8 %a, %m
762   call void @use8(i8 %a)
763   call void @use8(i8 %m)
764   ret i8 %s
767 ; sub(add(X,Y),umin(Y,Z)) --> add(X,usubsat(Y,Z))
769 define i8 @sub_add_umin(i8 %x, i8 %y, i8 %z) {
770 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin
771 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
772 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])
773 ; CHECK-NEXT:    [[S:%.*]] = add i8 [[TMP1]], [[X]]
774 ; CHECK-NEXT:    ret i8 [[S]]
776   %a = add i8 %x, %y
777   %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
778   %s = sub i8 %a, %m
779   ret i8 %s
782 define i8 @sub_add_umin_commute_umin(i8 %x, i8 %y, i8 %z) {
783 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_umin
784 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
785 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])
786 ; CHECK-NEXT:    [[S:%.*]] = add i8 [[TMP1]], [[X]]
787 ; CHECK-NEXT:    ret i8 [[S]]
789   %a = add i8 %x, %y
790   %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)
791   %s = sub i8 %a, %m
792   ret i8 %s
795 define i8 @sub_add_umin_commute_add(i8 %x, i8 %y, i8 %z) {
796 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add
797 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
798 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])
799 ; CHECK-NEXT:    [[S:%.*]] = add i8 [[TMP1]], [[X]]
800 ; CHECK-NEXT:    ret i8 [[S]]
802   %a = add i8 %y, %x
803   %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
804   %s = sub i8 %a, %m
805   ret i8 %s
808 define i8 @sub_add_umin_commute_add_umin(i8 %x, i8 %y, i8 %z) {
809 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_commute_add_umin
810 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
811 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[Y]], i8 [[Z]])
812 ; CHECK-NEXT:    [[S:%.*]] = add i8 [[TMP1]], [[X]]
813 ; CHECK-NEXT:    ret i8 [[S]]
815   %a = add i8 %y, %x
816   %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)
817   %s = sub i8 %a, %m
818   ret i8 %s
821 define <2 x i8> @sub_add_umin_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {
822 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_vec
823 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <2 x i8> [[Z:%.*]]) {
824 ; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[Y]], <2 x i8> [[Z]])
825 ; CHECK-NEXT:    [[S:%.*]] = add <2 x i8> [[TMP1]], [[X]]
826 ; CHECK-NEXT:    ret <2 x i8> [[S]]
828   %a = add <2 x i8> %x, %y
829   %m = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %y, <2 x i8> %z)
830   %s = sub <2 x i8> %a, %m
831   ret <2 x i8> %s
834 ; negative test
836 define i8 @sub_add_umin_mismatch(i8 %x, i8 %y, i8 %z, i8 %t) {
837 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_mismatch
838 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[T:%.*]]) {
839 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]
840 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[T]], i8 [[Z]])
841 ; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]
842 ; CHECK-NEXT:    ret i8 [[S]]
844   %a = add i8 %x, %y
845   %m = call i8 @llvm.umin.i8(i8 %t, i8 %z)
846   %s = sub i8 %a, %m
847   ret i8 %s
850 define i8 @sub_add_umin_use_a(i8 %x, i8 %y, i8 %z) {
851 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_a
852 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
853 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]
854 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
855 ; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]
856 ; CHECK-NEXT:    call void @use8(i8 [[A]])
857 ; CHECK-NEXT:    ret i8 [[S]]
859   %a = add i8 %x, %y
860   %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
861   %s = sub i8 %a, %m
862   call void @use8(i8 %a)
863   ret i8 %s
866 define i8 @sub_add_umin_use_m(i8 %x, i8 %y, i8 %z) {
867 ; CHECK-LABEL: define {{[^@]+}}@sub_add_umin_use_m
868 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
869 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X]], [[Y]]
870 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y]], i8 [[Z]])
871 ; CHECK-NEXT:    [[S:%.*]] = sub i8 [[A]], [[M]]
872 ; CHECK-NEXT:    call void @use8(i8 [[M]])
873 ; CHECK-NEXT:    ret i8 [[S]]
875   %a = add i8 %x, %y
876   %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
877   %s = sub i8 %a, %m
878   call void @use8(i8 %m)
879   ret i8 %s
882 define <2 x i8> @sub_smax0_sub_nsw(<2 x i8> %x, <2 x i8> %y) {
883 ; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw
884 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
885 ; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.smin.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
886 ; CHECK-NEXT:    ret <2 x i8> [[R]]
888   %sub = sub nsw <2 x i8> %x, %y
889   %m = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %sub, <2 x i8> <i8 0, i8 poison>)
890   %r = sub <2 x i8> %x, %m
891   ret <2 x i8> %r
894 define i8 @sub_smax0_sub_nsw_use(i8 %x, i8 %y) {
895 ; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_nsw_use
896 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
897 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]
898 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)
899 ; CHECK-NEXT:    call void @use8(i8 [[M]])
900 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]])
901 ; CHECK-NEXT:    ret i8 [[R]]
903   %sub = sub nsw i8 %x, %y
904   %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)
905   call void @use8(i8 %m)
906   %r = sub i8 %x, %m
907   ret i8 %r
910 ; negative test - must have nsw
912 define i8 @sub_smax0_sub(i8 %x, i8 %y) {
913 ; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub
914 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
915 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X]], [[Y]]
916 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)
917 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]
918 ; CHECK-NEXT:    ret i8 [[R]]
920   %sub = sub i8 %x, %y
921   %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)
922   %r = sub i8 %x, %m
923   ret i8 %r
926 ; negative test - wrong op
928 define i8 @sub_smax0_sub_commute(i8 %x, i8 %y) {
929 ; CHECK-LABEL: define {{[^@]+}}@sub_smax0_sub_commute
930 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
931 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]
932 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[SUB]], i8 0)
933 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[M]], [[X]]
934 ; CHECK-NEXT:    ret i8 [[R]]
936   %sub = sub nsw i8 %x, %y
937   %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)
938   %r = sub i8 %m, %x
939   ret i8 %r
942 define i8 @sub_smin0_sub_nsw_use(i8 %x, i8 %y) {
943 ; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_use
944 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
945 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[X]], [[Y]]
946 ; CHECK-NEXT:    call void @use8(i8 [[SUB]])
947 ; CHECK-NEXT:    [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]])
948 ; CHECK-NEXT:    ret i8 [[R]]
950   %sub = sub nsw i8 %x, %y
951   call void @use8(i8 %sub)
952   %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)
953   %r = sub i8 %x, %m
954   ret i8 %r
957 define <2 x i8> @sub_smin0_sub_nsw(<2 x i8> %x, <2 x i8> %y) {
958 ; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw
959 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
960 ; CHECK-NEXT:    [[R:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
961 ; CHECK-NEXT:    ret <2 x i8> [[R]]
963   %sub = sub nsw <2 x i8> %x, %y
964   %m = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %sub, <2 x i8> zeroinitializer)
965   %r = sub <2 x i8> %x, %m
966   ret <2 x i8> %r
969 ; negative test - must have nsw
971 define i8 @sub_smin0_sub(i8 %x, i8 %y) {
972 ; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub
973 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
974 ; CHECK-NEXT:    [[SUB:%.*]] = sub i8 [[X]], [[Y]]
975 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[SUB]], i8 0)
976 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]
977 ; CHECK-NEXT:    ret i8 [[R]]
979   %sub = sub i8 %x, %y
980   %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)
981   %r = sub i8 %x, %m
982   ret i8 %r
985 ; negative test - wrong op
987 define i8 @sub_smin0_sub_nsw_commute(i8 %x, i8 %y) {
988 ; CHECK-LABEL: define {{[^@]+}}@sub_smin0_sub_nsw_commute
989 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
990 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[Y]], [[X]]
991 ; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[SUB]], i8 0)
992 ; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[M]]
993 ; CHECK-NEXT:    ret i8 [[R]]
995   %sub = sub nsw i8 %y, %x
996   %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)
997   %r = sub i8 %x, %m
998   ret i8 %r
1001 define i8 @sub_max_min_nsw(i8 %a, i8 %b) {
1002 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw
1003 ; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {
1004 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]
1005 ; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)
1006 ; CHECK-NEXT:    ret i8 [[AB]]
1008   %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
1009   %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
1010   %ab = sub nsw i8 %max, %min
1011   ret i8 %ab
1014 define i8 @sub_max_min_nuw(i8 %a, i8 %b) {
1015 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw
1016 ; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {
1017 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]
1018 ; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)
1019 ; CHECK-NEXT:    ret i8 [[AB]]
1021   %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
1022   %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
1023   %ab = sub nuw i8 %max, %min
1024   ret i8 %ab
1027 define i8 @sub_max_min_nsw_commute(i8 %a, i8 %b) {
1028 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nsw_commute
1029 ; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {
1030 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]
1031 ; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)
1032 ; CHECK-NEXT:    ret i8 [[AB]]
1034   %min = call i8 @llvm.smin.i8(i8 %b, i8 %a)
1035   %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
1036   %ab = sub nsw i8 %max, %min
1037   ret i8 %ab
1040 define i8 @sub_max_min_nuw_commute(i8 %a, i8 %b) {
1041 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_nuw_commute
1042 ; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {
1043 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A]], [[B]]
1044 ; CHECK-NEXT:    [[AB:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB]], i1 true)
1045 ; CHECK-NEXT:    ret i8 [[AB]]
1047   %min = call i8 @llvm.smin.i8(i8 %b, i8 %a)
1048   %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
1049   %ab = sub nuw i8 %max, %min
1050   ret i8 %ab
1053 define <2 x i8> @sub_max_min_vec_nsw(<2 x i8> %a, <2 x i8> %b) {
1054 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nsw
1055 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
1056 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]
1057 ; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)
1058 ; CHECK-NEXT:    ret <2 x i8> [[AB]]
1060   %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)
1061   %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)
1062   %ab = sub nsw <2 x i8> %max, %min
1063   ret <2 x i8> %ab
1066 define <2 x i8> @sub_max_min_vec_nuw(<2 x i8> %a, <2 x i8> %b) {
1067 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nuw
1068 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
1069 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]
1070 ; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)
1071 ; CHECK-NEXT:    ret <2 x i8> [[AB]]
1073   %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)
1074   %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)
1075   %ab = sub nuw <2 x i8> %max, %min
1076   ret <2 x i8> %ab
1079 define <2 x i8> @sub_max_min_vec_nsw_commute(<2 x i8> %a, <2 x i8> %b) {
1080 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nsw_commute
1081 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
1082 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]
1083 ; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)
1084 ; CHECK-NEXT:    ret <2 x i8> [[AB]]
1086   %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %b, <2 x i8> %a)
1087   %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)
1088   %ab = sub nsw <2 x i8> %max, %min
1089   ret <2 x i8> %ab
1092 define <2 x i8> @sub_max_min_vec_nuw_commute(<2 x i8> %a, <2 x i8> %b) {
1093 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_nuw_commute
1094 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
1095 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw <2 x i8> [[A]], [[B]]
1096 ; CHECK-NEXT:    [[AB:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB]], i1 true)
1097 ; CHECK-NEXT:    ret <2 x i8> [[AB]]
1099   %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %b, <2 x i8> %a)
1100   %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)
1101   %ab = sub nuw <2 x i8> %max, %min
1102   ret <2 x i8> %ab
1105 ; negative test - multiple use
1107 define i8 @sub_max_min_multi_use(i8 %a, i8 %b) {
1108 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_multi_use
1109 ; CHECK-SAME: (i8 [[A:%.*]], i8 [[B:%.*]]) {
1110 ; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 [[B]])
1111 ; CHECK-NEXT:    call void @use8(i8 [[MIN]])
1112 ; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]])
1113 ; CHECK-NEXT:    call void @use8(i8 [[MAX]])
1114 ; CHECK-NEXT:    [[AB:%.*]] = sub nsw i8 [[MAX]], [[MIN]]
1115 ; CHECK-NEXT:    ret i8 [[AB]]
1117   %min = call i8 @llvm.smin.i8(i8 %a, i8 %b)
1118   call void @use8(i8 %min)
1119   %max = call i8 @llvm.smax.i8(i8 %a, i8 %b)
1120   call void @use8(i8 %max)
1121   %ab = sub nsw i8 %max, %min
1122   ret i8 %ab
1125 define <2 x i8> @sub_max_min_vec_multi_use(<2 x i8> %a, <2 x i8> %b) {
1126 ; CHECK-LABEL: define {{[^@]+}}@sub_max_min_vec_multi_use
1127 ; CHECK-SAME: (<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
1128 ; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i8> @llvm.smin.v2i8(<2 x i8> [[A]], <2 x i8> [[B]])
1129 ; CHECK-NEXT:    call void @use8v2(<2 x i8> [[MIN]])
1130 ; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[A]], <2 x i8> [[B]])
1131 ; CHECK-NEXT:    call void @use8v2(<2 x i8> [[MAX]])
1132 ; CHECK-NEXT:    [[AB:%.*]] = sub nsw <2 x i8> [[MAX]], [[MIN]]
1133 ; CHECK-NEXT:    ret <2 x i8> [[AB]]
1135   %min = call <2 x i8> @llvm.smin.v2i8(<2 x i8> %a, <2 x i8> %b)
1136   call void @use8v2(<2 x i8> %min)
1137   %max = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %a, <2 x i8> %b)
1138   call void @use8v2(<2 x i8> %max)
1139   %ab = sub nsw <2 x i8> %max, %min
1140   ret <2 x i8> %ab
1143 declare void @use8(i8)
1144 declare void @use32(i32 %u)
1146 declare void @use8v2(i8)