xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/minmax.ll (revision 87b1e735b28f81d9012fd302cd07385db50a274f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4; Test from PR63896
5define i1 @umax_ugt(i32 %x, i32 %y) {
6; CHECK-LABEL: define i1 @umax_ugt
7; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
8; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1)
9; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[Y]], [[MAX]]
10; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
11; CHECK:       if:
12; CHECK-NEXT:    [[RET:%.*]] = xor i1 true, true
13; CHECK-NEXT:    ret i1 [[RET]]
14; CHECK:       end:
15; CHECK-NEXT:    ret i1 false
16;
17  %max = call i32 @llvm.umax.i32(i32 %x, i32 1)
18  %cmp = icmp ugt i32 %y, %max
19  br i1 %cmp, label %if, label %end
20
21if:
22  %cmp2 = icmp ugt i32 %y, %x
23  %cmp3 = icmp uge i32 %y, %x
24  %ret = xor i1 %cmp2, %cmp3
25  ret i1 %ret
26
27end:
28  ret i1 false
29}
30
31define i1 @umax_uge(i32 %x, i32 %y) {
32; CHECK-LABEL: define i1 @umax_uge
33; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
34; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1)
35; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[Y]], [[MAX]]
36; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
37; CHECK:       if:
38; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i32 [[Y]], [[X]]
39; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[CMP2]], true
40; CHECK-NEXT:    ret i1 [[RET]]
41; CHECK:       end:
42; CHECK-NEXT:    ret i1 false
43;
44  %max = call i32 @llvm.umax.i32(i32 %x, i32 1)
45  %cmp = icmp uge i32 %y, %max
46  br i1 %cmp, label %if, label %end
47
48if:
49  %cmp2 = icmp ugt i32 %y, %x
50  %cmp3 = icmp uge i32 %y, %x
51  %ret = xor i1 %cmp2, %cmp3
52  ret i1 %ret
53
54end:
55  ret i1 false
56}
57
58define i1 @umin_ult(i32 %x, i32 %y) {
59; CHECK-LABEL: define i1 @umin_ult
60; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
61; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 1)
62; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[Y]], [[MIN]]
63; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
64; CHECK:       if:
65; CHECK-NEXT:    [[RET:%.*]] = xor i1 true, true
66; CHECK-NEXT:    ret i1 [[RET]]
67; CHECK:       end:
68; CHECK-NEXT:    ret i1 false
69;
70  %min = call i32 @llvm.umin.i32(i32 %x, i32 1)
71  %cmp = icmp ult i32 %y, %min
72  br i1 %cmp, label %if, label %end
73
74if:
75  %cmp2 = icmp ult i32 %y, %x
76  %cmp3 = icmp ule i32 %y, %x
77  %ret = xor i1 %cmp2, %cmp3
78  ret i1 %ret
79
80end:
81  ret i1 false
82}
83
84define i1 @umin_ule(i32 %x, i32 %y) {
85; CHECK-LABEL: define i1 @umin_ule
86; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
87; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 1)
88; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[Y]], [[MIN]]
89; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
90; CHECK:       if:
91; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[Y]], [[X]]
92; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[CMP2]], true
93; CHECK-NEXT:    ret i1 [[RET]]
94; CHECK:       end:
95; CHECK-NEXT:    ret i1 false
96;
97  %min = call i32 @llvm.umin.i32(i32 %x, i32 1)
98  %cmp = icmp ule i32 %y, %min
99  br i1 %cmp, label %if, label %end
100
101if:
102  %cmp2 = icmp ult i32 %y, %x
103  %cmp3 = icmp ule i32 %y, %x
104  %ret = xor i1 %cmp2, %cmp3
105  ret i1 %ret
106
107end:
108  ret i1 false
109}
110
111define i1 @smax_sgt(i32 %x, i32 %y) {
112; CHECK-LABEL: define i1 @smax_sgt
113; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
114; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1)
115; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[Y]], [[MAX]]
116; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
117; CHECK:       if:
118; CHECK-NEXT:    [[RET:%.*]] = xor i1 true, true
119; CHECK-NEXT:    ret i1 [[RET]]
120; CHECK:       end:
121; CHECK-NEXT:    ret i1 false
122;
123  %max = call i32 @llvm.smax.i32(i32 %x, i32 1)
124  %cmp = icmp sgt i32 %y, %max
125  br i1 %cmp, label %if, label %end
126
127if:
128  %cmp2 = icmp sgt i32 %y, %x
129  %cmp3 = icmp sge i32 %y, %x
130  %ret = xor i1 %cmp2, %cmp3
131  ret i1 %ret
132
133end:
134  ret i1 false
135}
136
137define i1 @smax_sge(i32 %x, i32 %y) {
138; CHECK-LABEL: define i1 @smax_sge
139; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
140; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 1)
141; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[Y]], [[MAX]]
142; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
143; CHECK:       if:
144; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[Y]], [[X]]
145; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[CMP2]], true
146; CHECK-NEXT:    ret i1 [[RET]]
147; CHECK:       end:
148; CHECK-NEXT:    ret i1 false
149;
150  %max = call i32 @llvm.smax.i32(i32 %x, i32 1)
151  %cmp = icmp sge i32 %y, %max
152  br i1 %cmp, label %if, label %end
153
154if:
155  %cmp2 = icmp sgt i32 %y, %x
156  %cmp3 = icmp sge i32 %y, %x
157  %ret = xor i1 %cmp2, %cmp3
158  ret i1 %ret
159
160end:
161  ret i1 false
162}
163
164define i1 @smin_slt(i32 %x, i32 %y) {
165; CHECK-LABEL: define i1 @smin_slt
166; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
167; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1)
168; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[Y]], [[MIN]]
169; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
170; CHECK:       if:
171; CHECK-NEXT:    [[RET:%.*]] = xor i1 true, true
172; CHECK-NEXT:    ret i1 [[RET]]
173; CHECK:       end:
174; CHECK-NEXT:    ret i1 false
175;
176  %min = call i32 @llvm.smin.i32(i32 %x, i32 1)
177  %cmp = icmp slt i32 %y, %min
178  br i1 %cmp, label %if, label %end
179
180if:
181  %cmp2 = icmp slt i32 %y, %x
182  %cmp3 = icmp sle i32 %y, %x
183  %ret = xor i1 %cmp2, %cmp3
184  ret i1 %ret
185
186end:
187  ret i1 false
188}
189
190define i1 @smin_sle(i32 %x, i32 %y) {
191; CHECK-LABEL: define i1 @smin_sle
192; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
193; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1)
194; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[Y]], [[MIN]]
195; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
196; CHECK:       if:
197; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]]
198; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[CMP2]], true
199; CHECK-NEXT:    ret i1 [[RET]]
200; CHECK:       end:
201; CHECK-NEXT:    ret i1 false
202;
203  %min = call i32 @llvm.smin.i32(i32 %x, i32 1)
204  %cmp = icmp sle i32 %y, %min
205  br i1 %cmp, label %if, label %end
206
207if:
208  %cmp2 = icmp slt i32 %y, %x
209  %cmp3 = icmp sle i32 %y, %x
210  %ret = xor i1 %cmp2, %cmp3
211  ret i1 %ret
212
213end:
214  ret i1 false
215}
216
217define i1 @umax_uge_ugt_with_add_nuw(i32 %x, i32 %y) {
218; CHECK-LABEL: define i1 @umax_uge_ugt_with_add_nuw
219; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
220; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 1)
221; CHECK-NEXT:    [[SUM:%.*]] = add nuw i32 [[MAX]], 1
222; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[Y]], [[SUM]]
223; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
224; CHECK:       if:
225; CHECK-NEXT:    ret i1 true
226; CHECK:       end:
227; CHECK-NEXT:    ret i1 false
228;
229  %max = call i32 @llvm.umax.i32(i32 %x, i32 1)
230  %sum = add nuw i32 %max, 1
231  %cmp = icmp uge i32 %y, %sum
232  br i1 %cmp, label %if, label %end
233
234if:
235  %cmp2 = icmp ugt i32 %y, %x
236  ret i1 %cmp2
237
238end:
239  ret i1 false
240}
241
242define i1 @smin_ule_mixed(i32 %x, i32 %y) {
243; CHECK-LABEL: define i1 @smin_ule_mixed
244; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
245; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 1)
246; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[Y]], [[MIN]]
247; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
248; CHECK:       if:
249; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[Y]], [[X]]
250; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[Y]], [[X]]
251; CHECK-NEXT:    [[CMP4:%.*]] = icmp ult i32 [[Y]], [[X]]
252; CHECK-NEXT:    [[CMP5:%.*]] = icmp ule i32 [[Y]], [[X]]
253; CHECK-NEXT:    [[XOR1:%.*]] = xor i1 [[CMP2]], [[CMP3]]
254; CHECK-NEXT:    [[XOR2:%.*]] = xor i1 [[CMP4]], [[CMP5]]
255; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[XOR1]], [[XOR2]]
256; CHECK-NEXT:    ret i1 [[RET]]
257; CHECK:       end:
258; CHECK-NEXT:    ret i1 false
259;
260  %min = call i32 @llvm.smin.i32(i32 %x, i32 1)
261  %cmp = icmp ule i32 %y, %min
262  br i1 %cmp, label %if, label %end
263
264if:
265  %cmp2 = icmp slt i32 %y, %x
266  %cmp3 = icmp sle i32 %y, %x
267  %cmp4 = icmp ult i32 %y, %x
268  %cmp5 = icmp ule i32 %y, %x
269  %xor1 = xor i1 %cmp2, %cmp3
270  %xor2 = xor i1 %cmp4, %cmp5
271  %ret = xor i1 %xor1, %xor2
272  ret i1 %ret
273
274end:
275  ret i1 false
276}
277
278define i1 @umax_ugt_ugt_both(i32 %x, i32 %y, i32 %z) {
279; CHECK-LABEL: define i1 @umax_ugt_ugt_both
280; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
281; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
282; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[Z]], [[MAX]]
283; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
284; CHECK:       if:
285; CHECK-NEXT:    [[AND:%.*]] = xor i1 true, true
286; CHECK-NEXT:    ret i1 [[AND]]
287; CHECK:       end:
288; CHECK-NEXT:    ret i1 false
289;
290  %max = call i32 @llvm.umax.i32(i32 %x, i32 %y)
291  %cmp = icmp ugt i32 %z, %max
292  br i1 %cmp, label %if, label %end
293
294if:
295  %cmp2 = icmp ugt i32 %z, %x
296  %cmp3 = icmp ugt i32 %z, %y
297  %and = xor i1 %cmp2, %cmp3
298  ret i1 %and
299
300end:
301  ret i1 false
302}
303
304define i1 @smin_branchless(i32 %x, i32 %y) {
305; CHECK-LABEL: define i1 @smin_branchless
306; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
307; CHECK-NEXT:  entry:
308; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[X]], i32 [[Y]])
309; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i32 [[MIN]], [[X]]
310; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[MIN]], [[X]]
311; CHECK-NEXT:    [[RET:%.*]] = xor i1 [[CMP1]], [[CMP2]]
312; CHECK-NEXT:    ret i1 [[RET]]
313;
314entry:
315  %min = call i32 @llvm.smin.i32(i32 %x, i32 %y)
316  %cmp1 = icmp sle i32 %min, %x
317  %cmp2 = icmp sgt i32 %min, %x
318  %ret = xor i1 %cmp1, %cmp2
319  ret i1 %ret
320}
321
322define i32 @simplify_smax(i32 %x, i32 %y, i32 %z) {
323; CHECK-LABEL: define i32 @simplify_smax
324; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
325; CHECK-NEXT:  entry:
326; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], [[Y]]
327; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
328; CHECK:       if:
329; CHECK-NEXT:    [[MAX1:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Z]])
330; CHECK-NEXT:    [[MAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[Y]], i32 [[MAX1]])
331; CHECK-NEXT:    ret i32 [[MAX2]]
332; CHECK:       end:
333; CHECK-NEXT:    ret i32 0
334;
335entry:
336  %cmp = icmp slt i32 %x, %y
337  br i1 %cmp, label %if, label %end
338if:
339  %max1 = call i32 @llvm.smax.i32(i32 %x, i32 %z)
340  %max2 = call i32 @llvm.smax.i32(i32 %y, i32 %max1)
341  ret i32 %max2
342end:
343  ret i32 0
344}
345
346; Test from PR75155
347define i32 @simplify_slt_smax_val(i32 %a, i32 %b) {
348; CHECK-LABEL: define i32 @simplify_slt_smax_val
349; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
350; CHECK-NEXT:  start:
351; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
352; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
353; CHECK:       then:
354; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
355; CHECK-NEXT:    ret i32 [[B]]
356; CHECK:       else:
357; CHECK-NEXT:    ret i32 -1
358;
359start:
360  %cmp = icmp slt i32 %a, %b
361  br i1 %cmp, label %then, label %else
362then:
363  %add = add nsw i32 %a, 1
364  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
365  ret i32 %max
366else:
367  ret i32 -1
368}
369
370define i32 @simplify_slt_smax_val_commuted(i32 %a, i32 %b) {
371; CHECK-LABEL: define i32 @simplify_slt_smax_val_commuted
372; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
373; CHECK-NEXT:  start:
374; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
375; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
376; CHECK:       then:
377; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
378; CHECK-NEXT:    ret i32 [[B]]
379; CHECK:       else:
380; CHECK-NEXT:    ret i32 -1
381;
382start:
383  %cmp = icmp slt i32 %a, %b
384  br i1 %cmp, label %then, label %else
385then:
386  %add = add nsw i32 %a, 1
387  %max = call i32 @llvm.smax.i32(i32 %add, i32 %b)
388  ret i32 %max
389else:
390  ret i32 -1
391}
392
393define i32 @simplify_slt_smax_val_at_use(i32 %a, i32 %b) {
394; CHECK-LABEL: define i32 @simplify_slt_smax_val_at_use
395; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
396; CHECK-NEXT:  start:
397; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
398; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
399; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]])
400; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
401; CHECK:       then:
402; CHECK-NEXT:    ret i32 [[MAX]]
403; CHECK:       else:
404; CHECK-NEXT:    ret i32 -1
405;
406start:
407  %cmp = icmp slt i32 %a, %b
408  %add = add nsw i32 %a, 1
409  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
410  br i1 %cmp, label %then, label %else
411then:
412  ret i32 %max
413else:
414  ret i32 -1
415}
416
417define i32 @simplify_sgt_smax_val(i32 %a, i32 %b) {
418; CHECK-LABEL: define i32 @simplify_sgt_smax_val
419; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
420; CHECK-NEXT:  start:
421; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
422; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
423; CHECK:       then:
424; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
425; CHECK-NEXT:    ret i32 [[ADD]]
426; CHECK:       else:
427; CHECK-NEXT:    ret i32 -1
428;
429start:
430  %cmp = icmp sgt i32 %a, %b
431  br i1 %cmp, label %then, label %else
432then:
433  %add = add nsw i32 %a, 1
434  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
435  ret i32 %max
436else:
437  ret i32 -1
438}
439
440define i32 @simplify_sle_smax_val(i32 %a, i32 %b) {
441; CHECK-LABEL: define i32 @simplify_sle_smax_val
442; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
443; CHECK-NEXT:  start:
444; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[A]], [[B]]
445; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
446; CHECK:       then:
447; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
448; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]])
449; CHECK-NEXT:    ret i32 [[MAX]]
450; CHECK:       else:
451; CHECK-NEXT:    ret i32 -1
452;
453start:
454  %cmp = icmp sle i32 %a, %b
455  br i1 %cmp, label %then, label %else
456then:
457  %add = add nsw i32 %a, 1
458  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
459  ret i32 %max
460else:
461  ret i32 -1
462}
463
464define i32 @simplify_sge_smax_val(i32 %a, i32 %b) {
465; CHECK-LABEL: define i32 @simplify_sge_smax_val
466; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
467; CHECK-NEXT:  start:
468; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[A]], [[B]]
469; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
470; CHECK:       then:
471; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
472; CHECK-NEXT:    ret i32 [[ADD]]
473; CHECK:       else:
474; CHECK-NEXT:    ret i32 -1
475;
476start:
477  %cmp = icmp sge i32 %a, %b
478  br i1 %cmp, label %then, label %else
479then:
480  %add = add nsw i32 %a, 1
481  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
482  ret i32 %max
483else:
484  ret i32 -1
485}
486
487define i32 @simplify_ult_umax_val(i32 %a, i32 %b) {
488; CHECK-LABEL: define i32 @simplify_ult_umax_val
489; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
490; CHECK-NEXT:  start:
491; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
492; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
493; CHECK:       then:
494; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
495; CHECK-NEXT:    ret i32 [[B]]
496; CHECK:       else:
497; CHECK-NEXT:    ret i32 -1
498;
499start:
500  %cmp = icmp ult i32 %a, %b
501  br i1 %cmp, label %then, label %else
502then:
503  %add = add nuw i32 %a, 1
504  %max = call i32 @llvm.umax.i32(i32 %b, i32 %add)
505  ret i32 %max
506else:
507  ret i32 -1
508}
509
510define i32 @simplify_slt_smin_val(i32 %a, i32 %b) {
511; CHECK-LABEL: define i32 @simplify_slt_smin_val
512; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
513; CHECK-NEXT:  start:
514; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
515; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
516; CHECK:       then:
517; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
518; CHECK-NEXT:    ret i32 [[ADD]]
519; CHECK:       else:
520; CHECK-NEXT:    ret i32 -1
521;
522start:
523  %cmp = icmp slt i32 %a, %b
524  br i1 %cmp, label %then, label %else
525then:
526  %add = add nsw i32 %a, 1
527  %max = call i32 @llvm.smin.i32(i32 %b, i32 %add)
528  ret i32 %max
529else:
530  ret i32 -1
531}
532
533define i32 @simplify_ult_umin_val(i32 %a, i32 %b) {
534; CHECK-LABEL: define i32 @simplify_ult_umin_val
535; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
536; CHECK-NEXT:  start:
537; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
538; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
539; CHECK:       then:
540; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A]], 1
541; CHECK-NEXT:    ret i32 [[ADD]]
542; CHECK:       else:
543; CHECK-NEXT:    ret i32 -1
544;
545start:
546  %cmp = icmp ult i32 %a, %b
547  br i1 %cmp, label %then, label %else
548then:
549  %add = add nuw i32 %a, 1
550  %max = call i32 @llvm.umin.i32(i32 %b, i32 %add)
551  ret i32 %max
552else:
553  ret i32 -1
554}
555
556define i32 @simplify_slt_smax_val_fail1(i32 %a, i32 %b) {
557; CHECK-LABEL: define i32 @simplify_slt_smax_val_fail1
558; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
559; CHECK-NEXT:  start:
560; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
561; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
562; CHECK:       then:
563; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 2
564; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]])
565; CHECK-NEXT:    ret i32 [[MAX]]
566; CHECK:       else:
567; CHECK-NEXT:    ret i32 -1
568;
569start:
570  %cmp = icmp slt i32 %a, %b
571  br i1 %cmp, label %then, label %else
572then:
573  %add = add nsw i32 %a, 2
574  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
575  ret i32 %max
576else:
577  ret i32 -1
578}
579
580define i32 @simplify_ult_smax_val_fail2(i32 %a, i32 %b) {
581; CHECK-LABEL: define i32 @simplify_ult_smax_val_fail2
582; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
583; CHECK-NEXT:  start:
584; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[A]], [[B]]
585; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
586; CHECK:       then:
587; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 1
588; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 [[ADD]])
589; CHECK-NEXT:    ret i32 [[MAX]]
590; CHECK:       else:
591; CHECK-NEXT:    ret i32 -1
592;
593start:
594  %cmp = icmp ult i32 %a, %b
595  br i1 %cmp, label %then, label %else
596then:
597  %add = add nsw i32 %a, 1
598  %max = call i32 @llvm.smax.i32(i32 %b, i32 %add)
599  ret i32 %max
600else:
601  ret i32 -1
602}
603
604define i64 @pr82271(i32 %a, i32 %b){
605; CHECK-LABEL: define i64 @pr82271
606; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
607; CHECK-NEXT:  entry:
608; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
609; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
610; CHECK:       then:
611; CHECK-NEXT:    [[SA:%.*]] = sext i32 [[A]] to i64
612; CHECK-NEXT:    [[SB:%.*]] = sext i32 [[B]] to i64
613; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[SA]], 1
614; CHECK-NEXT:    ret i64 [[SB]]
615; CHECK:       else:
616; CHECK-NEXT:    ret i64 0
617;
618entry:
619  %cmp = icmp slt i32 %a, %b
620  br i1 %cmp, label %then, label %else
621
622then:
623  %sa = sext i32 %a to i64
624  %sb = sext i32 %b to i64
625  %add = add nsw i64 %sa, 1
626  %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add)
627  ret i64 %smax
628
629else:
630  ret i64 0
631}
632
633define i64 @pr82271_sext_zext_nneg(i32 %a, i32 %b){
634; CHECK-LABEL: define i64 @pr82271_sext_zext_nneg
635; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
636; CHECK-NEXT:  entry:
637; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
638; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
639; CHECK:       then:
640; CHECK-NEXT:    [[SA:%.*]] = sext i32 [[A]] to i64
641; CHECK-NEXT:    [[SB:%.*]] = zext nneg i32 [[B]] to i64
642; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[SA]], 1
643; CHECK-NEXT:    ret i64 [[SB]]
644; CHECK:       else:
645; CHECK-NEXT:    ret i64 0
646;
647entry:
648  %cmp = icmp slt i32 %a, %b
649  br i1 %cmp, label %then, label %else
650
651then:
652  %sa = sext i32 %a to i64
653  %sb = zext nneg i32 %b to i64
654  %add = add nsw i64 %sa, 1
655  %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add)
656  ret i64 %smax
657
658else:
659  ret i64 0
660}
661
662define i64 @pr82271_zext_nneg(i32 %a, i32 %b){
663; CHECK-LABEL: define i64 @pr82271_zext_nneg
664; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
665; CHECK-NEXT:  entry:
666; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
667; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
668; CHECK:       then:
669; CHECK-NEXT:    [[SA:%.*]] = zext nneg i32 [[A]] to i64
670; CHECK-NEXT:    [[SB:%.*]] = zext nneg i32 [[B]] to i64
671; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[SA]], 1
672; CHECK-NEXT:    ret i64 [[SB]]
673; CHECK:       else:
674; CHECK-NEXT:    ret i64 0
675;
676entry:
677  %cmp = icmp slt i32 %a, %b
678  br i1 %cmp, label %then, label %else
679
680then:
681  %sa = zext nneg i32 %a to i64
682  %sb = zext nneg i32 %b to i64
683  %add = add nsw i64 %sa, 1
684  %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add)
685  ret i64 %smax
686
687else:
688  ret i64 0
689}
690
691define i64 @pr82271_zext(i32 %a, i32 %b){
692; CHECK-LABEL: define i64 @pr82271_zext
693; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) {
694; CHECK-NEXT:  entry:
695; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[A]], [[B]]
696; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
697; CHECK:       then:
698; CHECK-NEXT:    [[SA:%.*]] = zext i32 [[A]] to i64
699; CHECK-NEXT:    [[SB:%.*]] = zext i32 [[B]] to i64
700; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[SA]], 1
701; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SB]], i64 [[ADD]])
702; CHECK-NEXT:    ret i64 [[SMAX]]
703; CHECK:       else:
704; CHECK-NEXT:    ret i64 0
705;
706entry:
707  %cmp = icmp slt i32 %a, %b
708  br i1 %cmp, label %then, label %else
709
710then:
711  %sa = zext i32 %a to i64
712  %sb = zext i32 %b to i64
713  %add = add nsw i64 %sa, 1
714  %smax = call i64 @llvm.smax.i64(i64 %sb, i64 %add)
715  ret i64 %smax
716
717else:
718  ret i64 0
719}
720
721declare i32 @llvm.smin.i32(i32, i32)
722declare i32 @llvm.smax.i32(i32, i32)
723declare i32 @llvm.umin.i32(i32, i32)
724declare i32 @llvm.umax.i32(i32, i32)
725