xref: /llvm-project/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll (revision 979a0356d4c90ec855be4f2d2f6687132cf10298)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4; Canonicalization of unsigned saturated subtraction idioms to
5; usub.sat() intrinsics is tested here.
6
7declare void @use(i64)
8declare void @usei32(i32)
9declare void @usei1(i1)
10
11; usub_sat((sub nuw C1, A), C2) to usub_sat(usub_sat(C1 - C2), A)
12define i32 @usub_sat_C1_C2(i32 %a){
13; CHECK-LABEL: @usub_sat_C1_C2(
14; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 50, i32 [[A:%.*]])
15; CHECK-NEXT:    ret i32 [[COND]]
16;
17  %add = sub nuw i32 64, %a
18  %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
19  ret i32 %cond
20}
21
22define i32 @usub_sat_C1_C2_produce_0(i32 %a){
23; CHECK-LABEL: @usub_sat_C1_C2_produce_0(
24; CHECK-NEXT:    ret i32 0
25;
26  %add = sub nuw i32 14, %a
27  %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
28  ret i32 %cond
29}
30
31define i32 @usub_sat_C1_C2_produce_0_too(i32 %a){
32; CHECK-LABEL: @usub_sat_C1_C2_produce_0_too(
33; CHECK-NEXT:    ret i32 0
34;
35  %add = sub nuw i32 12, %a
36  %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
37  ret i32 %cond
38}
39
40; vector tests
41define <2 x i16> @usub_sat_C1_C2_splat(<2 x i16> %a) {
42; CHECK-LABEL: @usub_sat_C1_C2_splat(
43; CHECK-NEXT:    [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> splat (i16 50), <2 x i16> [[A:%.*]])
44; CHECK-NEXT:    ret <2 x i16> [[COND]]
45;
46  %add = sub nuw <2 x i16> <i16 64, i16 64>, %a
47  %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 14>)
48  ret <2 x i16> %cond
49}
50
51define <2 x i16> @usub_sat_C1_C2_non_splat(<2 x i16> %a) {
52; CHECK-LABEL: @usub_sat_C1_C2_non_splat(
53; CHECK-NEXT:    [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> <i16 30, i16 50>, <2 x i16> [[A:%.*]])
54; CHECK-NEXT:    ret <2 x i16> [[COND]]
55;
56  %add = sub nuw <2 x i16> <i16 50, i16 64>, %a
57  %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 20, i16 14>)
58  ret <2 x i16> %cond
59}
60
61define <2 x i16> @usub_sat_C1_C2_splat_produce_0(<2 x i16> %a){
62; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0(
63; CHECK-NEXT:    ret <2 x i16> zeroinitializer
64;
65  %add = sub nuw <2 x i16> <i16 14, i16 14>, %a
66  %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 14>)
67  ret <2 x i16> %cond
68}
69
70define <2 x i16> @usub_sat_C1_C2_splat_produce_0_too(<2 x i16> %a){
71; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0_too(
72; CHECK-NEXT:    ret <2 x i16> zeroinitializer
73;
74  %add = sub nuw <2 x i16> <i16 12, i16 12>, %a
75  %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 14>)
76  ret <2 x i16> %cond
77}
78
79define <2 x i16> @usub_sat_C1_C2_non_splat_produce_0_too(<2 x i16> %a){
80; CHECK-LABEL: @usub_sat_C1_C2_non_splat_produce_0_too(
81; CHECK-NEXT:    ret <2 x i16> zeroinitializer
82;
83  %add = sub nuw <2 x i16> <i16 12, i16 13>, %a
84  %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> <i16 14, i16 15>)
85  ret <2 x i16> %cond
86}
87
88; negative tests this souldn't work
89define i32 @usub_sat_C1_C2_without_nuw(i32 %a){
90; CHECK-LABEL: @usub_sat_C1_C2_without_nuw(
91; CHECK-NEXT:    [[ADD:%.*]] = sub i32 12, [[A:%.*]]
92; CHECK-NEXT:    [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[ADD]], i32 14)
93; CHECK-NEXT:    ret i32 [[COND]]
94;
95  %add = sub i32 12, %a
96  %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
97  ret i32 %cond
98}
99
100; (a > b) ? a - b : 0 -> usub.sat(a, b)
101
102define i64 @max_sub_ugt(i64 %a, i64 %b) {
103; CHECK-LABEL: @max_sub_ugt(
104; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
105; CHECK-NEXT:    ret i64 [[SEL]]
106;
107  %cmp = icmp ugt i64 %a, %b
108  %sub = sub i64 %a, %b
109  %sel = select i1 %cmp, i64 %sub ,i64 0
110  ret i64 %sel
111}
112
113; (a >= b) ? a - b : 0 -> usub.sat(a, b)
114
115define i64 @max_sub_uge(i64 %a, i64 %b) {
116; CHECK-LABEL: @max_sub_uge(
117; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
118; CHECK-NEXT:    ret i64 [[SEL]]
119;
120  %cmp = icmp uge i64 %a, %b
121  %sub = sub i64 %a, %b
122  %sel = select i1 %cmp, i64 %sub ,i64 0
123  ret i64 %sel
124}
125
126define i64 @max_sub_uge_extrause1(i64 %a, i64 %b) {
127; CHECK-LABEL: @max_sub_uge_extrause1(
128; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]
129; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
130; CHECK-NEXT:    call void @use(i64 [[SUB]])
131; CHECK-NEXT:    ret i64 [[SEL]]
132;
133  %cmp = icmp uge i64 %a, %b
134  %sub = sub i64 %a, %b
135  %sel = select i1 %cmp, i64 %sub ,i64 0
136  call void @use(i64 %sub)
137  ret i64 %sel
138}
139
140define i64 @max_sub_uge_extrause2(i64 %a, i64 %b) {
141; CHECK-LABEL: @max_sub_uge_extrause2(
142; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]]
143; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
144; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
145; CHECK-NEXT:    ret i64 [[SEL]]
146;
147  %cmp = icmp uge i64 %a, %b
148  %sub = sub i64 %a, %b
149  %sel = select i1 %cmp, i64 %sub ,i64 0
150  call void @usei1(i1 %cmp)
151  ret i64 %sel
152}
153
154define i64 @max_sub_uge_extrause3(i64 %a, i64 %b) {
155; CHECK-LABEL: @max_sub_uge_extrause3(
156; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i64 [[A:%.*]], [[B:%.*]]
157; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[A]], [[B]]
158; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
159; CHECK-NEXT:    call void @use(i64 [[SUB]])
160; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
161; CHECK-NEXT:    ret i64 [[SEL]]
162;
163  %cmp = icmp uge i64 %a, %b
164  %sub = sub i64 %a, %b
165  %sel = select i1 %cmp, i64 %sub ,i64 0
166  call void @use(i64 %sub)
167  call void @usei1(i1 %cmp)
168  ret i64 %sel
169}
170
171; Again, with vectors:
172; (a > b) ? a - b : 0 -> usub.sat(a, b)
173
174define <4 x i32> @max_sub_ugt_vec(<4 x i32> %a, <4 x i32> %b) {
175; CHECK-LABEL: @max_sub_ugt_vec(
176; CHECK-NEXT:    [[SEL:%.*]] = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]])
177; CHECK-NEXT:    ret <4 x i32> [[SEL]]
178;
179  %cmp = icmp ugt <4 x i32> %a, %b
180  %sub = sub <4 x i32> %a, %b
181  %sel = select <4 x i1> %cmp, <4 x i32> %sub, <4 x i32> zeroinitializer
182  ret <4 x i32> %sel
183}
184
185; Use extra ops to thwart icmp swapping canonicalization.
186; (b < a) ? a - b : 0 -> usub.sat(a, b)
187
188define i64 @max_sub_ult(i64 %a, i64 %b) {
189; CHECK-LABEL: @max_sub_ult(
190; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
191; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
192; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
193; CHECK-NEXT:    ret i64 [[SEL]]
194;
195  %cmp = icmp ult i64 %b, %a
196  %sub = sub i64 %a, %b
197  %sel = select i1 %cmp, i64 %sub ,i64 0
198  %extrasub = sub i64 %b, %a
199  call void @use(i64 %extrasub)
200  ret i64 %sel
201}
202
203; (b > a) ? 0 : a - b -> usub.sat(a, b)
204
205define i64 @max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
206; CHECK-LABEL: @max_sub_ugt_sel_swapped(
207; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
208; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[B]], [[A]]
209; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
210; CHECK-NEXT:    ret i64 [[SEL]]
211;
212  %cmp = icmp ugt i64 %b, %a
213  %sub = sub i64 %a, %b
214  %sel = select i1 %cmp, i64 0 ,i64 %sub
215  %extrasub = sub i64 %b, %a
216  call void @use(i64 %extrasub)
217  ret i64 %sel
218}
219
220; (a < b) ? 0 : a - b -> usub.sat(a, b)
221
222define i64 @max_sub_ult_sel_swapped(i64 %a, i64 %b) {
223; CHECK-LABEL: @max_sub_ult_sel_swapped(
224; CHECK-NEXT:    [[SEL:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
225; CHECK-NEXT:    ret i64 [[SEL]]
226;
227  %cmp = icmp ult i64 %a, %b
228  %sub = sub i64 %a, %b
229  %sel = select i1 %cmp, i64 0 ,i64 %sub
230  ret i64 %sel
231}
232
233; ((a > b) ? b - a : 0) -> -usub.sat(a, b)
234
235define i64 @neg_max_sub_ugt(i64 %a, i64 %b) {
236; CHECK-LABEL: @neg_max_sub_ugt(
237; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
238; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
239; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
240; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
241; CHECK-NEXT:    ret i64 [[SEL]]
242;
243  %cmp = icmp ugt i64 %a, %b
244  %sub = sub i64 %b, %a
245  %sel = select i1 %cmp, i64 %sub ,i64 0
246  %extrasub = sub i64 %a, %b
247  call void @use(i64 %extrasub)
248  ret i64 %sel
249}
250
251; ((b < a) ? b - a : 0) -> -usub.sat(a, b)
252
253define i64 @neg_max_sub_ult(i64 %a, i64 %b) {
254; CHECK-LABEL: @neg_max_sub_ult(
255; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
256; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
257; CHECK-NEXT:    ret i64 [[SEL]]
258;
259  %cmp = icmp ult i64 %b, %a
260  %sub = sub i64 %b, %a
261  %sel = select i1 %cmp, i64 %sub ,i64 0
262  ret i64 %sel
263}
264
265; ((b > a) ? 0 : b - a) -> -usub.sat(a, b)
266
267define i64 @neg_max_sub_ugt_sel_swapped(i64 %a, i64 %b) {
268; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped(
269; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
270; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
271; CHECK-NEXT:    ret i64 [[SEL]]
272;
273  %cmp = icmp ugt i64 %b, %a
274  %sub = sub i64 %b, %a
275  %sel = select i1 %cmp, i64 0 ,i64 %sub
276  ret i64 %sel
277}
278
279define i64 @neg_max_sub_ugt_sel_swapped_extrause1(i64 %a, i64 %b) {
280; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause1(
281; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]]
282; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
283; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
284; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
285; CHECK-NEXT:    ret i64 [[SEL]]
286;
287  %cmp = icmp ugt i64 %b, %a
288  %sub = sub i64 %b, %a
289  %sel = select i1 %cmp, i64 0 ,i64 %sub
290  call void @usei1(i1 %cmp)
291  ret i64 %sel
292}
293
294define i64 @neg_max_sub_ugt_sel_swapped_extrause2(i64 %a, i64 %b) {
295; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause2(
296; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]
297; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]])
298; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
299; CHECK-NEXT:    call void @use(i64 [[SUB]])
300; CHECK-NEXT:    ret i64 [[SEL]]
301;
302  %cmp = icmp ugt i64 %b, %a
303  %sub = sub i64 %b, %a
304  %sel = select i1 %cmp, i64 0 ,i64 %sub
305  call void @use(i64 %sub)
306  ret i64 %sel
307}
308
309define i64 @neg_max_sub_ugt_sel_swapped_extrause3(i64 %a, i64 %b) {
310; CHECK-LABEL: @neg_max_sub_ugt_sel_swapped_extrause3(
311; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i64 [[B:%.*]], [[A:%.*]]
312; CHECK-NEXT:    [[SUB:%.*]] = sub i64 [[B]], [[A]]
313; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i64 0, i64 [[SUB]]
314; CHECK-NEXT:    call void @use(i64 [[SUB]])
315; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
316; CHECK-NEXT:    ret i64 [[SEL]]
317;
318  %cmp = icmp ugt i64 %b, %a
319  %sub = sub i64 %b, %a
320  %sel = select i1 %cmp, i64 0 ,i64 %sub
321  call void @use(i64 %sub)
322  call void @usei1(i1 %cmp)
323  ret i64 %sel
324}
325
326; ((a < b) ? 0 : b - a) -> -usub.sat(a, b)
327
328define i64 @neg_max_sub_ult_sel_swapped(i64 %a, i64 %b) {
329; CHECK-LABEL: @neg_max_sub_ult_sel_swapped(
330; CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
331; CHECK-NEXT:    [[SEL:%.*]] = sub i64 0, [[TMP1]]
332; CHECK-NEXT:    [[EXTRASUB:%.*]] = sub i64 [[A]], [[B]]
333; CHECK-NEXT:    call void @use(i64 [[EXTRASUB]])
334; CHECK-NEXT:    ret i64 [[SEL]]
335;
336  %cmp = icmp ult i64 %a, %b
337  %sub = sub i64 %b, %a
338  %sel = select i1 %cmp, i64 0 ,i64 %sub
339  %extrasub = sub i64 %a, %b
340  call void @use(i64 %extrasub)
341  ret i64 %sel
342}
343
344define i32 @max_sub_ugt_c1(i32 %a) {
345; CHECK-LABEL: @max_sub_ugt_c1(
346; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1)
347; CHECK-NEXT:    ret i32 [[SEL]]
348;
349  %cmp = icmp ugt i32 %a, 1
350  %sub = add i32 %a, -1
351  %sel = select i1 %cmp, i32 %sub ,i32 0
352  ret i32 %sel
353}
354
355define i32 @max_sub_ugt_c01(i32 %a) {
356; CHECK-LABEL: @max_sub_ugt_c01(
357; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 1)
358; CHECK-NEXT:    ret i32 [[SEL]]
359;
360  %cmp = icmp ugt i32 %a, 0
361  %sub = add i32 %a, -1
362  %sel = select i1 %cmp, i32 %sub ,i32 0
363  ret i32 %sel
364}
365
366define i32 @max_sub_ugt_c10(i32 %a) {
367; CHECK-LABEL: @max_sub_ugt_c10(
368; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10)
369; CHECK-NEXT:    ret i32 [[SEL]]
370;
371  %cmp = icmp ugt i32 %a, 10
372  %sub = add i32 %a, -10
373  %sel = select i1 %cmp, i32 %sub, i32 0
374  ret i32 %sel
375}
376
377define i32 @max_sub_ugt_c910(i32 %a) {
378; CHECK-LABEL: @max_sub_ugt_c910(
379; CHECK-NEXT:    [[SUB:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 10)
380; CHECK-NEXT:    ret i32 [[SUB]]
381;
382  %cmp = icmp ugt i32 %a, 9
383  %sub = add i32 %a, -10
384  %sel = select i1 %cmp, i32 %sub, i32 0
385  ret i32 %sel
386}
387
388define i32 @max_sub_ugt_c1110(i32 %a) {
389; CHECK-LABEL: @max_sub_ugt_c1110(
390; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 11
391; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -10
392; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
393; CHECK-NEXT:    ret i32 [[SEL]]
394;
395  %cmp = icmp ugt i32 %a, 11
396  %sub = add i32 %a, -10
397  %sel = select i1 %cmp, i32 %sub, i32 0
398  ret i32 %sel
399}
400
401define i32 @max_sub_ugt_c0(i32 %a) {
402; CHECK-LABEL: @max_sub_ugt_c0(
403; CHECK-NEXT:    ret i32 0
404;
405  %cmp = icmp ugt i32 %a, -1
406  %sub = add i32 %a, 0
407  %sel = select i1 %cmp, i32 %sub, i32 0
408  ret i32 %sel
409}
410
411define i32 @max_sub_ugt_cmiss(i32 %a) {
412; CHECK-LABEL: @max_sub_ugt_cmiss(
413; CHECK-NEXT:    [[SUB:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 2)
414; CHECK-NEXT:    ret i32 [[SUB]]
415;
416  %cmp = icmp ugt i32 %a, 1
417  %sub = add i32 %a, -2
418  %sel = select i1 %cmp, i32 %sub, i32 0
419  ret i32 %sel
420}
421
422define i32 @max_sub_ult_c1(i32 %a) {
423; CHECK-LABEL: @max_sub_ult_c1(
424; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
425; CHECK-NEXT:    [[SEL:%.*]] = sext i1 [[CMP]] to i32
426; CHECK-NEXT:    ret i32 [[SEL]]
427;
428  %cmp = icmp ult i32 %a, 1
429  %sub = add i32 %a, -1
430  %sel = select i1 %cmp, i32 %sub, i32 0
431  ret i32 %sel
432}
433
434define i32 @max_sub_ult_c2(i32 %a) {
435; CHECK-LABEL: @max_sub_ult_c2(
436; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]])
437; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
438; CHECK-NEXT:    ret i32 [[SEL]]
439;
440  %cmp = icmp ult i32 %a, 2
441  %sub = add i32 %a, -2
442  %sel = select i1 %cmp, i32 %sub, i32 0
443  ret i32 %sel
444}
445
446define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) {
447; CHECK-LABEL: @max_sub_ult_c2_oneuseicmp(
448; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
449; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
450; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
451; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
452; CHECK-NEXT:    ret i32 [[SEL]]
453;
454  %cmp = icmp ult i32 %a, 2
455  %sub = add i32 %a, -2
456  %sel = select i1 %cmp, i32 %sub, i32 0
457  call void @usei1(i1 %cmp)
458  ret i32 %sel
459}
460
461define i32 @max_sub_ult_c2_oneusesub(i32 %a) {
462; CHECK-LABEL: @max_sub_ult_c2_oneusesub(
463; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A:%.*]], -2
464; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
465; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
466; CHECK-NEXT:    call void @usei32(i32 [[SUB]])
467; CHECK-NEXT:    ret i32 [[SEL]]
468;
469  %cmp = icmp ult i32 %a, 2
470  %sub = add i32 %a, -2
471  %sel = select i1 %cmp, i32 %sub, i32 0
472  call void @usei32(i32 %sub)
473  ret i32 %sel
474}
475
476define i32 @max_sub_ult_c32(i32 %a) {
477; CHECK-LABEL: @max_sub_ult_c32(
478; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2)
479; CHECK-NEXT:    [[SEL:%.*]] = add nsw i32 [[TMP1]], -2
480; CHECK-NEXT:    ret i32 [[SEL]]
481;
482  %cmp = icmp ult i32 %a, 3
483  %sub = add i32 %a, -2
484  %sel = select i1 %cmp, i32 %sub, i32 0
485  ret i32 %sel
486}
487
488define i32 @max_sub_ugt_c32(i32 %a) {
489; CHECK-LABEL: @max_sub_ugt_c32(
490; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2)
491; CHECK-NEXT:    [[SEL:%.*]] = add nsw i32 [[TMP1]], -2
492; CHECK-NEXT:    ret i32 [[SEL]]
493;
494  %cmp = icmp ugt i32 3, %a
495  %sub = add i32 %a, -2
496  %sel = select i1 %cmp, i32 %sub, i32 0
497  ret i32 %sel
498}
499
500define i32 @max_sub_uge_c32(i32 %a) {
501; CHECK-LABEL: @max_sub_uge_c32(
502; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 2)
503; CHECK-NEXT:    [[SEL:%.*]] = add nsw i32 [[TMP1]], -2
504; CHECK-NEXT:    ret i32 [[SEL]]
505;
506  %cmp = icmp uge i32 2, %a
507  %sub = add i32 %a, -2
508  %sel = select i1 %cmp, i32 %sub, i32 0
509  ret i32 %sel
510}
511
512define i32 @max_sub_ult_c12(i32 %a) {
513; CHECK-LABEL: @max_sub_ult_c12(
514; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
515; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 -2, i32 0
516; CHECK-NEXT:    ret i32 [[SEL]]
517;
518  %cmp = icmp ult i32 %a, 1
519  %sub = add i32 %a, -2
520  %sel = select i1 %cmp, i32 %sub, i32 0
521  ret i32 %sel
522}
523
524define i32 @max_sub_ult_c0(i32 %a) {
525; CHECK-LABEL: @max_sub_ult_c0(
526; CHECK-NEXT:    ret i32 0
527;
528  %cmp = icmp ult i32 %a, 0
529  %sub = add i32 %a, -1
530  %sel = select i1 %cmp, i32 %sub, i32 0
531  ret i32 %sel
532}
533
534