[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / AArch64 / combine-comparisons-by-cse.ll
blob86be3ccea1d80f7a7cdeb855dc48a22d49ec9ac8
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
12 ; CHECK: cmp
13 ; CHECK: b.le
14 ; CHECK: ret
15 ; CHECK-NOT: cmp
16 ; CHECK: b.lt
17 entry:
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
39   br label %return
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
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, 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
76   br label %return
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
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, 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
113   br label %return
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
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, 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
150   br label %return
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
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, 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
187   br label %return
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
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, 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
224   br label %return
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
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 {
239 entry:
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
244 land.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
250 while.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
257 while.end:
258   ret void
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
266 ; CHECK: cmn
267 ; CHECK: b.gt
268 ; CHECK: cmp
269 ; CHECK: b.gt
270 entry:
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
276   br label %while.body
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
287   br label %while.end
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
301   br label %return
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
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, 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
320   br label %while.body
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
330   br label %while.end
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
344   br label %return
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
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
358 define i32 @fcmpri(i32 %argc, i8** nocapture readonly %argv) {
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
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
372 entry:
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
394   br label %cond.end14
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)
399   br label %return
401 return:                                           ; preds = %land.lhs.true, %cond.end14
402   %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
403   ret i32 %retval.0
406 define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) {
407 ; CHECK-LABEL: cmp_shifted:
408 ; CHECK: cmp w0, #2, lsl #12
409 ; [...]
410 ; CHECK: cmp w0, #1
412   %tst_low = icmp sgt i32 %in, 8191
413   br i1 %tst_low, label %true, label %false
415 true:
416   call i32 @zoo(i32 128)
417   ret void
419 false:
420   %tst = icmp sgt i32 %in, 0
421   br i1 %tst, label %truer, label %falser
423 truer:
424   call i32 @zoo(i32 42)
425   ret void
427 falser:
428   call i32 @zoo(i32 1)
429   ret void
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
437 entry:
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
461   br label %return
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 ]
465   ret i32 %retval.0
468 declare i32 @zoo(i32)
470 declare double @yoo(i32)
472 declare i32 @xoo(i32, i32)
474 declare i32 @woo(double, double)