1 ; RUN: opt < %s -basic-aa -tbaa -licm -S | FileCheck %s
2 ; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(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) {
10 ; CHECK-LABEL: @test1(
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
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) {
37 ; CHECK-LABEL: @test2(
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
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(
64 ; Should not promote this to a register
65 %x = load volatile i32, i32* @X
67 store i32 %x2, i32* @X
68 br i1 true, label %Out, label %Loop
71 ; CHECK-NEXT: load volatile
77 define void @test3b(i32 %i) {
78 ; CHECK-LABEL: @test3b(
80 ; CHECK: store volatile
84 ; Should not promote this to a register
85 %x = load i32, i32* @X
87 store volatile i32 %x2, i32* @X
88 br i1 true, label %Out, label %Loop
95 define void @test4(i8* %x, i8 %n) {
96 ; CHECK-LABEL: @test4(
99 store i8* %x, i8** %handle1
103 %tmp = getelementptr i8, i8* %x, i64 8
104 store i8* %tmp, i8** %handle2
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.
119 ; CHECK-NEXT: phi i8* [
120 ; CHECK-NEXT: %count = phi i8 [
121 ; CHECK-NEXT: store i8 %n
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.
133 ; CHECK: %val = load i8, i8* %offsetx1
134 ; CHECK: %cond = icmp eq i8 %val, %n
135 ; CHECK: br i1 %cond, label %exit, label %loop
141 define void @test5(i32 %i, i32** noalias %P2) {
144 ; CHECK-LABEL: @test5(
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
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) {
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
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
196 for.end: ; preds = %for.cond.for.end_crit_edge, %entry
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(
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
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
224 call void @capture(i32* %local)
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
237 %ret = load i32, i32* %local
241 ; Make sure we don't promote if the store is really control-flow dependent.
242 define i32 @test7bad() {
243 ; CHECK-LABEL: @test7bad(
245 ; CHECK-NEXT: %local = alloca
246 ; CHECK-NEXT: call void @capture(i32* %local)
247 ; CHECK-NEXT: br label %loop
249 ; CHECK-NEXT: store i32 %x2, i32* %local
250 ; CHECK-NEXT: br label %else
252 ; CHECK-NEXT: %ret = load i32, i32* %local
253 ; CHECK-NEXT: ret i32 %ret
256 call void @capture(i32* %local)
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
266 store i32 %x2, i32* %local
270 %next = add i32 %j, 1
271 %cond = icmp eq i32 %next, 0
272 br i1 %cond, label %exit, label %loop
275 %ret = load i32, i32* %local
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(
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
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
296 call void @capture(i32* %local)
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
310 %ret = load i32, i32* %local
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
318 define i32 @test9() {
319 ; CHECK-LABEL: @test9(
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
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
332 call void @capture(i32* %local)
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
342 %x = load i32, i32* %local
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
353 %ret = load i32, i32* %local
357 define i32 @test9bad(i32 %i) {
358 ; CHECK-LABEL: @test9bad(
360 ; CHECK-NEXT: %local = alloca
361 ; CHECK-NEXT: call void @capture(i32* %local)
362 ; CHECK-NEXT: %notderef = getelementptr
363 ; CHECK-NEXT: br label %loop
365 ; CHECK-NEXT: load i32, i32* %notderef
366 ; CHECK-NEXT: br label %else
368 ; CHECK-NEXT: %ret = load i32, i32* %notderef
369 ; CHECK-NEXT: ret i32 %ret
372 call void @capture(i32* %local)
373 %notderef = getelementptr i32, i32* %local, i32 %i
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
383 %x = load i32, i32* %notderef
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
394 %ret = load i32, i32* %notderef
398 define void @test10(i32 %i) {
401 ; CHECK-LABEL: @test10(
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
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
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) {
430 ; CHECK-LABEL: @test11(
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
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
450 ; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %x2
451 ; CHECK-NEXT: store i32 %[[LCSSAPHI]], i32* @X
452 ; CHECK-NEXT: ret void
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}