1 ; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s
3 ; marked as external to prevent possible optimizations
4 @a = external global i32
5 @b = external global i32
6 @c = external global i32
7 @d = external global i32
9 ; (a > 10 && b == c) || (a >= 10 && b == d)
10 define i32 @combine_gt_ge_10() #0 {
11 ; CHECK-LABEL: combine_gt_ge_10
18 %0 = load i32, i32* @a, align 4
19 %cmp = icmp sgt i32 %0, 10
20 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
22 land.lhs.true: ; preds = %entry
23 %1 = load i32, i32* @b, align 4
24 %2 = load i32, i32* @c, align 4
25 %cmp1 = icmp eq i32 %1, %2
26 br i1 %cmp1, label %return, label %land.lhs.true3
28 lor.lhs.false: ; preds = %entry
29 %cmp2 = icmp sgt i32 %0, 9
30 br i1 %cmp2, label %land.lhs.true3, label %if.end
32 land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true
33 %3 = load i32, i32* @b, align 4
34 %4 = load i32, i32* @d, align 4
35 %cmp4 = icmp eq i32 %3, %4
36 br i1 %cmp4, label %return, label %if.end
38 if.end: ; preds = %land.lhs.true3, %lor.lhs.false
41 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
42 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
46 ; (a > 5 && b == c) || (a < 5 && b == d)
47 define i32 @combine_gt_lt_5() #0 {
48 ; CHECK-LABEL: combine_gt_lt_5
55 %0 = load i32, i32* @a, align 4
56 %cmp = icmp sgt i32 %0, 5
57 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
59 land.lhs.true: ; preds = %entry
60 %1 = load i32, i32* @b, align 4
61 %2 = load i32, i32* @c, align 4
62 %cmp1 = icmp eq i32 %1, %2
63 br i1 %cmp1, label %return, label %if.end
65 lor.lhs.false: ; preds = %entry
66 %cmp2 = icmp slt i32 %0, 5
67 br i1 %cmp2, label %land.lhs.true3, label %if.end
69 land.lhs.true3: ; preds = %lor.lhs.false
70 %3 = load i32, i32* @b, align 4
71 %4 = load i32, i32* @d, align 4
72 %cmp4 = icmp eq i32 %3, %4
73 br i1 %cmp4, label %return, label %if.end
75 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
78 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
79 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
83 ; (a < 5 && b == c) || (a <= 5 && b == d)
84 define i32 @combine_lt_ge_5() #0 {
85 ; CHECK-LABEL: combine_lt_ge_5
92 %0 = load i32, i32* @a, align 4
93 %cmp = icmp slt i32 %0, 5
94 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
96 land.lhs.true: ; preds = %entry
97 %1 = load i32, i32* @b, align 4
98 %2 = load i32, i32* @c, align 4
99 %cmp1 = icmp eq i32 %1, %2
100 br i1 %cmp1, label %return, label %land.lhs.true3
102 lor.lhs.false: ; preds = %entry
103 %cmp2 = icmp slt i32 %0, 6
104 br i1 %cmp2, label %land.lhs.true3, label %if.end
106 land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true
107 %3 = load i32, i32* @b, align 4
108 %4 = load i32, i32* @d, align 4
109 %cmp4 = icmp eq i32 %3, %4
110 br i1 %cmp4, label %return, label %if.end
112 if.end: ; preds = %land.lhs.true3, %lor.lhs.false
115 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
116 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
120 ; (a < 5 && b == c) || (a > 5 && b == d)
121 define i32 @combine_lt_gt_5() #0 {
122 ; CHECK-LABEL: combine_lt_gt_5
129 %0 = load i32, i32* @a, align 4
130 %cmp = icmp slt i32 %0, 5
131 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
133 land.lhs.true: ; preds = %entry
134 %1 = load i32, i32* @b, align 4
135 %2 = load i32, i32* @c, align 4
136 %cmp1 = icmp eq i32 %1, %2
137 br i1 %cmp1, label %return, label %if.end
139 lor.lhs.false: ; preds = %entry
140 %cmp2 = icmp sgt i32 %0, 5
141 br i1 %cmp2, label %land.lhs.true3, label %if.end
143 land.lhs.true3: ; preds = %lor.lhs.false
144 %3 = load i32, i32* @b, align 4
145 %4 = load i32, i32* @d, align 4
146 %cmp4 = icmp eq i32 %3, %4
147 br i1 %cmp4, label %return, label %if.end
149 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
152 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
153 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
157 ; (a > -5 && b == c) || (a < -5 && b == d)
158 define i32 @combine_gt_lt_n5() #0 {
159 ; CHECK-LABEL: combine_gt_lt_n5
166 %0 = load i32, i32* @a, align 4
167 %cmp = icmp sgt i32 %0, -5
168 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
170 land.lhs.true: ; preds = %entry
171 %1 = load i32, i32* @b, align 4
172 %2 = load i32, i32* @c, align 4
173 %cmp1 = icmp eq i32 %1, %2
174 br i1 %cmp1, label %return, label %if.end
176 lor.lhs.false: ; preds = %entry
177 %cmp2 = icmp slt i32 %0, -5
178 br i1 %cmp2, label %land.lhs.true3, label %if.end
180 land.lhs.true3: ; preds = %lor.lhs.false
181 %3 = load i32, i32* @b, align 4
182 %4 = load i32, i32* @d, align 4
183 %cmp4 = icmp eq i32 %3, %4
184 br i1 %cmp4, label %return, label %if.end
186 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
189 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
190 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
194 ; (a < -5 && b == c) || (a > -5 && b == d)
195 define i32 @combine_lt_gt_n5() #0 {
196 ; CHECK-LABEL: combine_lt_gt_n5
203 %0 = load i32, i32* @a, align 4
204 %cmp = icmp slt i32 %0, -5
205 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
207 land.lhs.true: ; preds = %entry
208 %1 = load i32, i32* @b, align 4
209 %2 = load i32, i32* @c, align 4
210 %cmp1 = icmp eq i32 %1, %2
211 br i1 %cmp1, label %return, label %if.end
213 lor.lhs.false: ; preds = %entry
214 %cmp2 = icmp sgt i32 %0, -5
215 br i1 %cmp2, label %land.lhs.true3, label %if.end
217 land.lhs.true3: ; preds = %lor.lhs.false
218 %3 = load i32, i32* @b, align 4
219 %4 = load i32, i32* @d, align 4
220 %cmp4 = icmp eq i32 %3, %4
221 br i1 %cmp4, label %return, label %if.end
223 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
226 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
227 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
231 %struct.Struct = type { i64, i64 }
233 @glob = internal unnamed_addr global %struct.Struct* null, align 8
235 declare %struct.Struct* @Update(%struct.Struct*) #1
237 ; no checks for this case, it just should be processed without errors
238 define void @combine_non_adjacent_cmp_br(%struct.Struct* nocapture readonly %hdCall) #0 {
240 %size = getelementptr inbounds %struct.Struct, %struct.Struct* %hdCall, i64 0, i32 0
241 %0 = load i64, i64* %size, align 8
245 %rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ]
246 %1 = load i64, i64* inttoptr (i64 24 to i64*), align 8
247 %cmp2 = icmp sgt i64 %1, 0
248 br i1 %cmp2, label %while.body, label %while.end
251 %2 = load %struct.Struct*, %struct.Struct** @glob, align 8
252 %call = tail call %struct.Struct* @Update(%struct.Struct* %2) #2
253 %sub = add nsw i64 %rp.06, -2
254 %cmp = icmp slt i64 %0, %rp.06
255 br i1 %cmp, label %land.rhs, label %while.end
261 ; undefined external to prevent possible optimizations
262 declare void @do_something() #1
264 define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 {
265 ; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ
271 %0 = load i32, i32* @a, align 4
272 %cmp4 = icmp slt i32 %0, -1
273 br i1 %cmp4, label %while.body.preheader, label %while.end
275 while.body.preheader: ; preds = %entry
278 while.body: ; preds = %while.body, %while.body.preheader
279 %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
280 tail call void @do_something() #2
281 %inc = add nsw i32 %i.05, 1
282 %cmp = icmp slt i32 %i.05, 0
283 br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
285 while.cond.while.end_crit_edge: ; preds = %while.body
286 %.pre = load i32, i32* @a, align 4
289 while.end: ; preds = %while.cond.while.end_crit_edge, %entry
290 %1 = phi i32 [ %.pre, %while.cond.while.end_crit_edge ], [ %0, %entry ]
291 %cmp1 = icmp slt i32 %1, 2
292 br i1 %cmp1, label %land.lhs.true, label %if.end
294 land.lhs.true: ; preds = %while.end
295 %2 = load i32, i32* @b, align 4
296 %3 = load i32, i32* @d, align 4
297 %cmp2 = icmp eq i32 %2, %3
298 br i1 %cmp2, label %return, label %if.end
300 if.end: ; preds = %land.lhs.true, %while.end
303 return: ; preds = %if.end, %land.lhs.true
304 %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
308 define i32 @do_nothing_if_compares_can_not_be_adjusted_to_each_other() #0 {
309 ; CHECK-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other
315 %0 = load i32, i32* @a, align 4
316 %cmp4 = icmp slt i32 %0, 1
317 br i1 %cmp4, label %while.body.preheader, label %while.end
319 while.body.preheader: ; preds = %entry
322 while.body: ; preds = %while.body, %while.body.preheader
323 %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
324 tail call void @do_something() #2
325 %inc = add nsw i32 %i.05, 1
326 %cmp = icmp slt i32 %i.05, 0
327 br i1 %cmp, label %while.body, label %while.end.loopexit
329 while.end.loopexit: ; preds = %while.body
332 while.end: ; preds = %while.end.loopexit, %entry
333 %1 = load i32, i32* @c, align 4
334 %cmp1 = icmp sgt i32 %1, -3
335 br i1 %cmp1, label %land.lhs.true, label %if.end
337 land.lhs.true: ; preds = %while.end
338 %2 = load i32, i32* @b, align 4
339 %3 = load i32, i32* @d, align 4
340 %cmp2 = icmp eq i32 %2, %3
341 br i1 %cmp2, label %return, label %if.end
343 if.end: ; preds = %land.lhs.true, %while.end
346 return: ; preds = %if.end, %land.lhs.true
347 %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
351 ; Test in the following case, we don't hit 'cmp' and trigger a false positive
358 define i32 @fcmpri(i32 %argc, i8** nocapture readonly %argv) {
360 ; CHECK-LABEL: fcmpri:
362 ; CHECK: b.lt .LBB9_3
363 ; CHECK-NOT: cmp w0, #1
364 ; CHECK-NOT: b.le .LBB9_3
366 ; CHECK-LABEL-DAG: .LBB9_3
368 ; CHECK: fcmp d8, #0.0
369 ; CHECK-NOT: cmp w19, #1
370 ; CHECK-NOT: b.ge .LBB9_5
373 %cmp = icmp sgt i32 %argc, 1
374 br i1 %cmp, label %land.lhs.true, label %if.end
376 land.lhs.true: ; preds = %entry
377 %arrayidx = getelementptr inbounds i8*, i8** %argv, i64 1
378 %0 = load i8*, i8** %arrayidx, align 8
379 %cmp1 = icmp eq i8* %0, null
380 br i1 %cmp1, label %if.end, label %return
382 if.end: ; preds = %land.lhs.true, %entry
383 %call = call i32 @zoo(i32 1)
384 %call2 = call double @yoo(i32 -1)
385 %cmp4 = icmp sgt i32 %call, 0
386 %add = zext i1 %cmp4 to i32
387 %cond = add nsw i32 %add, %call
388 %call7 = call i32 @xoo(i32 %cond, i32 2)
389 %cmp9 = fcmp ogt double %call2, 0.000000e+00
390 br i1 %cmp9, label %cond.end14, label %cond.false12
392 cond.false12: ; preds = %if.end
393 %sub = fadd fast double %call2, -1.000000e+00
396 cond.end14: ; preds = %if.end, %cond.false12
397 %cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
398 %call16 = call i32 @woo(double %cond15, double -2.000000e+00)
401 return: ; preds = %land.lhs.true, %cond.end14
402 %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
406 define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) {
407 ; CHECK-LABEL: cmp_shifted:
408 ; CHECK: cmp w0, #2, lsl #12
412 %tst_low = icmp sgt i32 %in, 8191
413 br i1 %tst_low, label %true, label %false
416 call i32 @zoo(i32 128)
420 %tst = icmp sgt i32 %in, 0
421 br i1 %tst, label %truer, label %falser
424 call i32 @zoo(i32 42)
432 define i32 @combine_gt_ge_sel(i64 %v, i64* %p) #0 {
433 ; CHECK-LABEL: combine_gt_ge_sel
434 ; CHECK: ldr [[reg1:w[0-9]*]],
435 ; CHECK: cmp [[reg1]], #0
436 ; CHECK: csel {{.*}}, gt
438 %0 = load i32, i32* @a, align 4
439 %cmp = icmp sgt i32 %0, 0
440 %m = select i1 %cmp, i64 %v, i64 0
441 store i64 %m, i64* %p
442 br i1 %cmp, label %lor.lhs.false, label %land.lhs.true
444 land.lhs.true: ; preds = %entry
445 %1 = load i32, i32* @b, align 4
446 %2 = load i32, i32* @c, align 4
447 %cmp1 = icmp eq i32 %1, %2
448 br i1 %cmp1, label %return, label %land.lhs.true3
450 lor.lhs.false: ; preds = %entry
451 %cmp2 = icmp sgt i32 %0, 1
452 br i1 %cmp2, label %land.lhs.true3, label %if.end
454 land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true
455 %3 = load i32, i32* @b, align 4
456 %4 = load i32, i32* @d, align 4
457 %cmp4 = icmp eq i32 %3, %4
458 br i1 %cmp4, label %return, label %if.end
460 if.end: ; preds = %land.lhs.true3, %lor.lhs.false
463 return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true
464 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
468 declare i32 @zoo(i32)
470 declare double @yoo(i32)
472 declare i32 @xoo(i32, i32)
474 declare i32 @woo(double, double)