Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / minmax.ll
bloba31cf6845ad67da5504f426a39258b46fadcbf7e
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
4 ; Test from PR63896
5 define 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
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
21 if:
22   %cmp2 = icmp ugt i32 %y, %x
23   %cmp3 = icmp uge i32 %y, %x
24   %ret = xor i1 %cmp2, %cmp3
25   ret i1 %ret
27 end:
28   ret i1 false
31 define 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
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
48 if:
49   %cmp2 = icmp ugt i32 %y, %x
50   %cmp3 = icmp uge i32 %y, %x
51   %ret = xor i1 %cmp2, %cmp3
52   ret i1 %ret
54 end:
55   ret i1 false
58 define 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
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
74 if:
75   %cmp2 = icmp ult i32 %y, %x
76   %cmp3 = icmp ule i32 %y, %x
77   %ret = xor i1 %cmp2, %cmp3
78   ret i1 %ret
80 end:
81   ret i1 false
84 define 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
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
102   %cmp2 = icmp ult i32 %y, %x
103   %cmp3 = icmp ule i32 %y, %x
104   %ret = xor i1 %cmp2, %cmp3
105   ret i1 %ret
107 end:
108   ret i1 false
111 define 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
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
128   %cmp2 = icmp sgt i32 %y, %x
129   %cmp3 = icmp sge i32 %y, %x
130   %ret = xor i1 %cmp2, %cmp3
131   ret i1 %ret
133 end:
134   ret i1 false
137 define 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
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
155   %cmp2 = icmp sgt i32 %y, %x
156   %cmp3 = icmp sge i32 %y, %x
157   %ret = xor i1 %cmp2, %cmp3
158   ret i1 %ret
160 end:
161   ret i1 false
164 define 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
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
181   %cmp2 = icmp slt i32 %y, %x
182   %cmp3 = icmp sle i32 %y, %x
183   %ret = xor i1 %cmp2, %cmp3
184   ret i1 %ret
186 end:
187   ret i1 false
190 define 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
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
208   %cmp2 = icmp slt i32 %y, %x
209   %cmp3 = icmp sle i32 %y, %x
210   %ret = xor i1 %cmp2, %cmp3
211   ret i1 %ret
213 end:
214   ret i1 false
217 define 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
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
235   %cmp2 = icmp ugt i32 %y, %x
236   ret i1 %cmp2
238 end:
239   ret i1 false
242 define 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
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
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
274 end:
275   ret i1 false
278 define 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
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
295   %cmp2 = icmp ugt i32 %z, %x
296   %cmp3 = icmp ugt i32 %z, %y
297   %and = xor i1 %cmp2, %cmp3
298   ret i1 %and
300 end:
301   ret i1 false
304 define 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:    [[RET:%.*]] = xor i1 true, false
310 ; CHECK-NEXT:    ret i1 [[RET]]
312 entry:
313   %min = call i32 @llvm.smin.i32(i32 %x, i32 %y)
314   %cmp1 = icmp sle i32 %min, %x
315   %cmp2 = icmp sgt i32 %min, %x
316   %ret = xor i1 %cmp1, %cmp2
317   ret i1 %ret
320 define i32 @simplify_smax(i32 %x, i32 %y, i32 %z) {
321 ; CHECK-LABEL: define i32 @simplify_smax
322 ; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
323 ; CHECK-NEXT:  entry:
324 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], [[Y]]
325 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
326 ; CHECK:       if:
327 ; CHECK-NEXT:    [[MAX1:%.*]] = call i32 @llvm.smax.i32(i32 [[X]], i32 [[Z]])
328 ; CHECK-NEXT:    [[MAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[Y]], i32 [[MAX1]])
329 ; CHECK-NEXT:    ret i32 [[MAX2]]
330 ; CHECK:       end:
331 ; CHECK-NEXT:    ret i32 0
333 entry:
334   %cmp = icmp slt i32 %x, %y
335   br i1 %cmp, label %if, label %end
337   %max1 = call i32 @llvm.smax.i32(i32 %x, i32 %z)
338   %max2 = call i32 @llvm.smax.i32(i32 %y, i32 %max1)
339   ret i32 %max2
340 end:
341   ret i32 0
344 declare i32 @llvm.smin.i32(i32, i32)
345 declare i32 @llvm.smax.i32(i32, i32)
346 declare i32 @llvm.umin.i32(i32, i32)
347 declare i32 @llvm.umax.i32(i32, i32)