1; RUN: llc < %s -march=aarch64 -mtriple=aarch64-linux-gnu | FileCheck %s
2
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
8
9; (a > 10 && b == c) || (a >= 10 && b == d)
10define i32 @combine_gt_ge_10() #0 {
11; CHECK-LABEL: combine_gt_ge_10
12; CHECK: cmp
13; CHECK: b.le
14; CHECK: ret
15; CHECK-NOT: cmp
16; CHECK: b.lt
17entry:
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
21
22land.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
27
28lor.lhs.false:                                    ; preds = %entry
29  %cmp2 = icmp sgt i32 %0, 9
30  br i1 %cmp2, label %land.lhs.true3, label %if.end
31
32land.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
37
38if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
39  br label %return
40
41return:                                           ; 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 ]
43  ret i32 %retval.0
44}
45
46; (a > 5 && b == c) || (a < 5 && b == d)
47define i32 @combine_gt_lt_5() #0 {
48; CHECK-LABEL: combine_gt_lt_5
49; CHECK: cmp
50; CHECK: b.le
51; CHECK: ret
52; CHECK-NOT: cmp
53; CHECK: b.ge
54entry:
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
58
59land.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
64
65lor.lhs.false:                                    ; preds = %entry
66  %cmp2 = icmp slt i32 %0, 5
67  br i1 %cmp2, label %land.lhs.true3, label %if.end
68
69land.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
74
75if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
76  br label %return
77
78return:                                           ; 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 ]
80  ret i32 %retval.0
81}
82
83; (a < 5 && b == c) || (a <= 5 && b == d)
84define i32 @combine_lt_ge_5() #0 {
85; CHECK-LABEL: combine_lt_ge_5
86; CHECK: cmp
87; CHECK: b.ge
88; CHECK: ret
89; CHECK-NOT: cmp
90; CHECK: b.gt
91entry:
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
95
96land.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
101
102lor.lhs.false:                                    ; preds = %entry
103  %cmp2 = icmp slt i32 %0, 6
104  br i1 %cmp2, label %land.lhs.true3, label %if.end
105
106land.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
111
112if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
113  br label %return
114
115return:                                           ; 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 ]
117  ret i32 %retval.0
118}
119
120; (a < 5 && b == c) || (a > 5 && b == d)
121define i32 @combine_lt_gt_5() #0 {
122; CHECK-LABEL: combine_lt_gt_5
123; CHECK: cmp
124; CHECK: b.ge
125; CHECK: ret
126; CHECK-NOT: cmp
127; CHECK: b.le
128entry:
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
132
133land.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
138
139lor.lhs.false:                                    ; preds = %entry
140  %cmp2 = icmp sgt i32 %0, 5
141  br i1 %cmp2, label %land.lhs.true3, label %if.end
142
143land.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
148
149if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
150  br label %return
151
152return:                                           ; 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 ]
154  ret i32 %retval.0
155}
156
157; (a > -5 && b == c) || (a < -5 && b == d)
158define i32 @combine_gt_lt_n5() #0 {
159; CHECK-LABEL: combine_gt_lt_n5
160; CHECK: cmn
161; CHECK: b.le
162; CHECK: ret
163; CHECK-NOT: cmn
164; CHECK: b.ge
165entry:
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
169
170land.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
175
176lor.lhs.false:                                    ; preds = %entry
177  %cmp2 = icmp slt i32 %0, -5
178  br i1 %cmp2, label %land.lhs.true3, label %if.end
179
180land.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
185
186if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
187  br label %return
188
189return:                                           ; 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 ]
191  ret i32 %retval.0
192}
193
194; (a < -5 && b == c) || (a > -5 && b == d)
195define i32 @combine_lt_gt_n5() #0 {
196; CHECK-LABEL: combine_lt_gt_n5
197; CHECK: cmn
198; CHECK: b.ge
199; CHECK: ret
200; CHECK-NOT: cmn
201; CHECK: b.le
202entry:
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
206
207land.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
212
213lor.lhs.false:                                    ; preds = %entry
214  %cmp2 = icmp sgt i32 %0, -5
215  br i1 %cmp2, label %land.lhs.true3, label %if.end
216
217land.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
222
223if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
224  br label %return
225
226return:                                           ; 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 ]
228  ret i32 %retval.0
229}
230
231%struct.Struct = type { i64, i64 }
232
233@glob = internal unnamed_addr global %struct.Struct* null, align 8
234
235declare %struct.Struct* @Update(%struct.Struct*) #1
236
237; no checks for this case, it just should be processed without errors
238define void @combine_non_adjacent_cmp_br(%struct.Struct* nocapture readonly %hdCall) #0 {
239entry:
240  %size = getelementptr inbounds %struct.Struct, %struct.Struct* %hdCall, i64 0, i32 0
241  %0 = load i64, i64* %size, align 8
242  br label %land.rhs
243
244land.rhs:
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
249
250while.body:
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
256
257while.end:
258  ret void
259}
260
261; undefined external to prevent possible optimizations
262declare void @do_something() #1
263
264define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 {
265; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ
266; CHECK: cmn
267; CHECK: b.gt
268; CHECK: cmp
269; CHECK: b.gt
270entry:
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
274
275while.body.preheader:                             ; preds = %entry
276  br label %while.body
277
278while.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
284
285while.cond.while.end_crit_edge:                   ; preds = %while.body
286  %.pre = load i32, i32* @a, align 4
287  br label %while.end
288
289while.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
293
294land.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
299
300if.end:                                           ; preds = %land.lhs.true, %while.end
301  br label %return
302
303return:                                           ; preds = %if.end, %land.lhs.true
304  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
305  ret i32 %retval.0
306}
307
308define 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
310; CHECK: cmp
311; CHECK: b.gt
312; CHECK: cmn
313; CHECK: b.lt
314entry:
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
318
319while.body.preheader:                             ; preds = %entry
320  br label %while.body
321
322while.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
328
329while.end.loopexit:                               ; preds = %while.body
330  br label %while.end
331
332while.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
336
337land.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
342
343if.end:                                           ; preds = %land.lhs.true, %while.end
344  br label %return
345
346return:                                           ; preds = %if.end, %land.lhs.true
347  %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
348  ret i32 %retval.0
349}
350
351; Test in the following case, we don't hit 'cmp' and trigger a false positive
352; cmp  w19, #0
353; cinc w0, w19, gt
354; ...
355; fcmp d8, #0.0
356; b.gt .LBB0_5
357
358define i32 @fcmpri(i32 %argc, i8** nocapture readonly %argv) {
359
360; CHECK-LABEL: fcmpri:
361; CHECK: cmp w0, #2
362; CHECK: b.lt .LBB9_3
363; CHECK-NOT: cmp w0, #1
364; CHECK-NOT: b.le .LBB9_3
365
366; CHECK-LABEL-DAG: .LBB9_3
367; CHECK: cmp w19, #0
368; CHECK: fcmp d8, #0.0
369; CHECK-NOT: cmp w19, #1
370; CHECK-NOT: b.ge .LBB9_5
371
372entry:
373  %cmp = icmp sgt i32 %argc, 1
374  br i1 %cmp, label %land.lhs.true, label %if.end
375
376land.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
381
382if.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
391
392cond.false12:                                     ; preds = %if.end
393  %sub = fadd fast double %call2, -1.000000e+00
394  br label %cond.end14
395
396cond.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)
399  br label %return
400
401return:                                           ; preds = %land.lhs.true, %cond.end14
402  %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
403  ret i32 %retval.0
404}
405
406declare i32 @zoo(i32)
407
408declare double @yoo(i32)
409
410declare i32 @xoo(i32, i32)
411
412declare i32 @woo(double, double)
413