[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / LICM / scalar-promote.ll
blobb719c1e6cb46f52e3cd1ec6c384976257b3e1edc
1 ; RUN: opt < %s -basicaa -tbaa -licm -S | FileCheck %s
2 ; RUN: opt -aa-pipeline=type-based-aa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
3 target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
5 @X = global i32 7   ; <i32*> [#uses=4]
7 define void @test1(i32 %i) {
8 Entry:
9   br label %Loop
10 ; CHECK-LABEL: @test1(
11 ; CHECK: Entry:
12 ; CHECK-NEXT:   load i32, i32* @X
13 ; CHECK-NEXT:   br label %Loop
16 Loop:   ; preds = %Loop, %0
17   %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ]    ; <i32> [#uses=1]
18   %x = load i32, i32* @X   ; <i32> [#uses=1]
19   %x2 = add i32 %x, 1   ; <i32> [#uses=1]
20   store i32 %x2, i32* @X
21   %Next = add i32 %j, 1   ; <i32> [#uses=2]
22   %cond = icmp eq i32 %Next, 0    ; <i1> [#uses=1]
23   br i1 %cond, label %Out, label %Loop
25 Out:
26   ret void
27 ; CHECK: Out:
28 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %x2
29 ; CHECK-NEXT:   store i32 %[[LCSSAPHI]], i32* @X
30 ; CHECK-NEXT:   ret void
34 define void @test2(i32 %i) {
35 Entry:
36   br label %Loop
37 ; CHECK-LABEL: @test2(
38 ; CHECK: Entry:
39 ; CHECK-NEXT:    %.promoted = load i32, i32* getelementptr inbounds (i32, i32* @X, i64 1)
40 ; CHECK-NEXT:    br label %Loop
42 Loop:   ; preds = %Loop, %0
43   %X1 = getelementptr i32, i32* @X, i64 1    ; <i32*> [#uses=1]
44   %A = load i32, i32* %X1    ; <i32> [#uses=1]
45   %V = add i32 %A, 1    ; <i32> [#uses=1]
46   %X2 = getelementptr i32, i32* @X, i64 1    ; <i32*> [#uses=1]
47   store i32 %V, i32* %X2
48   br i1 false, label %Loop, label %Exit
50 Exit:   ; preds = %Loop
51   ret void
52 ; CHECK: Exit:
53 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %V
54 ; CHECK-NEXT:   store i32 %[[LCSSAPHI]], i32* getelementptr inbounds (i32, i32* @X, i64 1)
55 ; CHECK-NEXT:   ret void
60 define void @test3(i32 %i) {
61 ; CHECK-LABEL: @test3(
62   br label %Loop
63 Loop:
64         ; Should not promote this to a register
65   %x = load volatile i32, i32* @X
66   %x2 = add i32 %x, 1
67   store i32 %x2, i32* @X
68   br i1 true, label %Out, label %Loop
70 ; CHECK: Loop:
71 ; CHECK-NEXT: load volatile
73 Out:    ; preds = %Loop
74   ret void
77 define void @test3b(i32 %i) {
78 ; CHECK-LABEL: @test3b(
79 ; CHECK-LABEL: Loop:
80 ; CHECK: store volatile
81 ; CHECK-LABEL: Out:
82   br label %Loop
83 Loop:
84         ; Should not promote this to a register
85   %x = load i32, i32* @X
86   %x2 = add i32 %x, 1
87   store volatile i32 %x2, i32* @X
88   br i1 true, label %Out, label %Loop
90 Out:    ; preds = %Loop
91   ret void
94 ; PR8041
95 define void @test4(i8* %x, i8 %n) {
96 ; CHECK-LABEL: @test4(
97   %handle1 = alloca i8*
98   %handle2 = alloca i8*
99   store i8* %x, i8** %handle1
100   br label %loop
102 loop:
103   %tmp = getelementptr i8, i8* %x, i64 8
104   store i8* %tmp, i8** %handle2
105   br label %subloop
107 subloop:
108   %count = phi i8 [ 0, %loop ], [ %nextcount, %subloop ]
109   %offsetx2 = load i8*, i8** %handle2
110   store i8 %n, i8* %offsetx2
111   %newoffsetx2 = getelementptr i8, i8* %offsetx2, i64 -1
112   store i8* %newoffsetx2, i8** %handle2
113   %nextcount = add i8 %count, 1
114   %innerexitcond = icmp sge i8 %nextcount, 8
115   br i1 %innerexitcond, label %innerexit, label %subloop
117 ; Should have promoted 'handle2' accesses.
118 ; CHECK: subloop:
119 ; CHECK-NEXT: phi i8* [
120 ; CHECK-NEXT: %count = phi i8 [
121 ; CHECK-NEXT: store i8 %n
122 ; CHECK-NOT: store
123 ; CHECK: br i1
125 innerexit:
126   %offsetx1 = load i8*, i8** %handle1
127   %val = load i8, i8* %offsetx1
128   %cond = icmp eq i8 %val, %n
129   br i1 %cond, label %exit, label %loop
131 ; Should not have promoted offsetx1 loads.
132 ; CHECK: innerexit:
133 ; CHECK: %val = load i8, i8* %offsetx1
134 ; CHECK: %cond = icmp eq i8 %val, %n
135 ; CHECK: br i1 %cond, label %exit, label %loop
137 exit:
138   ret void
141 define void @test5(i32 %i, i32** noalias %P2) {
142 Entry:
143   br label %Loop
144 ; CHECK-LABEL: @test5(
145 ; CHECK: Entry:
146 ; CHECK-NEXT:   load i32, i32* @X
147 ; CHECK-NEXT:   br label %Loop
150 Loop:   ; preds = %Loop, %0
151   %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ]    ; <i32> [#uses=1]
152   %x = load i32, i32* @X   ; <i32> [#uses=1]
153   %x2 = add i32 %x, 1   ; <i32> [#uses=1]
154   store i32 %x2, i32* @X
156         store atomic i32* @X, i32** %P2 monotonic, align 8
158   %Next = add i32 %j, 1   ; <i32> [#uses=2]
159   %cond = icmp eq i32 %Next, 0    ; <i1> [#uses=1]
160   br i1 %cond, label %Out, label %Loop
162 Out:
163   ret void
164 ; CHECK: Out:
165 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %x2
166 ; CHECK-NEXT:   store i32 %[[LCSSAPHI]], i32* @X
167 ; CHECK-NEXT:   ret void
172 ; PR14753 - Preserve TBAA tags when promoting values in a loop.
173 define void @test6(i32 %n, float* nocapture %a, i32* %gi) {
174 entry:
175   store i32 0, i32* %gi, align 4, !tbaa !0
176   %cmp1 = icmp slt i32 0, %n
177   br i1 %cmp1, label %for.body.lr.ph, label %for.end
179 for.body.lr.ph:                                   ; preds = %entry
180   br label %for.body
182 for.body:                                         ; preds = %for.body.lr.ph, %for.body
183   %storemerge2 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
184   %idxprom = sext i32 %storemerge2 to i64
185   %arrayidx = getelementptr inbounds float, float* %a, i64 %idxprom
186   store float 0.000000e+00, float* %arrayidx, align 4, !tbaa !3
187   %0 = load i32, i32* %gi, align 4, !tbaa !0
188   %inc = add nsw i32 %0, 1
189   store i32 %inc, i32* %gi, align 4, !tbaa !0
190   %cmp = icmp slt i32 %inc, %n
191   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
193 for.cond.for.end_crit_edge:                       ; preds = %for.body
194   br label %for.end
196 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
197   ret void
199 ; CHECK: for.body.lr.ph:
200 ; CHECK-NEXT:  %gi.promoted = load i32, i32* %gi, align 4, !tbaa !0
201 ; CHECK: for.cond.for.end_crit_edge:
202 ; CHECK-NEXT:  %[[LCSSAPHI:.*]] = phi i32 [ %inc
203 ; CHECK-NEXT:  store i32 %[[LCSSAPHI]], i32* %gi, align 4, !tbaa !0
206 declare i32 @opaque(i32) argmemonly
207 declare void @capture(i32*)
209 ; We can promote even if opaque may throw.
210 define i32 @test7() {
211 ; CHECK-LABEL: @test7(
212 ; CHECK: entry:
213 ; CHECK-NEXT: %local = alloca
214 ; CHECK-NEXT: call void @capture(i32* %local)
215 ; CHECK-NEXT: load i32, i32* %local
216 ; CHECK-NEXT: br label %loop
217 ; CHECK: exit:
218 ; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %x2, %loop ]
219 ; CHECK-NEXT: store i32 %[[LCSSAPHI]], i32* %local
220 ; CHECK-NEXT: %ret = load i32, i32* %local
221 ; CHECK-NEXT: ret i32 %ret
222 entry:
223   %local = alloca i32
224   call void @capture(i32* %local)
225   br label %loop
227 loop:
228   %j = phi i32 [ 0, %entry ], [ %next, %loop ]
229   %x = load i32, i32* %local
230   %x2 = call i32 @opaque(i32 %x) ; Note this does not capture %local
231   store i32 %x2, i32* %local
232   %next = add i32 %j, 1
233   %cond = icmp eq i32 %next, 0
234   br i1 %cond, label %exit, label %loop
236 exit:
237   %ret = load i32, i32* %local
238   ret i32 %ret
241 ; Make sure we don't promote if the store is really control-flow dependent.
242 define i32 @test7bad() {
243 ; CHECK-LABEL: @test7bad(
244 ; CHECK: entry:
245 ; CHECK-NEXT: %local = alloca
246 ; CHECK-NEXT: call void @capture(i32* %local)
247 ; CHECK-NEXT: br label %loop
248 ; CHECK: if:
249 ; CHECK-NEXT: store i32 %x2, i32* %local
250 ; CHECK-NEXT: br label %else
251 ; CHECK: exit:
252 ; CHECK-NEXT: %ret = load i32, i32* %local
253 ; CHECK-NEXT: ret i32 %ret
254 entry:
255   %local = alloca i32
256   call void @capture(i32* %local)  
257   br label %loop
258 loop:
259   %j = phi i32 [ 0, %entry ], [ %next, %else ]
260   %x = load i32, i32* %local
261   %x2 = call i32 @opaque(i32 %x) ; Note this does not capture %local
262   %cmp = icmp eq i32 %x2, 0
263   br i1 %cmp, label %if, label %else
265 if:  
266   store i32 %x2, i32* %local
267   br label %else
269 else:
270   %next = add i32 %j, 1
271   %cond = icmp eq i32 %next, 0
272   br i1 %cond, label %exit, label %loop
274 exit:
275   %ret = load i32, i32* %local
276   ret i32 %ret
279 ; Even if neither the load nor the store or guaranteed to execute because
280 ; opaque() may throw, we can still promote - the load not being guaranteed
281 ; doesn't block us, because %local is always dereferenceable.
282 define i32 @test8() {
283 ; CHECK-LABEL: @test8(
284 ; CHECK: entry:
285 ; CHECK-NEXT: %local = alloca
286 ; CHECK-NEXT: call void @capture(i32* %local)
287 ; CHECK-NEXT: load i32, i32* %local
288 ; CHECK-NEXT: br label %loop
289 ; CHECK: exit:
290 ; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %x2, %loop ]
291 ; CHECK-NEXT: store i32 %[[LCSSAPHI]], i32* %local
292 ; CHECK-NEXT: %ret = load i32, i32* %local
293 ; CHECK-NEXT: ret i32 %ret
294 entry:
295   %local = alloca i32
296   call void @capture(i32* %local)  
297   br label %loop
299 loop:
300   %j = phi i32 [ 0, %entry ], [ %next, %loop ]
301   %throwaway = call i32 @opaque(i32 %j)
302   %x = load i32, i32* %local  
303   %x2 = call i32 @opaque(i32 %x)
304   store i32 %x2, i32* %local
305   %next = add i32 %j, 1
306   %cond = icmp eq i32 %next, 0
307   br i1 %cond, label %exit, label %loop
309 exit:
310   %ret = load i32, i32* %local
311   ret i32 %ret
315 ; If the store is "guaranteed modulo exceptions", and the load depends on
316 ; control flow, we can only promote if the pointer is otherwise known to be
317 ; dereferenceable
318 define i32 @test9() {
319 ; CHECK-LABEL: @test9(
320 ; CHECK: entry:
321 ; CHECK-NEXT: %local = alloca
322 ; CHECK-NEXT: call void @capture(i32* %local)
323 ; CHECK-NEXT: load i32, i32* %local
324 ; CHECK-NEXT: br label %loop
325 ; CHECK: exit:
326 ; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %x2, %else ]
327 ; CHECK-NEXT: store i32 %[[LCSSAPHI]], i32* %local
328 ; CHECK-NEXT: %ret = load i32, i32* %local
329 ; CHECK-NEXT: ret i32 %ret
330 entry:
331   %local = alloca i32
332   call void @capture(i32* %local)  
333   br label %loop
335 loop:
336   %j = phi i32 [ 0, %entry ], [ %next, %else ]  
337   %j2 = call i32 @opaque(i32 %j)
338   %cmp = icmp eq i32 %j2, 0
339   br i1 %cmp, label %if, label %else
341 if:  
342   %x = load i32, i32* %local
343   br label %else
345 else:
346   %x2 = phi i32 [ 0, %loop ], [ %x, %if]
347   store i32 %x2, i32* %local
348   %next = add i32 %j, 1
349   %cond = icmp eq i32 %next, 0
350   br i1 %cond, label %exit, label %loop
352 exit:
353   %ret = load i32, i32* %local
354   ret i32 %ret
357 define i32 @test9bad(i32 %i) {
358 ; CHECK-LABEL: @test9bad(
359 ; CHECK: entry:
360 ; CHECK-NEXT: %local = alloca
361 ; CHECK-NEXT: call void @capture(i32* %local)
362 ; CHECK-NEXT: %notderef = getelementptr
363 ; CHECK-NEXT: br label %loop
364 ; CHECK: if:
365 ; CHECK-NEXT: load i32, i32* %notderef
366 ; CHECK-NEXT: br label %else
367 ; CHECK: exit:
368 ; CHECK-NEXT: %ret = load i32, i32* %notderef
369 ; CHECK-NEXT: ret i32 %ret
370 entry:
371   %local = alloca i32
372   call void @capture(i32* %local)  
373   %notderef = getelementptr i32, i32* %local, i32 %i
374   br label %loop
376 loop:
377   %j = phi i32 [ 0, %entry ], [ %next, %else ]  
378   %j2 = call i32 @opaque(i32 %j)
379   %cmp = icmp eq i32 %j2, 0
380   br i1 %cmp, label %if, label %else
382 if:  
383   %x = load i32, i32* %notderef
384   br label %else
386 else:
387   %x2 = phi i32 [ 0, %loop ], [ %x, %if]
388   store i32 %x2, i32* %notderef
389   %next = add i32 %j, 1
390   %cond = icmp eq i32 %next, 0
391   br i1 %cond, label %exit, label %loop
393 exit:
394   %ret = load i32, i32* %notderef
395   ret i32 %ret
398 define void @test10(i32 %i) {
399 Entry:
400   br label %Loop
401 ; CHECK-LABEL: @test10(
402 ; CHECK: Entry:
403 ; CHECK-NEXT:   load atomic i32, i32* @X unordered, align 4
404 ; CHECK-NEXT:   br label %Loop
407 Loop:   ; preds = %Loop, %0
408   %j = phi i32 [ 0, %Entry ], [ %Next, %Loop ]    ; <i32> [#uses=1]
409   %x = load atomic i32, i32* @X unordered, align 4
410   %x2 = add i32 %x, 1
411   store atomic i32 %x2, i32* @X unordered, align 4
412   %Next = add i32 %j, 1
413   %cond = icmp eq i32 %Next, 0
414   br i1 %cond, label %Out, label %Loop
416 Out:
417   ret void
418 ; CHECK: Out:
419 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %x2
420 ; CHECK-NEXT:   store atomic i32 %[[LCSSAPHI]], i32* @X unordered, align 4
421 ; CHECK-NEXT:   ret void
425 ; Early exit is known not to be taken on first iteration and thus doesn't
426 ; effect whether load is known to execute.
427 define void @test11(i32 %i) {
428 Entry:
429   br label %Loop
430 ; CHECK-LABEL: @test11(
431 ; CHECK: Entry:
432 ; CHECK-NEXT:   load i32, i32* @X
433 ; CHECK-NEXT:   br label %Loop
436 Loop:   ; preds = %Loop, %0
437   %j = phi i32 [ 0, %Entry ], [ %Next, %body ]    ; <i32> [#uses=1]
438   %early.test = icmp ult i32 %j, 32
439   br i1 %early.test, label %body, label %Early
440 body:
441   %x = load i32, i32* @X   ; <i32> [#uses=1]
442   %x2 = add i32 %x, 1   ; <i32> [#uses=1]
443   store i32 %x2, i32* @X
444   %Next = add i32 %j, 1   ; <i32> [#uses=2]
445   %cond = icmp eq i32 %Next, 0    ; <i1> [#uses=1]
446   br i1 %cond, label %Out, label %Loop
448 Early:
449 ; CHECK: Early:
450 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %x2
451 ; CHECK-NEXT:   store i32 %[[LCSSAPHI]], i32* @X
452 ; CHECK-NEXT:   ret void
453   ret void
454 Out:
455   ret void
456 ; CHECK: Out:
457 ; CHECK-NEXT:   %[[LCSSAPHI:.*]] = phi i32 [ %x2
458 ; CHECK-NEXT:   store i32 %[[LCSSAPHI]], i32* @X
459 ; CHECK-NEXT:   ret void
463 !0 = !{!4, !4, i64 0}
464 !1 = !{!"omnipotent char", !2}
465 !2 = !{!"Simple C/C++ TBAA"}
466 !3 = !{!5, !5, i64 0}
467 !4 = !{!"int", !1}
468 !5 = !{!"float", !1}