[AArch64] CondOpt pass is missing FCMP instructions when searching backward for
[oota-llvm.git] / test / CodeGen / AArch64 / combine-comparisons-by-cse.ll
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)
10 define 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
17 entry:
18   %0 = load i32* @a, align 4
19   %cmp = icmp sgt i32 %0, 10
20   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
21
22 land.lhs.true:                                    ; preds = %entry
23   %1 = load i32* @b, align 4
24   %2 = load i32* @c, align 4
25   %cmp1 = icmp eq i32 %1, %2
26   br i1 %cmp1, label %return, label %land.lhs.true3
27
28 lor.lhs.false:                                    ; preds = %entry
29   %cmp2 = icmp sgt i32 %0, 9
30   br i1 %cmp2, label %land.lhs.true3, label %if.end
31
32 land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
33   %3 = load i32* @b, align 4
34   %4 = load i32* @d, align 4
35   %cmp4 = icmp eq i32 %3, %4
36   br i1 %cmp4, label %return, label %if.end
37
38 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
39   br label %return
40
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 ]
43   ret i32 %retval.0
44 }
45
46 ; (a > 5 && b == c) || (a < 5 && b == d)
47 define 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
54 entry:
55   %0 = load i32* @a, align 4
56   %cmp = icmp sgt i32 %0, 5
57   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
58
59 land.lhs.true:                                    ; preds = %entry
60   %1 = load i32* @b, align 4
61   %2 = load i32* @c, align 4
62   %cmp1 = icmp eq i32 %1, %2
63   br i1 %cmp1, label %return, label %if.end
64
65 lor.lhs.false:                                    ; preds = %entry
66   %cmp2 = icmp slt i32 %0, 5
67   br i1 %cmp2, label %land.lhs.true3, label %if.end
68
69 land.lhs.true3:                                   ; preds = %lor.lhs.false
70   %3 = load i32* @b, align 4
71   %4 = load i32* @d, align 4
72   %cmp4 = icmp eq i32 %3, %4
73   br i1 %cmp4, label %return, label %if.end
74
75 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
76   br label %return
77
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 ]
80   ret i32 %retval.0
81 }
82
83 ; (a < 5 && b == c) || (a <= 5 && b == d)
84 define 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
91 entry:
92   %0 = load i32* @a, align 4
93   %cmp = icmp slt i32 %0, 5
94   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
95
96 land.lhs.true:                                    ; preds = %entry
97   %1 = load i32* @b, align 4
98   %2 = load i32* @c, align 4
99   %cmp1 = icmp eq i32 %1, %2
100   br i1 %cmp1, label %return, label %land.lhs.true3
101
102 lor.lhs.false:                                    ; preds = %entry
103   %cmp2 = icmp slt i32 %0, 6
104   br i1 %cmp2, label %land.lhs.true3, label %if.end
105
106 land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
107   %3 = load i32* @b, align 4
108   %4 = load i32* @d, align 4
109   %cmp4 = icmp eq i32 %3, %4
110   br i1 %cmp4, label %return, label %if.end
111
112 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
113   br label %return
114
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 ]
117   ret i32 %retval.0
118 }
119
120 ; (a < 5 && b == c) || (a > 5 && b == d)
121 define 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
128 entry:
129   %0 = load i32* @a, align 4
130   %cmp = icmp slt i32 %0, 5
131   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
132
133 land.lhs.true:                                    ; preds = %entry
134   %1 = load i32* @b, align 4
135   %2 = load i32* @c, align 4
136   %cmp1 = icmp eq i32 %1, %2
137   br i1 %cmp1, label %return, label %if.end
138
139 lor.lhs.false:                                    ; preds = %entry
140   %cmp2 = icmp sgt i32 %0, 5
141   br i1 %cmp2, label %land.lhs.true3, label %if.end
142
143 land.lhs.true3:                                   ; preds = %lor.lhs.false
144   %3 = load i32* @b, align 4
145   %4 = load i32* @d, align 4
146   %cmp4 = icmp eq i32 %3, %4
147   br i1 %cmp4, label %return, label %if.end
148
149 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
150   br label %return
151
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 ]
154   ret i32 %retval.0
155 }
156
157 ; (a > -5 && b == c) || (a < -5 && b == d)
158 define 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
165 entry:
166   %0 = load i32* @a, align 4
167   %cmp = icmp sgt i32 %0, -5
168   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
169
170 land.lhs.true:                                    ; preds = %entry
171   %1 = load i32* @b, align 4
172   %2 = load i32* @c, align 4
173   %cmp1 = icmp eq i32 %1, %2
174   br i1 %cmp1, label %return, label %if.end
175
176 lor.lhs.false:                                    ; preds = %entry
177   %cmp2 = icmp slt i32 %0, -5
178   br i1 %cmp2, label %land.lhs.true3, label %if.end
179
180 land.lhs.true3:                                   ; preds = %lor.lhs.false
181   %3 = load i32* @b, align 4
182   %4 = load i32* @d, align 4
183   %cmp4 = icmp eq i32 %3, %4
184   br i1 %cmp4, label %return, label %if.end
185
186 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
187   br label %return
188
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 ]
191   ret i32 %retval.0
192 }
193
194 ; (a < -5 && b == c) || (a > -5 && b == d)
195 define 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
202 entry:
203   %0 = load i32* @a, align 4
204   %cmp = icmp slt i32 %0, -5
205   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
206
207 land.lhs.true:                                    ; preds = %entry
208   %1 = load i32* @b, align 4
209   %2 = load i32* @c, align 4
210   %cmp1 = icmp eq i32 %1, %2
211   br i1 %cmp1, label %return, label %if.end
212
213 lor.lhs.false:                                    ; preds = %entry
214   %cmp2 = icmp sgt i32 %0, -5
215   br i1 %cmp2, label %land.lhs.true3, label %if.end
216
217 land.lhs.true3:                                   ; preds = %lor.lhs.false
218   %3 = load i32* @b, align 4
219   %4 = load i32* @d, align 4
220   %cmp4 = icmp eq i32 %3, %4
221   br i1 %cmp4, label %return, label %if.end
222
223 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
224   br label %return
225
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 ]
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
235 declare %struct.Struct* @Update(%struct.Struct*) #1
236
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 {
239 entry:
240   %size = getelementptr inbounds %struct.Struct* %hdCall, i64 0, i32 0
241   %0 = load i64* %size, align 8
242   br label %land.rhs
243
244 land.rhs:
245   %rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ]
246   %1 = load 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
250 while.body:
251   %2 = load %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
257 while.end:
258   ret void
259 }
260
261 ; undefined external to prevent possible optimizations
262 declare void @do_something() #1
263
264 define 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
270 entry:
271   %0 = load i32* @a, align 4
272   %cmp4 = icmp slt i32 %0, -1
273   br i1 %cmp4, label %while.body.preheader, label %while.end
274
275 while.body.preheader:                             ; preds = %entry
276   br label %while.body
277
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
284
285 while.cond.while.end_crit_edge:                   ; preds = %while.body
286   %.pre = load i32* @a, align 4
287   br label %while.end
288
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
293
294 land.lhs.true:                                    ; preds = %while.end
295   %2 = load i32* @b, align 4
296   %3 = load i32* @d, align 4
297   %cmp2 = icmp eq i32 %2, %3
298   br i1 %cmp2, label %return, label %if.end
299
300 if.end:                                           ; preds = %land.lhs.true, %while.end
301   br label %return
302
303 return:                                           ; 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
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
310 ; CHECK: cmp
311 ; CHECK: b.gt
312 ; CHECK: cmn
313 ; CHECK: b.lt
314 entry:
315   %0 = load i32* @a, align 4
316   %cmp4 = icmp slt i32 %0, 1
317   br i1 %cmp4, label %while.body.preheader, label %while.end
318
319 while.body.preheader:                             ; preds = %entry
320   br label %while.body
321
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
328
329 while.end.loopexit:                               ; preds = %while.body
330   br label %while.end
331
332 while.end:                                        ; preds = %while.end.loopexit, %entry
333   %1 = load i32* @c, align 4
334   %cmp1 = icmp sgt i32 %1, -3
335   br i1 %cmp1, label %land.lhs.true, label %if.end
336
337 land.lhs.true:                                    ; preds = %while.end
338   %2 = load i32* @b, align 4
339   %3 = load i32* @d, align 4
340   %cmp2 = icmp eq i32 %2, %3
341   br i1 %cmp2, label %return, label %if.end
342
343 if.end:                                           ; preds = %land.lhs.true, %while.end
344   br label %return
345
346 return:                                           ; 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
358 define 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: b.gt .LBB9_5
370 ; CHECK-NOT: cmp w19, #1
371 ; CHECK-NOT: b.ge .LBB9_5
372
373 entry:
374   %cmp = icmp sgt i32 %argc, 1
375   br i1 %cmp, label %land.lhs.true, label %if.end
376
377 land.lhs.true:                                    ; preds = %entry
378   %arrayidx = getelementptr inbounds i8** %argv, i64 1
379   %0 = load i8** %arrayidx, align 8
380   %cmp1 = icmp eq i8* %0, null
381   br i1 %cmp1, label %if.end, label %return
382
383 if.end:                                           ; preds = %land.lhs.true, %entry
384   %call = call i32 @zoo(i32 1)
385   %call2 = call double @yoo(i32 -1)
386   %cmp4 = icmp sgt i32 %call, 0
387   %add = zext i1 %cmp4 to i32
388   %cond = add nsw i32 %add, %call
389   %call7 = call i32 @xoo(i32 %cond, i32 2)
390   %cmp9 = fcmp ogt double %call2, 0.000000e+00
391   br i1 %cmp9, label %cond.end14, label %cond.false12
392
393 cond.false12:                                     ; preds = %if.end
394   %sub = fadd fast double %call2, -1.000000e+00
395   br label %cond.end14
396
397 cond.end14:                                       ; preds = %if.end, %cond.false12
398   %cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
399   %call16 = call i32 @woo(double %cond15, double -2.000000e+00)
400   br label %return
401
402 return:                                           ; preds = %land.lhs.true, %cond.end14
403   %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
404   ret i32 %retval.0
405 }
406
407 declare i32 @zoo(i32)
408
409 declare double @yoo(i32)
410
411 declare i32 @xoo(i32, i32)
412
413 declare i32 @woo(double, double)