[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / unsigned_saturated_sub.ll
blob60da66b7a388a917ed85975f80f8b82dd3a19db7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 ; Canonicalization of unsigned saturated subtraction idioms to
5 ; usub.sat() intrinsics is tested here.
7 declare void @use(i64)
8 declare void @usei32(i32)
9 declare void @usei1(i1)
11 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
13 define i64 @max_sub_ugt(i64 %a, i64 %b) {
14 ; CHECK-LABEL: @max_sub_ugt(
15 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
16 ; CHECK-NEXT:    ret i64 [[TMP1]]
18   %cmp = icmp ugt i64 %a, %b
19   %sub = sub i64 %a, %b
20   %sel = select i1 %cmp, i64 %sub ,i64 0
21   ret i64 %sel
24 ; (a >= b) ? a - b : 0 -> usub.sat(a, b)
26 define i64 @max_sub_uge(i64 %a, i64 %b) {
27 ; CHECK-LABEL: @max_sub_uge(
28 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
29 ; CHECK-NEXT:    ret i64 [[TMP1]]
31   %cmp = icmp uge i64 %a, %b
32   %sub = sub i64 %a, %b
33   %sel = select i1 %cmp, i64 %sub ,i64 0
34   ret i64 %sel
37 define i64 @max_sub_uge_extrause1(i64 %a, i64 %b) {
38 ; CHECK-LABEL: @max_sub_uge_extrause1(
39 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]
40 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
41 ; CHECK-NEXT:    call void @use(i64 [[SUB]])
42 ; CHECK-NEXT:    ret i64 [[TMP1]]
44   %cmp = icmp uge i64 %a, %b
45   %sub = sub i64 %a, %b
46   %sel = select i1 %cmp, i64 %sub ,i64 0
47   call void @use(i64 %sub)
48   ret i64 %sel
51 define i64 @max_sub_uge_extrause2(i64 %a, i64 %b) {
52 ; CHECK-LABEL: @max_sub_uge_extrause2(
53 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]]
54 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
55 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
56 ; CHECK-NEXT:    ret i64 [[TMP1]]
58   %cmp = icmp uge i64 %a, %b
59   %sub = sub i64 %a, %b
60   %sel = select i1 %cmp, i64 %sub ,i64 0
61   call void @usei1(i1 %cmp)
62   ret i64 %sel
65 define i64 @max_sub_uge_extrause3(i64 %a, i64 %b) {
66 ; CHECK-LABEL: @max_sub_uge_extrause3(
67 ; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]]
68 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[A]], [[B]]
69 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
70 ; CHECK-NEXT:    call void @use(i64 [[SUB]])
71 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
72 ; CHECK-NEXT:    ret i64 [[TMP1]]
74   %cmp = icmp uge i64 %a, %b
75   %sub = sub i64 %a, %b
76   %sel = select i1 %cmp, i64 %sub ,i64 0
77   call void @use(i64 %sub)
78   call void @usei1(i1 %cmp)
79   ret i64 %sel
82 ; Again, with vectors:
83 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
85 define <4 x i32> @max_sub_ugt_vec(<4 x i32> %a, <4 x i32> %b) {
86 ; CHECK-LABEL: @max_sub_ugt_vec(
87 ; CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]])
88 ; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
90   %cmp = icmp ugt <4 x i32> %a, %b
91   %sub = sub <4 x i32> %a, %b
92   %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer
93   ret <4 x i32> %sel
96 ; Use extra ops to thwart icmp swapping canonicalization.
97 ; (b < a) ? a - b : 0 -> usub.sat(a, b)
99 define i64 @max_sub_ult(i64 %a, i64 %b) {
100 ; CHECK-LABEL: @max_sub_ult(
101 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
102 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
103 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
104 ; CHECK-NEXT:    ret i64 [[TMP1]]
106   %cmp = icmp ult i64 %b, %a
107   %sub = sub i64 %a, %b
108   %sel = select i1 %cmp, i64 %sub ,i64 0
109   %extrasub = sub i64 %b, %a
110   call void @use(i64 %extrasub)
111   ret i64 %sel
114 ; (b > a) ? 0 : a - b -> usub.sat(a, b)
116 define i64 @max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
117 ; CHECK-LABEL: @max_sub_ugt_sel_swapped(
118 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
119 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
120 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
121 ; CHECK-NEXT:    ret i64 [[TMP1]]
123   %cmp = icmp ugt i64 %b, %a
124   %sub = sub i64 %a, %b
125   %sel = select i1 %cmp, i64 0 ,i64 %sub
126   %extrasub = sub i64 %b, %a
127   call void @use(i64 %extrasub)
128   ret i64 %sel
131 ; (a < b) ? 0 : a - b -> usub.sat(a, b)
133 define i64 @max_sub_ult_sel_swapped(i64 %a, i64 %b) {
134 ; CHECK-LABEL: @max_sub_ult_sel_swapped(
135 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
136 ; CHECK-NEXT:    ret i64 [[TMP1]]
138   %cmp = icmp ult i64 %a, %b
139   %sub = sub i64 %a, %b
140   %sel = select i1 %cmp, i64 0 ,i64 %sub
141   ret i64 %sel
144 ; ((a > b) ? b - a : 0) -> -usub.sat(a, b)
146 define i64 @neg_max_sub_ugt(i64 %a, i64 %b) {
147 ; CHECK-LABEL: @neg_max_sub_ugt(
148 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
149 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
150 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
151 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
152 ; CHECK-NEXT:    ret i64 [[TMP2]]
154   %cmp = icmp ugt i64 %a, %b
155   %sub = sub i64 %b, %a
156   %sel = select i1 %cmp, i64 %sub ,i64 0
157   %extrasub = sub i64 %a, %b
158   call void @use(i64 %extrasub)
159   ret i64 %sel
162 ; ((b < a) ? b - a : 0) -> -usub.sat(a, b)
164 define i64 @neg_max_sub_ult(i64 %a, i64 %b) {
165 ; CHECK-LABEL: @neg_max_sub_ult(
166 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
167 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
168 ; CHECK-NEXT:    ret i64 [[TMP2]]
170   %cmp = icmp ult i64 %b, %a
171   %sub = sub i64 %b, %a
172   %sel = select i1 %cmp, i64 %sub ,i64 0
173   ret i64 %sel
176 ; ((b > a) ? 0 : b - a) -> -usub.sat(a, b)
178 define i64 @neg_max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
179 ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped(
180 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
181 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
182 ; CHECK-NEXT:    ret i64 [[TMP2]]
184   %cmp = icmp ugt i64 %b, %a
185   %sub = sub i64 %b, %a
186   %sel = select i1 %cmp, i64 0 ,i64 %sub
187   ret i64 %sel
190 define i64 @neg_max_sub_ugt_sel_swapped_extrause1(i64 %a, i64 %b) {
191 ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause1(
192 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]]
193 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
194 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
195 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
196 ; CHECK-NEXT:    ret i64 [[TMP2]]
198   %cmp = icmp ugt i64 %b, %a
199   %sub = sub i64 %b, %a
200   %sel = select i1 %cmp, i64 0 ,i64 %sub
201   call void @usei1(i1 %cmp)
202   ret i64 %sel
205 define i64 @neg_max_sub_ugt_sel_swapped_extrause2(i64 %a, i64 %b) {
206 ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause2(
207 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]
208 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
209 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
210 ; CHECK-NEXT:    call void @use(i64 [[SUB]])
211 ; CHECK-NEXT:    ret i64 [[TMP2]]
213   %cmp = icmp ugt i64 %b, %a
214   %sub = sub i64 %b, %a
215   %sel = select i1 %cmp, i64 0 ,i64 %sub
216   call void @use(i64 %sub)
217   ret i64 %sel
220 define i64 @neg_max_sub_ugt_sel_swapped_extrause3(i64 %a, i64 %b) {
221 ; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause3(
222 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]]
223 ; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[B]], [[A]]
224 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i64 0, i64 [[SUB]]
225 ; CHECK-NEXT:    call void @use(i64 [[SUB]])
226 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
227 ; CHECK-NEXT:    ret i64 [[SEL]]
229   %cmp = icmp ugt i64 %b, %a
230   %sub = sub i64 %b, %a
231   %sel = select i1 %cmp, i64 0 ,i64 %sub
232   call void @use(i64 %sub)
233   call void @usei1(i1 %cmp)
234   ret i64 %sel
237 ; ((a < b) ? 0 : b - a) -> -usub.sat(a, b)
239 define i64 @neg_max_sub_ult_sel_swapped(i64 %a, i64 %b) {
240 ; CHECK-LABEL: @neg_max_sub_ult_sel_swapped(
241 ; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
242 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 0, [[TMP1]]
243 ; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
244 ; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
245 ; CHECK-NEXT:    ret i64 [[TMP2]]
247   %cmp = icmp ult i64 %a, %b
248   %sub = sub i64 %b, %a
249   %sel = select i1 %cmp, i64 0 ,i64 %sub
250   %extrasub = sub i64 %a, %b
251   call void @use(i64 %extrasub)
252   ret i64 %sel
255 define i32 @max_sub_ugt_c1(i32 %a) {
256 ; CHECK-LABEL: @max_sub_ugt_c1(
257 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1)
258 ; CHECK-NEXT:    ret i32 [[TMP1]]
260   %cmp = icmp ugt i32 %a, 1
261   %sub = add i32 %a, -1
262   %sel = select i1 %cmp, i32 %sub ,i32 0
263   ret i32 %sel
266 define i32 @max_sub_ugt_c01(i32 %a) {
267 ; CHECK-LABEL: @max_sub_ugt_c01(
268 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
269 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -1
270 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 0, i32 [[SUB]]
271 ; CHECK-NEXT:    ret i32 [[SEL]]
273   %cmp = icmp ugt i32 %a, 0
274   %sub = add i32 %a, -1
275   %sel = select i1 %cmp, i32 %sub ,i32 0
276   ret i32 %sel
279 define i32 @max_sub_ugt_c10(i32 %a) {
280 ; CHECK-LABEL: @max_sub_ugt_c10(
281 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10)
282 ; CHECK-NEXT:    ret i32 [[TMP1]]
284   %cmp = icmp ugt i32 %a, 10
285   %sub = add i32 %a, -10
286   %sel = select i1 %cmp, i32 %sub, i32 0
287   ret i32 %sel
290 define i32 @max_sub_ugt_c910(i32 %a) {
291 ; CHECK-LABEL: @max_sub_ugt_c910(
292 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 9
293 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -10
294 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
295 ; CHECK-NEXT:    ret i32 [[SEL]]
297   %cmp = icmp ugt i32 %a, 9
298   %sub = add i32 %a, -10
299   %sel = select i1 %cmp, i32 %sub, i32 0
300   ret i32 %sel
303 define i32 @max_sub_ugt_c1110(i32 %a) {
304 ; CHECK-LABEL: @max_sub_ugt_c1110(
305 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 11
306 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -10
307 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
308 ; CHECK-NEXT:    ret i32 [[SEL]]
310   %cmp = icmp ugt i32 %a, 11
311   %sub = add i32 %a, -10
312   %sel = select i1 %cmp, i32 %sub, i32 0
313   ret i32 %sel
316 define i32 @max_sub_ugt_c0(i32 %a) {
317 ; CHECK-LABEL: @max_sub_ugt_c0(
318 ; CHECK-NEXT:    ret i32 0
320   %cmp = icmp ugt i32 %a, -1
321   %sub = add i32 %a, 0
322   %sel = select i1 %cmp, i32 %sub, i32 0
323   ret i32 %sel
326 define i32 @max_sub_ugt_cmiss(i32 %a) {
327 ; CHECK-LABEL: @max_sub_ugt_cmiss(
328 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 1
329 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
330 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
331 ; CHECK-NEXT:    ret i32 [[SEL]]
333   %cmp = icmp ugt i32 %a, 1
334   %sub = add i32 %a, -2
335   %sel = select i1 %cmp, i32 %sub, i32 0
336   ret i32 %sel
339 define i32 @max_sub_ult_c1(i32 %a) {
340 ; CHECK-LABEL: @max_sub_ult_c1(
341 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
342 ; CHECK-NEXT:    [[SEL:%.*]] = sext i1 [[CMP]] to i32
343 ; CHECK-NEXT:    ret i32 [[SEL]]
345   %cmp = icmp ult i32 %a, 1
346   %sub = add i32 %a, -1
347   %sel = select i1 %cmp, i32 %sub, i32 0
348   ret i32 %sel
351 define i32 @max_sub_ult_c2(i32 %a) {
352 ; CHECK-LABEL: @max_sub_ult_c2(
353 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]])
354 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
355 ; CHECK-NEXT:    ret i32 [[TMP2]]
357   %cmp = icmp ult i32 %a, 2
358   %sub = add i32 %a, -2
359   %sel = select i1 %cmp, i32 %sub, i32 0
360   ret i32 %sel
363 define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) {
364 ; CHECK-LABEL: @max_sub_ult_c2_oneuseicmp(
365 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
366 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
367 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
368 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
369 ; CHECK-NEXT:    ret i32 [[TMP2]]
371   %cmp = icmp ult i32 %a, 2
372   %sub = add i32 %a, -2
373   %sel = select i1 %cmp, i32 %sub, i32 0
374   call void @usei1(i1 %cmp)
375   ret i32 %sel
378 define i32 @max_sub_ult_c2_oneusesub(i32 %a) {
379 ; CHECK-LABEL: @max_sub_ult_c2_oneusesub(
380 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A:%.*]], -2
381 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
382 ; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]]
383 ; CHECK-NEXT:    call void @usei32(i32 [[SUB]])
384 ; CHECK-NEXT:    ret i32 [[TMP2]]
386   %cmp = icmp ult i32 %a, 2
387   %sub = add i32 %a, -2
388   %sel = select i1 %cmp, i32 %sub, i32 0
389   call void @usei32(i32 %sub)
390   ret i32 %sel
393 define i32 @max_sub_ult_c32(i32 %a) {
394 ; CHECK-LABEL: @max_sub_ult_c32(
395 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
396 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
397 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
398 ; CHECK-NEXT:    ret i32 [[SEL]]
400   %cmp = icmp ult i32 %a, 3
401   %sub = add i32 %a, -2
402   %sel = select i1 %cmp, i32 %sub, i32 0
403   ret i32 %sel
406 define i32 @max_sub_ugt_c32(i32 %a) {
407 ; CHECK-LABEL: @max_sub_ugt_c32(
408 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
409 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
410 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
411 ; CHECK-NEXT:    ret i32 [[SEL]]
413   %cmp = icmp ugt i32 3, %a
414   %sub = add i32 %a, -2
415   %sel = select i1 %cmp, i32 %sub, i32 0
416   ret i32 %sel
419 define i32 @max_sub_uge_c32(i32 %a) {
420 ; CHECK-LABEL: @max_sub_uge_c32(
421 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
422 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
423 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
424 ; CHECK-NEXT:    ret i32 [[SEL]]
426   %cmp = icmp uge i32 2, %a
427   %sub = add i32 %a, -2
428   %sel = select i1 %cmp, i32 %sub, i32 0
429   ret i32 %sel
432 define i32 @max_sub_ult_c12(i32 %a) {
433 ; CHECK-LABEL: @max_sub_ult_c12(
434 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
435 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 -2, i32 0
436 ; CHECK-NEXT:    ret i32 [[SEL]]
438   %cmp = icmp ult i32 %a, 1
439   %sub = add i32 %a, -2
440   %sel = select i1 %cmp, i32 %sub, i32 0
441   ret i32 %sel
444 define i32 @max_sub_ult_c0(i32 %a) {
445 ; CHECK-LABEL: @max_sub_ult_c0(
446 ; CHECK-NEXT:    ret i32 0
448   %cmp = icmp ult i32 %a, 0
449   %sub = add i32 %a, -1
450   %sel = select i1 %cmp, i32 %sub, i32 0
451   ret i32 %sel