Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / unsigned_saturated_sub.ll
blobab147584d2108fb14786e76bf637e8628dce0d81
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=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 ; usub_sat((sub nuw C1, A), C2) to usub_sat(usub_sat(C1 - C2), A)
12 define 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]]
17   %add = sub nuw i32 64, %a
18   %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
19   ret i32 %cond
22 define i32 @usub_sat_C1_C2_produce_0(i32 %a){
23 ; CHECK-LABEL: @usub_sat_C1_C2_produce_0(
24 ; CHECK-NEXT:    ret i32 0
26   %add = sub nuw i32 14, %a
27   %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
28   ret i32 %cond
31 define 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
35   %add = sub nuw i32 12, %a
36   %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
37   ret i32 %cond
40 ; vector tests
41 define <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> <i16 50, i16 50>, <2 x i16> [[A:%.*]])
44 ; CHECK-NEXT:    ret <2 x i16> [[COND]]
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
51 define <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]]
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
61 define <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
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
70 define <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
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
79 define <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
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
88 ; negative tests this souldn't work
89 define 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]]
95   %add = sub i32 12, %a
96   %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14)
97   ret i32 %cond
100 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
102 define 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]]
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
113 ; (a >= b) ? a - b : 0 -> usub.sat(a, b)
115 define 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]]
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
126 define 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]]
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
140 define 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]]
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
154 define 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]]
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
171 ; Again, with vectors:
172 ; (a > b) ? a - b : 0 -> usub.sat(a, b)
174 define <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]]
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
185 ; Use extra ops to thwart icmp swapping canonicalization.
186 ; (b < a) ? a - b : 0 -> usub.sat(a, b)
188 define 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]]
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
203 ; (b > a) ? 0 : a - b -> usub.sat(a, b)
205 define 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]]
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
220 ; (a < b) ? 0 : a - b -> usub.sat(a, b)
222 define 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]]
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
233 ; ((a > b) ? b - a : 0) -> -usub.sat(a, b)
235 define 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]]
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
251 ; ((b < a) ? b - a : 0) -> -usub.sat(a, b)
253 define 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]]
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
265 ; ((b > a) ? 0 : b - a) -> -usub.sat(a, b)
267 define 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]]
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
279 define 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]]
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
294 define 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]]
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
309 define 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]]
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
326 ; ((a < b) ? 0 : b - a) -> -usub.sat(a, b)
328 define 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]]
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
344 define 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]]
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
355 define 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]]
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
366 define 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]]
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
377 define i32 @max_sub_ugt_c910(i32 %a) {
378 ; CHECK-LABEL: @max_sub_ugt_c910(
379 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 9
380 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -10
381 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
382 ; CHECK-NEXT:    ret i32 [[SEL]]
384   %cmp = icmp ugt i32 %a, 9
385   %sub = add i32 %a, -10
386   %sel = select i1 %cmp, i32 %sub, i32 0
387   ret i32 %sel
390 define i32 @max_sub_ugt_c1110(i32 %a) {
391 ; CHECK-LABEL: @max_sub_ugt_c1110(
392 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 11
393 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -10
394 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
395 ; CHECK-NEXT:    ret i32 [[SEL]]
397   %cmp = icmp ugt i32 %a, 11
398   %sub = add i32 %a, -10
399   %sel = select i1 %cmp, i32 %sub, i32 0
400   ret i32 %sel
403 define i32 @max_sub_ugt_c0(i32 %a) {
404 ; CHECK-LABEL: @max_sub_ugt_c0(
405 ; CHECK-NEXT:    ret i32 0
407   %cmp = icmp ugt i32 %a, -1
408   %sub = add i32 %a, 0
409   %sel = select i1 %cmp, i32 %sub, i32 0
410   ret i32 %sel
413 define i32 @max_sub_ugt_cmiss(i32 %a) {
414 ; CHECK-LABEL: @max_sub_ugt_cmiss(
415 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A:%.*]], 1
416 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
417 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
418 ; CHECK-NEXT:    ret i32 [[SEL]]
420   %cmp = icmp ugt i32 %a, 1
421   %sub = add i32 %a, -2
422   %sel = select i1 %cmp, i32 %sub, i32 0
423   ret i32 %sel
426 define i32 @max_sub_ult_c1(i32 %a) {
427 ; CHECK-LABEL: @max_sub_ult_c1(
428 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
429 ; CHECK-NEXT:    [[SEL:%.*]] = sext i1 [[CMP]] to i32
430 ; CHECK-NEXT:    ret i32 [[SEL]]
432   %cmp = icmp ult i32 %a, 1
433   %sub = add i32 %a, -1
434   %sel = select i1 %cmp, i32 %sub, i32 0
435   ret i32 %sel
438 define i32 @max_sub_ult_c2(i32 %a) {
439 ; CHECK-LABEL: @max_sub_ult_c2(
440 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A:%.*]])
441 ; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
442 ; CHECK-NEXT:    ret i32 [[SEL]]
444   %cmp = icmp ult i32 %a, 2
445   %sub = add i32 %a, -2
446   %sel = select i1 %cmp, i32 %sub, i32 0
447   ret i32 %sel
450 define i32 @max_sub_ult_c2_oneuseicmp(i32 %a) {
451 ; CHECK-LABEL: @max_sub_ult_c2_oneuseicmp(
452 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 2
453 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
454 ; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
455 ; CHECK-NEXT:    call void @usei1(i1 [[CMP]])
456 ; CHECK-NEXT:    ret i32 [[SEL]]
458   %cmp = icmp ult i32 %a, 2
459   %sub = add i32 %a, -2
460   %sel = select i1 %cmp, i32 %sub, i32 0
461   call void @usei1(i1 %cmp)
462   ret i32 %sel
465 define i32 @max_sub_ult_c2_oneusesub(i32 %a) {
466 ; CHECK-LABEL: @max_sub_ult_c2_oneusesub(
467 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A:%.*]], -2
468 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 2, i32 [[A]])
469 ; CHECK-NEXT:    [[SEL:%.*]] = sub nsw i32 0, [[TMP1]]
470 ; CHECK-NEXT:    call void @usei32(i32 [[SUB]])
471 ; CHECK-NEXT:    ret i32 [[SEL]]
473   %cmp = icmp ult i32 %a, 2
474   %sub = add i32 %a, -2
475   %sel = select i1 %cmp, i32 %sub, i32 0
476   call void @usei32(i32 %sub)
477   ret i32 %sel
480 define i32 @max_sub_ult_c32(i32 %a) {
481 ; CHECK-LABEL: @max_sub_ult_c32(
482 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
483 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
484 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
485 ; CHECK-NEXT:    ret i32 [[SEL]]
487   %cmp = icmp ult i32 %a, 3
488   %sub = add i32 %a, -2
489   %sel = select i1 %cmp, i32 %sub, i32 0
490   ret i32 %sel
493 define i32 @max_sub_ugt_c32(i32 %a) {
494 ; CHECK-LABEL: @max_sub_ugt_c32(
495 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
496 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
497 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
498 ; CHECK-NEXT:    ret i32 [[SEL]]
500   %cmp = icmp ugt i32 3, %a
501   %sub = add i32 %a, -2
502   %sel = select i1 %cmp, i32 %sub, i32 0
503   ret i32 %sel
506 define i32 @max_sub_uge_c32(i32 %a) {
507 ; CHECK-LABEL: @max_sub_uge_c32(
508 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 3
509 ; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[A]], -2
510 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0
511 ; CHECK-NEXT:    ret i32 [[SEL]]
513   %cmp = icmp uge i32 2, %a
514   %sub = add i32 %a, -2
515   %sel = select i1 %cmp, i32 %sub, i32 0
516   ret i32 %sel
519 define i32 @max_sub_ult_c12(i32 %a) {
520 ; CHECK-LABEL: @max_sub_ult_c12(
521 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0
522 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 -2, i32 0
523 ; CHECK-NEXT:    ret i32 [[SEL]]
525   %cmp = icmp ult i32 %a, 1
526   %sub = add i32 %a, -2
527   %sel = select i1 %cmp, i32 %sub, i32 0
528   ret i32 %sel
531 define i32 @max_sub_ult_c0(i32 %a) {
532 ; CHECK-LABEL: @max_sub_ult_c0(
533 ; CHECK-NEXT:    ret i32 0
535   %cmp = icmp ult i32 %a, 0
536   %sub = add i32 %a, -1
537   %sel = select i1 %cmp, i32 %sub, i32 0
538   ret i32 %sel