[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / icmp-dom.ll
blobab6c26db6c96eb04fec419e7f3a43928bac8e66a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define void @idom_sign_bit_check_edge_dominates(i64 %a) {
5 ; CHECK-LABEL: @idom_sign_bit_check_edge_dominates(
6 ; CHECK-NEXT:  entry:
7 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 0
8 ; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
9 ; CHECK:       land.lhs.true:
10 ; CHECK-NEXT:    br label [[LOR_END:%.*]]
11 ; CHECK:       lor.rhs:
12 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i64 [[A]], 0
13 ; CHECK-NEXT:    br i1 [[CMP2]], label [[LOR_END]], label [[LAND_RHS:%.*]]
14 ; CHECK:       land.rhs:
15 ; CHECK-NEXT:    br label [[LOR_END]]
16 ; CHECK:       lor.end:
17 ; CHECK-NEXT:    ret void
19 entry:
20   %cmp = icmp slt i64 %a, 0
21   br i1 %cmp, label %land.lhs.true, label %lor.rhs
23 land.lhs.true:
24   br label %lor.end
26 lor.rhs:
27   %cmp2 = icmp sgt i64 %a, 0
28   br i1 %cmp2, label %land.rhs, label %lor.end
30 land.rhs:
31   br label %lor.end
33 lor.end:
34   ret void
37 define void @idom_sign_bit_check_edge_not_dominates(i64 %a) {
38 ; CHECK-LABEL: @idom_sign_bit_check_edge_not_dominates(
39 ; CHECK-NEXT:  entry:
40 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 0
41 ; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
42 ; CHECK:       land.lhs.true:
43 ; CHECK-NEXT:    br i1 undef, label [[LOR_END:%.*]], label [[LOR_RHS]]
44 ; CHECK:       lor.rhs:
45 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[A]], 0
46 ; CHECK-NEXT:    br i1 [[CMP2]], label [[LAND_RHS:%.*]], label [[LOR_END]]
47 ; CHECK:       land.rhs:
48 ; CHECK-NEXT:    br label [[LOR_END]]
49 ; CHECK:       lor.end:
50 ; CHECK-NEXT:    ret void
52 entry:
53   %cmp = icmp slt i64 %a, 0
54   br i1 %cmp, label %land.lhs.true, label %lor.rhs
56 land.lhs.true:
57   br i1 undef, label %lor.end, label %lor.rhs
59 lor.rhs:
60   %cmp2 = icmp sgt i64 %a, 0
61   br i1 %cmp2, label %land.rhs, label %lor.end
63 land.rhs:
64   br label %lor.end
66 lor.end:
67   ret void
70 ; TODO: cmp3 could be reduced to A != B, but we miss that
71 ; while avoiding an infinite loop with min/max canonicalization.
73 define void @idom_sign_bit_check_edge_dominates_select(i64 %a, i64 %b) {
74 ; CHECK-LABEL: @idom_sign_bit_check_edge_dominates_select(
75 ; CHECK-NEXT:  entry:
76 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 5
77 ; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
78 ; CHECK:       land.lhs.true:
79 ; CHECK-NEXT:    br label [[LOR_END:%.*]]
80 ; CHECK:       lor.rhs:
81 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[A]], 5
82 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP2]], i64 [[A]], i64 5
83 ; CHECK-NEXT:    [[CMP3_NOT:%.*]] = icmp eq i64 [[SELECT]], [[B:%.*]]
84 ; CHECK-NEXT:    br i1 [[CMP3_NOT]], label [[LOR_END]], label [[LAND_RHS:%.*]]
85 ; CHECK:       land.rhs:
86 ; CHECK-NEXT:    br label [[LOR_END]]
87 ; CHECK:       lor.end:
88 ; CHECK-NEXT:    ret void
90 entry:
91   %cmp = icmp slt i64 %a, 5
92   br i1 %cmp, label %land.lhs.true, label %lor.rhs
94 land.lhs.true:
95   br label %lor.end
97 lor.rhs:
98   %cmp2 = icmp sgt i64 %a, 5
99   %select = select i1 %cmp2, i64 %a, i64 5
100   %cmp3 = icmp ne i64 %select, %b
101   br i1 %cmp3, label %land.rhs, label %lor.end
103 land.rhs:
104   br label %lor.end
106 lor.end:
107   ret void
110 define void @idom_zbranch(i64 %a) {
111 ; CHECK-LABEL: @idom_zbranch(
112 ; CHECK-NEXT:  entry:
113 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[A:%.*]], 0
114 ; CHECK-NEXT:    br i1 [[CMP]], label [[LOR_END:%.*]], label [[LOR_RHS:%.*]]
115 ; CHECK:       lor.rhs:
116 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[A]], 0
117 ; CHECK-NEXT:    br i1 [[CMP2]], label [[LAND_RHS:%.*]], label [[LOR_END]]
118 ; CHECK:       land.rhs:
119 ; CHECK-NEXT:    br label [[LOR_END]]
120 ; CHECK:       lor.end:
121 ; CHECK-NEXT:    ret void
123 entry:
124   %cmp = icmp sgt i64 %a, 0
125   br i1 %cmp, label %lor.end, label %lor.rhs
127 lor.rhs:
128   %cmp2 = icmp slt i64 %a, 0
129   br i1 %cmp2, label %land.rhs, label %lor.end
131 land.rhs:
132   br label %lor.end
134 lor.end:
135   ret void
138 ; TODO: cmp2 could be reduced to A != B, but we miss that
139 ; while avoiding an infinite loop with min/max canonicalization.
141 define void @idom_not_zbranch(i32 %a, i32 %b) {
142 ; CHECK-LABEL: @idom_not_zbranch(
143 ; CHECK-NEXT:  entry:
144 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
145 ; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_END:%.*]]
146 ; CHECK:       if.end:
147 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[A]], 0
148 ; CHECK-NEXT:    [[A_:%.*]] = select i1 [[CMP1]], i32 [[A]], i32 0
149 ; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i32 [[A_]], [[B:%.*]]
150 ; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[RETURN]], label [[IF_THEN3:%.*]]
151 ; CHECK:       if.then3:
152 ; CHECK-NEXT:    br label [[RETURN]]
153 ; CHECK:       return:
154 ; CHECK-NEXT:    ret void
156 entry:
157   %cmp = icmp sgt i32 %a, 0
158   br i1 %cmp, label %return, label %if.end
160 if.end:
161   %cmp1 = icmp slt i32 %a, 0
162   %a. = select i1 %cmp1, i32 %a, i32 0
163   %cmp2 = icmp ne i32 %a., %b
164   br i1 %cmp2, label %if.then3, label %return
166 if.then3:
167   br label %return
169 return:
170   ret void
173 define void @trueblock_cmp_eq(i32 %a, i32 %b) {
174 ; CHECK-LABEL: @trueblock_cmp_eq(
175 ; CHECK-NEXT:  entry:
176 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
177 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END:%.*]], label [[RETURN:%.*]]
178 ; CHECK:       if.end:
179 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A]], 1
180 ; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN3:%.*]], label [[RETURN]]
181 ; CHECK:       if.then3:
182 ; CHECK-NEXT:    br label [[RETURN]]
183 ; CHECK:       return:
184 ; CHECK-NEXT:    ret void
186 entry:
187   %cmp = icmp sgt i32 %a, 0
188   br i1 %cmp, label %if.end, label %return
190 if.end:
191   %cmp1 = icmp slt i32 %a, 2
192   br i1 %cmp1, label %if.then3, label %return
194 if.then3:
195   br label %return
197 return:
198   ret void
201 define i1 @trueblock_cmp_is_false(i32 %x, i32 %y) {
202 ; CHECK-LABEL: @trueblock_cmp_is_false(
203 ; CHECK-NEXT:  entry:
204 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
205 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
206 ; CHECK:       t:
207 ; CHECK-NEXT:    ret i1 false
208 ; CHECK:       f:
209 ; CHECK-NEXT:    ret i1 [[CMP]]
211 entry:
212   %cmp = icmp sgt i32 %x, %y
213   br i1 %cmp, label %t, label %f
215   %cmp2 = icmp slt i32 %x, %y
216   ret i1 %cmp2
218   ret i1 %cmp
221 define i1 @trueblock_cmp_is_false_commute(i32 %x, i32 %y) {
222 ; CHECK-LABEL: @trueblock_cmp_is_false_commute(
223 ; CHECK-NEXT:  entry:
224 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
225 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
226 ; CHECK:       t:
227 ; CHECK-NEXT:    ret i1 false
228 ; CHECK:       f:
229 ; CHECK-NEXT:    ret i1 [[CMP]]
231 entry:
232   %cmp = icmp eq i32 %x, %y
233   br i1 %cmp, label %t, label %f
235   %cmp2 = icmp sgt i32 %y, %x
236   ret i1 %cmp2
238   ret i1 %cmp
241 define i1 @trueblock_cmp_is_true(i32 %x, i32 %y) {
242 ; CHECK-LABEL: @trueblock_cmp_is_true(
243 ; CHECK-NEXT:  entry:
244 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
245 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
246 ; CHECK:       t:
247 ; CHECK-NEXT:    ret i1 true
248 ; CHECK:       f:
249 ; CHECK-NEXT:    ret i1 [[CMP]]
251 entry:
252   %cmp = icmp ult i32 %x, %y
253   br i1 %cmp, label %t, label %f
255   %cmp2 = icmp ne i32 %x, %y
256   ret i1 %cmp2
258   ret i1 %cmp
261 define i1 @trueblock_cmp_is_true_commute(i32 %x, i32 %y) {
262 ; CHECK-LABEL: @trueblock_cmp_is_true_commute(
263 ; CHECK-NEXT:  entry:
264 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
265 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
266 ; CHECK:       t:
267 ; CHECK-NEXT:    ret i1 true
268 ; CHECK:       f:
269 ; CHECK-NEXT:    ret i1 [[CMP]]
271 entry:
272   %cmp = icmp ugt i32 %x, %y
273   br i1 %cmp, label %t, label %f
275   %cmp2 = icmp ne i32 %y, %x
276   ret i1 %cmp2
278   ret i1 %cmp
281 define i1 @falseblock_cmp_is_false(i32 %x, i32 %y) {
282 ; CHECK-LABEL: @falseblock_cmp_is_false(
283 ; CHECK-NEXT:  entry:
284 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
285 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
286 ; CHECK:       t:
287 ; CHECK-NEXT:    ret i1 [[CMP]]
288 ; CHECK:       f:
289 ; CHECK-NEXT:    ret i1 false
291 entry:
292   %cmp = icmp sle i32 %x, %y
293   br i1 %cmp, label %t, label %f
295   ret i1 %cmp
297   %cmp2 = icmp slt i32 %x, %y
298   ret i1 %cmp2
301 define i1 @falseblock_cmp_is_false_commute(i32 %x, i32 %y) {
302 ; CHECK-LABEL: @falseblock_cmp_is_false_commute(
303 ; CHECK-NEXT:  entry:
304 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
305 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
306 ; CHECK:       t:
307 ; CHECK-NEXT:    ret i1 [[CMP]]
308 ; CHECK:       f:
309 ; CHECK-NEXT:    ret i1 false
311 entry:
312   %cmp = icmp eq i32 %x, %y
313   br i1 %cmp, label %t, label %f
315   ret i1 %cmp
317   %cmp2 = icmp eq i32 %y, %x
318   ret i1 %cmp2
321 define i1 @falseblock_cmp_is_true(i32 %x, i32 %y) {
322 ; CHECK-LABEL: @falseblock_cmp_is_true(
323 ; CHECK-NEXT:  entry:
324 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
325 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
326 ; CHECK:       t:
327 ; CHECK-NEXT:    ret i1 [[CMP]]
328 ; CHECK:       f:
329 ; CHECK-NEXT:    ret i1 true
331 entry:
332   %cmp = icmp ult i32 %x, %y
333   br i1 %cmp, label %t, label %f
335   ret i1 %cmp
337   %cmp2 = icmp uge i32 %x, %y
338   ret i1 %cmp2
341 define i1 @falseblock_cmp_is_true_commute(i32 %x, i32 %y) {
342 ; CHECK-LABEL: @falseblock_cmp_is_true_commute(
343 ; CHECK-NEXT:  entry:
344 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
345 ; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
346 ; CHECK:       t:
347 ; CHECK-NEXT:    ret i1 [[CMP]]
348 ; CHECK:       f:
349 ; CHECK-NEXT:    ret i1 true
351 entry:
352   %cmp = icmp sgt i32 %x, %y
353   br i1 %cmp, label %t, label %f
355   ret i1 %cmp
357   %cmp2 = icmp sge i32 %y, %x
358   ret i1 %cmp2
361 ; This used to infinite loop because of a conflict
362 ; with min/max canonicalization.
364 define i32 @PR48900(i32 %i, i1* %p) {
365 ; CHECK-LABEL: @PR48900(
366 ; CHECK-NEXT:    [[MAXCMP:%.*]] = icmp ugt i32 [[I:%.*]], 1
367 ; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[MAXCMP]], i32 [[I]], i32 1
368 ; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[UMAX]], 0
369 ; CHECK-NEXT:    br i1 [[I4]], label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]]
370 ; CHECK:       truelabel:
371 ; CHECK-NEXT:    [[MINCMP:%.*]] = icmp ult i32 [[UMAX]], 2
372 ; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[MINCMP]], i32 [[UMAX]], i32 2
373 ; CHECK-NEXT:    ret i32 [[SMIN]]
374 ; CHECK:       falselabel:
375 ; CHECK-NEXT:    ret i32 0
377   %maxcmp = icmp ugt i32 %i, 1
378   %umax = select i1 %maxcmp, i32 %i, i32 1
379   %i4 = icmp sgt i32 %umax, 0
380   br i1 %i4, label %truelabel, label %falselabel
382 truelabel:
383   %mincmp = icmp ult i32 %umax, 2
384   %smin = select i1 %mincmp, i32 %umax, i32 2
385   ret i32 %smin
387 falselabel:
388   ret i32 0
391 ; This used to infinite loop because of a conflict
392 ; with min/max canonicalization.
394 define i8 @PR48900_alt(i8 %i, i1* %p) {
395 ; CHECK-LABEL: @PR48900_alt(
396 ; CHECK-NEXT:    [[MAXCMP:%.*]] = icmp sgt i8 [[I:%.*]], -127
397 ; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[MAXCMP]], i8 [[I]], i8 -127
398 ; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i8 [[SMAX]], -128
399 ; CHECK-NEXT:    br i1 [[I4]], label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]]
400 ; CHECK:       truelabel:
401 ; CHECK-NEXT:    [[MINCMP:%.*]] = icmp slt i8 [[SMAX]], -126
402 ; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[MINCMP]], i8 [[SMAX]], i8 -126
403 ; CHECK-NEXT:    ret i8 [[UMIN]]
404 ; CHECK:       falselabel:
405 ; CHECK-NEXT:    ret i8 0
407   %maxcmp = icmp sgt i8 %i, -127
408   %smax = select i1 %maxcmp, i8 %i, i8 -127
409   %i4 = icmp ugt i8 %smax, 128
410   br i1 %i4, label %truelabel, label %falselabel
412 truelabel:
413   %mincmp = icmp slt i8 %smax, -126
414   %umin = select i1 %mincmp, i8 %smax, i8 -126
415   ret i8 %umin
417 falselabel:
418   ret i8 0