1 ; RUN: opt -S -loop-sink < %s | FileCheck %s
2 ; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
4 @g = global i32 0, align 4
22 ; CHECK: load i32, i32* @g
24 ; CHECK-NOT: load i32, i32* @g
25 define i32 @t1(i32, i32) #0 !prof !0 {
26 %3 = icmp eq i32 %1, 0
27 br i1 %3, label %.exit, label %.preheader
30 %invariant = load i32, i32* @g
34 %iv = phi i32 [ %t7, %.b7 ], [ 0, %.preheader ]
35 %c1 = icmp sgt i32 %iv, %0
36 br i1 %c1, label %.b2, label %.b6, !prof !1
39 %c2 = icmp sgt i32 %iv, 1
40 br i1 %c2, label %.b3, label %.b4
43 %t3 = sub nsw i32 %invariant, %iv
47 %t4 = add nsw i32 %invariant, %iv
51 %p5 = phi i32 [ %t3, %.b3 ], [ %t4, %.b4 ]
52 %t5 = mul nsw i32 %p5, 5
56 %t6 = add nsw i32 %iv, 100
60 %p7 = phi i32 [ %t6, %.b6 ], [ %t5, %.b5 ]
61 %t7 = add nuw nsw i32 %iv, 1
62 %c7 = icmp eq i32 %t7, %p7
63 br i1 %c7, label %.b1, label %.exit, !prof !3
82 ; Sink load to b3 and b6
85 ; CHECK-NOT: load i32, i32* @g
87 ; CHECK: load i32, i32* @g
90 ; CHECK: load i32, i32* @g
92 define i32 @t2(i32, i32) #0 !prof !0 {
93 %3 = icmp eq i32 %1, 0
94 br i1 %3, label %.exit, label %.preheader
97 %invariant = load i32, i32* @g
101 %iv = phi i32 [ %t7, %.b7 ], [ 0, %.preheader ]
102 %c1 = icmp sgt i32 %iv, %0
103 br i1 %c1, label %.b2, label %.b6, !prof !2
106 %c2 = icmp sgt i32 %iv, 1
107 br i1 %c2, label %.b3, label %.b4, !prof !1
110 %t3 = sub nsw i32 %invariant, %iv
114 %t4 = add nsw i32 5, %iv
118 %p5 = phi i32 [ %t3, %.b3 ], [ %t4, %.b4 ]
119 %t5 = mul nsw i32 %p5, 5
123 %t6 = add nsw i32 %iv, %invariant
127 %p7 = phi i32 [ %t6, %.b6 ], [ %t5, %.b5 ]
128 %t7 = add nuw nsw i32 %iv, 1
129 %c7 = icmp eq i32 %t7, %p7
130 br i1 %c7, label %.b1, label %.exit, !prof !3
148 ; Do not sink load from preheader.
151 ; CHECK: load i32, i32* @g
153 ; CHECK-NOT: load i32, i32* @g
154 define i32 @t3(i32, i32) #0 !prof !0 {
155 %3 = icmp eq i32 %1, 0
156 br i1 %3, label %.exit, label %.preheader
159 %invariant = load i32, i32* @g
163 %iv = phi i32 [ %t7, %.b7 ], [ 0, %.preheader ]
164 %c1 = icmp sgt i32 %iv, %0
165 br i1 %c1, label %.b2, label %.b6, !prof !2
168 %c2 = icmp sgt i32 %iv, 1
169 br i1 %c2, label %.b3, label %.b4, !prof !1
172 %t3 = sub nsw i32 %invariant, %iv
176 %t4 = add nsw i32 5, %iv
180 %p5 = phi i32 [ %t3, %.b3 ], [ %t4, %.b4 ]
181 %t5 = mul nsw i32 %p5, %invariant
185 %t6 = add nsw i32 %iv, 5
189 %p7 = phi i32 [ %t6, %.b6 ], [ %t5, %.b5 ]
190 %t7 = add nuw nsw i32 %iv, 1
191 %c7 = icmp eq i32 %t7, %p7
192 br i1 %c7, label %.b1, label %.exit, !prof !3
198 ; For single-BB loop with <=1 avg trip count, sink load to b1
201 ; CHECK-NOT: load i32, i32* @g
203 ; CHECK: load i32, i32* @g
205 define i32 @t4(i32, i32) #0 !prof !0 {
207 %invariant = load i32, i32* @g
211 %iv = phi i32 [ %t1, %.b1 ], [ 0, %.preheader ]
212 %t1 = add nsw i32 %invariant, %iv
213 %c1 = icmp sgt i32 %iv, %0
214 br i1 %c1, label %.b1, label %.exit, !prof !1
233 ; There is alias store in loop, do not sink load
236 ; CHECK: load i32, i32* @g
238 ; CHECK-NOT: load i32, i32* @g
239 define i32 @t5(i32, i32*) #0 !prof !0 {
240 %3 = icmp eq i32 %0, 0
241 br i1 %3, label %.exit, label %.preheader
244 %invariant = load i32, i32* @g
248 %iv = phi i32 [ %t7, %.b7 ], [ 0, %.preheader ]
249 %c1 = icmp sgt i32 %iv, %0
250 br i1 %c1, label %.b2, label %.b6, !prof !1
253 %c2 = icmp sgt i32 %iv, 1
254 br i1 %c2, label %.b3, label %.b4
257 %t3 = sub nsw i32 %invariant, %iv
261 %t4 = add nsw i32 %invariant, %iv
265 %p5 = phi i32 [ %t3, %.b3 ], [ %t4, %.b4 ]
266 %t5 = mul nsw i32 %p5, 5
270 %t6 = call i32 @foo()
274 %p7 = phi i32 [ %t6, %.b6 ], [ %t5, %.b5 ]
275 %t7 = add nuw nsw i32 %iv, 1
276 %c7 = icmp eq i32 %t7, %p7
277 br i1 %c7, label %.b1, label %.exit, !prof !3
296 ; Regardless of aliasing store in loop this load from constant memory can be sunk.
297 ; CHECK: t5_const_memory
299 ; CHECK-NOT: load i32, i32* @g_const
301 ; CHECK: load i32, i32* @g_const
302 ; CHECK: br i1 %c2, label %.b3, label %.b4
303 define i32 @t5_const_memory(i32, i32*) #0 !prof !0 {
304 %3 = icmp eq i32 %0, 0
305 br i1 %3, label %.exit, label %.preheader
308 %invariant = load i32, i32* @g_const
312 %iv = phi i32 [ %t7, %.b7 ], [ 0, %.preheader ]
313 %c1 = icmp sgt i32 %iv, %0
314 br i1 %c1, label %.b2, label %.b6, !prof !1
317 %c2 = icmp sgt i32 %iv, 1
318 br i1 %c2, label %.b3, label %.b4
321 %t3 = sub nsw i32 %invariant, %iv
325 %t4 = add nsw i32 %invariant, %iv
329 %p5 = phi i32 [ %t3, %.b3 ], [ %t4, %.b4 ]
330 %t5 = mul nsw i32 %p5, 5
334 %t6 = call i32 @foo()
338 %p7 = phi i32 [ %t6, %.b6 ], [ %t5, %.b5 ]
339 %t7 = add nuw nsw i32 %iv, 1
340 %c7 = icmp eq i32 %t7, %p7
341 br i1 %c7, label %.b1, label %.exit, !prof !3
355 ; Do not sink unordered atomic load to b2
358 ; CHECK: load atomic i32, i32* @g unordered, align 4
360 ; CHECK-NOT: load atomic i32, i32* @g unordered, align 4
361 define i32 @t6(i32, i32) #0 !prof !0 {
362 %3 = icmp eq i32 %1, 0
363 br i1 %3, label %.exit, label %.preheader
366 %invariant = load atomic i32, i32* @g unordered, align 4
370 %iv = phi i32 [ %t3, %.b4 ], [ 0, %.preheader ]
371 %c1 = icmp sgt i32 %iv, %0
372 br i1 %c1, label %.b2, label %.b3, !prof !1
375 %t1 = add nsw i32 %invariant, %iv
379 %t2 = add nsw i32 %iv, 100
383 %p1 = phi i32 [ %t2, %.b3 ], [ %t1, %.b2 ]
384 %t3 = add nuw nsw i32 %iv, 1
385 %c2 = icmp eq i32 %t3, %p1
386 br i1 %c2, label %.b1, label %.exit, !prof !3
392 @g_const = constant i32 0, align 4
402 ; Sink unordered atomic load to b2. It is allowed to sink into loop unordered
403 ; load from constant.
406 ; CHECK-NOT: load atomic i32, i32* @g_const unordered, align 4
408 ; CHECK: load atomic i32, i32* @g_const unordered, align 4
409 define i32 @t7(i32, i32) #0 !prof !0 {
410 %3 = icmp eq i32 %1, 0
411 br i1 %3, label %.exit, label %.preheader
414 %invariant = load atomic i32, i32* @g_const unordered, align 4
418 %iv = phi i32 [ %t3, %.b4 ], [ 0, %.preheader ]
419 %c1 = icmp sgt i32 %iv, %0
420 br i1 %c1, label %.b2, label %.b3, !prof !1
423 %t1 = add nsw i32 %invariant, %iv
427 %t2 = add nsw i32 %iv, 100
431 %p1 = phi i32 [ %t2, %.b3 ], [ %t1, %.b2 ]
432 %t3 = add nuw nsw i32 %iv, 1
433 %c2 = icmp eq i32 %t3, %p1
434 br i1 %c2, label %.b1, label %.exit, !prof !3
442 !0 = !{!"function_entry_count", i64 1}
443 !1 = !{!"branch_weights", i32 1, i32 2000}
444 !2 = !{!"branch_weights", i32 2000, i32 1}
445 !3 = !{!"branch_weights", i32 100, i32 1}