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]]
24 %l0 = icmp ult i32 %not, %B
25 %l1 = select i1 %l0, i32 %not, i32 %B
26 %x = sub i32 %l1, %not
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]]
38 %l0 = icmp ult i32 %not, %B
39 %l1 = select i1 %l0, i32 %not, i32 %B
40 %x = sub i32 %not, %l1
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)
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
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
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)
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
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
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]]
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
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]]
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
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]]
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
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]]
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
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)
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)
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
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)
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
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)
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)
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)
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
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)
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
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)
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]]
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)
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]]
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)
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
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)
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]]
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
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]]
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
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]]
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
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]]
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
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]]
509 call void @use8(i8 %nx)
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
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)
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
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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]]
678 %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
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]]
690 %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)
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]]
702 %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
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]]
714 %m = call i8 @llvm.umax.i8(i8 %y, i8 %x)
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]]
728 %m = call i8 @llvm.smin.i8(i8 %x, i8 %y)
730 call void @use8(i8 %m)
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]]
743 %m = call i8 @llvm.smax.i8(i8 %y, i8 %x)
745 call void @use8(i8 %a)
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]]
760 %m = call i8 @llvm.umin.i8(i8 %x, i8 %y)
762 call void @use8(i8 %a)
763 call void @use8(i8 %m)
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]]
777 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
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]]
790 %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)
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]]
803 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
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]]
816 %m = call i8 @llvm.umin.i8(i8 %z, i8 %y)
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
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]]
845 %m = call i8 @llvm.umin.i8(i8 %t, i8 %z)
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]]
860 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
862 call void @use8(i8 %a)
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]]
876 %m = call i8 @llvm.umin.i8(i8 %y, i8 %z)
878 call void @use8(i8 %m)
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
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)
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]]
921 %m = call i8 @llvm.smax.i8(i8 %sub, i8 0)
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)
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)
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
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]]
980 %m = call i8 @llvm.smin.i8(i8 %sub, i8 0)
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)
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
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
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
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
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
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
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
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
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
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
1143 declare void @use8(i8)
1144 declare void @use32(i32 %u)
1146 declare void @use8v2(i8)