xref: /llvm-project/llvm/test/Transforms/InstCombine/sub-minmax.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
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
3
4declare i5 @llvm.umin.i5(i5, i5)
5declare <2 x i8> @llvm.smin.v2i8(<2 x i8>, <2 x i8>)
6declare <2 x i8> @llvm.smax.v2i8(<2 x i8>, <2 x i8>)
7declare <2 x i8> @llvm.umin.v2i8(<2 x i8>, <2 x i8>)
8declare <2 x i8> @llvm.umax.v2i8(<2 x i8>, <2 x i8>)
9
10declare i8 @llvm.smax.i8(i8, i8)
11declare i8 @llvm.smin.i8(i8, i8)
12declare i8 @llvm.umax.i8(i8, i8)
13declare i8 @llvm.umin.i8(i8, i8)
14
15define 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]]
22;
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
28}
29
30define 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]]
36;
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
42}
43
44define 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]]
49;
50  %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
51  %r = sub i5 %a, %umin
52  ret i5 %r
53}
54
55define <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]]
60;
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
64}
65
66define 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]]
73;
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
78}
79
80define 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]]
86;
87  %umin = call i5 @llvm.umin.i5(i5 %a, i5 %b)
88  %r = sub i5 %c, %umin
89  ret i5 %r
90}
91
92define 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]]
99;
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
105}
106
107define 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]]
113;
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
119}
120
121
122define 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]]
128;
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
135}
136
137define 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]]
142;
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
149}
150
151define 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]]
157;
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
164}
165
166define 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]]
171;
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
178}
179
180
181define 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]]
189;
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
196}
197
198define 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]]
206;
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
213}
214
215define 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]]
223;
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
231}
232
233define 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]]
241;
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
249}
250
251
252define 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]]
261;
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
269}
270
271define 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]]
280;
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
288}
289
290define 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]]
300;
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
309}
310
311define 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]]
321;
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
330}
331
332define 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]]
342;
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
352}
353
354define 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]]
364;
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
374}
375
376define 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
390;
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
406}
407
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)
413
414define 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]]
424;
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
432}
433
434define 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]]
444;
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
452}
453
454define 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]]
464;
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
472}
473
474define 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]]
484;
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
492}
493
494; negative test - don't increase instruction count
495
496define 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]]
507;
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
516}
517
518define 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]]
523;
524  %u = call i8 @llvm.umax.i8(i8 %y, i8 %x)
525  %r = sub i8 %u, %y
526  ret i8 %r
527}
528
529define <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]]
534;
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
538}
539
540define 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]]
547;
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
552}
553
554define 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]]
560;
561  %u = call i8 @llvm.umax.i8(i8 %x, i8 %y)
562  %r = sub i8 %y, %u
563  ret i8 %r
564}
565
566define <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]]
572;
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
576}
577
578define 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]]
585;
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
590}
591
592define 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]]
597;
598  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
599  %r = sub i8 %y, %u
600  ret i8 %r
601}
602
603define 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]]
608;
609  %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
610  %r = sub i8 %y, %u
611  ret i8 %r
612}
613
614define 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]]
620;
621  %u = call i8 @llvm.umin.i8(i8 %y, i8 %x)
622  %r = sub i8 %u, %y
623  ret i8 %r
624}
625
626define 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]]
632;
633  %u = call i8 @llvm.umin.i8(i8 %x, i8 %y)
634  %r = sub i8 %u, %y
635  ret i8 %r
636}
637
638define 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]]
645;
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
650}
651
652define 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]]
659;
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
664}
665
666;
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)
669;
670
671define 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]]
676;
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
681}
682
683define 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]]
688;
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
693}
694
695define 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]]
700;
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
705}
706
707define 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]]
712;
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
717}
718
719define 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]]
726;
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
732}
733
734define 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]]
741;
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
747}
748
749define 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]]
758;
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
765}
766
767; sub(add(X,Y),umin(Y,Z)) --> add(X,usubsat(Y,Z))
768
769define 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 [[X]], [[TMP1]]
774; CHECK-NEXT:    ret i8 [[S]]
775;
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
780}
781
782define 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 [[X]], [[TMP1]]
787; CHECK-NEXT:    ret i8 [[S]]
788;
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
793}
794
795define 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 [[X]], [[TMP1]]
800; CHECK-NEXT:    ret i8 [[S]]
801;
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
806}
807
808define 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 [[X]], [[TMP1]]
813; CHECK-NEXT:    ret i8 [[S]]
814;
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
819}
820
821define <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> [[X]], [[TMP1]]
826; CHECK-NEXT:    ret <2 x i8> [[S]]
827;
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
832}
833
834; negative test
835
836define 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]]
843;
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
848}
849
850define 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]]
858;
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
864}
865
866define 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]]
874;
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
880}
881
882define <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]]
887;
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
892}
893
894define 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]]
902;
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
908}
909
910; negative test - must have nsw
911
912define 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]]
919;
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
924}
925
926; negative test - wrong op
927
928define 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]]
935;
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
940}
941
942define 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]]
949;
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
955}
956
957define <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]]
962;
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
967}
968
969; negative test - must have nsw
970
971define 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]]
978;
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
983}
984
985; negative test - wrong op
986
987define 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]]
994;
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
999}
1000
1001define 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]]
1007;
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
1012}
1013
1014define 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]]
1020;
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
1025}
1026
1027define 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]]
1033;
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
1038}
1039
1040define 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]]
1046;
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
1051}
1052
1053define <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]]
1059;
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
1064}
1065
1066define <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]]
1072;
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
1077}
1078
1079define <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]]
1085;
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
1090}
1091
1092define <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]]
1098;
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
1103}
1104
1105; negative test - multiple use
1106
1107define 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]]
1116;
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
1123}
1124
1125define <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]]
1134;
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
1141}
1142
1143declare void @use8(i8)
1144declare void @use32(i32 %u)
1145
1146declare void @use8v2(i8)
1147