1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
3 ; RUN: opt -licm -basicaa -ipt-expensive-asserts=true < %s -S | FileCheck %s
4 ; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s
6 ; Hoist guard and load.
7 define void @test1(i1 %cond, i32* %ptr) {
10 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
11 ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR:%.*]]
12 ; CHECK-NEXT: br label [[LOOP:%.*]]
14 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
15 ; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
16 ; CHECK-NEXT: br label [[LOOP]]
23 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
24 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
25 %val = load i32, i32* %ptr
26 %x.inc = add i32 %x, %val
30 ; Can't hoist over a side effect
31 define void @test2(i1 %cond, i32* %ptr) {
32 ; CHECK-LABEL: @test2(
34 ; CHECK-NEXT: br label [[LOOP:%.*]]
36 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
37 ; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]]
38 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
39 ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR]]
40 ; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
41 ; CHECK-NEXT: br label [[LOOP]]
48 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
49 store i32 0, i32* %ptr
50 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
51 %val = load i32, i32* %ptr
52 %x.inc = add i32 %x, %val
56 ; Can't hoist over a side effect
57 define void @test2b(i1 %cond, i32* %ptr) {
58 ; CHECK-LABEL: @test2b(
60 ; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 1
61 ; CHECK-NEXT: br label [[LOOP:%.*]]
63 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
64 ; CHECK-NEXT: store i32 0, i32* [[P2]]
65 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
66 ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR]]
67 ; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
68 ; CHECK-NEXT: br label [[LOOP]]
75 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
76 %p2 = getelementptr i32, i32* %ptr, i32 1
78 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
79 %val = load i32, i32* %ptr
80 %x.inc = add i32 %x, %val
84 ; Hoist guard. Cannot hoist load because of aliasing.
85 define void @test3(i1 %cond, i32* %ptr) {
86 ; CHECK-LABEL: @test3(
88 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
89 ; CHECK-NEXT: br label [[LOOP:%.*]]
91 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
92 ; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR:%.*]]
93 ; CHECK-NEXT: store i32 0, i32* [[PTR]]
94 ; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
95 ; CHECK-NEXT: br label [[LOOP]]
102 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
103 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
104 %val = load i32, i32* %ptr
105 store i32 0, i32* %ptr
106 %x.inc = add i32 %x, %val
110 ; Hoist load and guard.
111 define void @test4(i1 %c, i32* %p) {
112 ; CHECK-LABEL: @test4(
114 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
115 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
116 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
117 ; CHECK-NEXT: br label [[LOOP:%.*]]
119 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
120 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
121 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
123 ; CHECK-NEXT: br label [[BACKEDGE]]
125 ; CHECK-NEXT: br label [[BACKEDGE]]
127 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
128 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
130 ; CHECK-NEXT: ret void
137 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
138 %iv.next = add i32 %iv, 1
139 br i1 %c, label %if.true, label %if.false
148 %a = load i32, i32* %p
149 %invariant_cond = icmp ne i32 %a, 100
150 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
151 %loop_cond = icmp slt i32 %iv.next, 1000
152 br i1 %loop_cond, label %loop, label %exit
158 ; Do not hoist across a conditionally executed side effect.
159 define void @test4a(i1 %c, i32* %p, i32* %q) {
160 ; CHECK-LABEL: @test4a(
162 ; CHECK-NEXT: br label [[LOOP:%.*]]
164 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
165 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
166 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
168 ; CHECK-NEXT: store i32 123, i32* [[Q:%.*]]
169 ; CHECK-NEXT: br label [[BACKEDGE]]
171 ; CHECK-NEXT: br label [[BACKEDGE]]
173 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
174 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
175 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
176 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
177 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
179 ; CHECK-NEXT: ret void
186 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
187 %iv.next = add i32 %iv, 1
188 br i1 %c, label %if.true, label %if.false
191 store i32 123, i32* %q
198 %a = load i32, i32* %p
199 %invariant_cond = icmp ne i32 %a, 100
200 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
201 %loop_cond = icmp slt i32 %iv.next, 1000
202 br i1 %loop_cond, label %loop, label %exit
208 ; Do not hoist a conditionally executed guard.
209 define void @test4b(i1 %c, i32* %p, i32* %q) {
210 ; CHECK-LABEL: @test4b(
212 ; CHECK-NEXT: br label [[LOOP:%.*]]
214 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
215 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
216 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
218 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
219 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
220 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
221 ; CHECK-NEXT: br label [[BACKEDGE]]
223 ; CHECK-NEXT: br label [[BACKEDGE]]
225 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
226 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
228 ; CHECK-NEXT: ret void
235 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
236 %iv.next = add i32 %iv, 1
237 br i1 %c, label %if.true, label %if.false
240 %a = load i32, i32* %p
241 %invariant_cond = icmp ne i32 %a, 100
242 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
249 %loop_cond = icmp slt i32 %iv.next, 1000
250 br i1 %loop_cond, label %loop, label %exit
256 ; Hoist store, load and guard.
257 define void @test4c(i1 %c, i32* %p, i8* noalias %s) {
258 ; CHECK-LABEL: @test4c(
260 ; CHECK-NEXT: store i8 0, i8* [[S:%.*]]
261 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
262 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
263 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
264 ; CHECK-NEXT: br label [[LOOP:%.*]]
266 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
267 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
268 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
270 ; CHECK-NEXT: br label [[BACKEDGE]]
272 ; CHECK-NEXT: br label [[BACKEDGE]]
274 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
275 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
277 ; CHECK-NEXT: ret void
284 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
285 %iv.next = add i32 %iv, 1
287 br i1 %c, label %if.true, label %if.false
296 %a = load i32, i32* %p
297 %invariant_cond = icmp ne i32 %a, 100
298 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
299 %loop_cond = icmp slt i32 %iv.next, 1000
300 br i1 %loop_cond, label %loop, label %exit
306 ; Check that we don't hoist across a store in a conditionally executed block.
307 define void @test4d(i1 %c, i32* %p, i8* noalias %s) {
308 ; CHECK-LABEL: @test4d(
310 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
311 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
312 ; CHECK-NEXT: br label [[LOOP:%.*]]
314 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
315 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
316 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
318 ; CHECK-NEXT: store i8 0, i8* [[S:%.*]]
319 ; CHECK-NEXT: br label [[BACKEDGE]]
321 ; CHECK-NEXT: br label [[BACKEDGE]]
323 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
324 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
325 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
327 ; CHECK-NEXT: ret void
334 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
335 %iv.next = add i32 %iv, 1
336 br i1 %c, label %if.true, label %if.false
346 %a = load i32, i32* %p
347 %invariant_cond = icmp ne i32 %a, 100
348 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
349 %loop_cond = icmp slt i32 %iv.next, 1000
350 br i1 %loop_cond, label %loop, label %exit
356 ; Check that we don't hoist across a store before the guard in the backedge.
357 define void @test4e(i1 %c, i32* %p, i8* noalias %s) {
358 ; CHECK-LABEL: @test4e(
360 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
361 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
362 ; CHECK-NEXT: store i8 0, i8* [[S:%.*]]
363 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
364 ; CHECK-NEXT: br label [[LOOP:%.*]]
366 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
367 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
368 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
370 ; CHECK-NEXT: br label [[BACKEDGE]]
372 ; CHECK-NEXT: br label [[BACKEDGE]]
374 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
375 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
377 ; CHECK-NEXT: ret void
384 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
385 %iv.next = add i32 %iv, 1
386 br i1 %c, label %if.true, label %if.false
395 %a = load i32, i32* %p
396 %invariant_cond = icmp ne i32 %a, 100
398 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
399 %loop_cond = icmp slt i32 %iv.next, 1000
400 br i1 %loop_cond, label %loop, label %exit
406 ; Check that we can hoist the guard in spite of store which happens after.
407 define void @test4f(i1 %c, i32* %p, i8* noalias %s) {
408 ; CHECK-LABEL: @test4f(
410 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
411 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
412 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
413 ; CHECK-NEXT: store i8 0, i8* [[S:%.*]]
414 ; CHECK-NEXT: br label [[LOOP:%.*]]
416 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
417 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
418 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
420 ; CHECK-NEXT: br label [[BACKEDGE]]
422 ; CHECK-NEXT: br label [[BACKEDGE]]
424 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
425 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
427 ; CHECK-NEXT: ret void
434 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
435 %iv.next = add i32 %iv, 1
436 br i1 %c, label %if.true, label %if.false
445 %a = load i32, i32* %p
446 %invariant_cond = icmp ne i32 %a, 100
447 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
449 %loop_cond = icmp slt i32 %iv.next, 1000
450 br i1 %loop_cond, label %loop, label %exit
456 ; Do not hoist an invariant guard across a variant guard.
457 define void @test5(i1 %c, i32* %p, i32* %q) {
458 ; CHECK-LABEL: @test5(
460 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
461 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
462 ; CHECK-NEXT: br label [[LOOP:%.*]]
464 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
465 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
466 ; CHECK-NEXT: [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]]
467 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ]
468 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
469 ; CHECK-NEXT: br label [[BACKEDGE]]
471 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
472 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
474 ; CHECK-NEXT: ret void
481 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
482 %iv.next = add i32 %iv, 1
483 %a = load i32, i32* %p
484 %invariant_cond = icmp ne i32 %a, 100
485 %variant_cond = icmp ne i32 %a, %iv
486 call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ]
487 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
491 %loop_cond = icmp slt i32 %iv.next, 1000
492 br i1 %loop_cond, label %loop, label %exit
498 ; Hoist an invariant guard, leave the following variant guard in the loop.
499 define void @test5a(i1 %c, i32* %p, i32* %q) {
500 ; CHECK-LABEL: @test5a(
502 ; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P:%.*]]
503 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
504 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
505 ; CHECK-NEXT: br label [[LOOP:%.*]]
507 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
508 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
509 ; CHECK-NEXT: [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]]
510 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ]
511 ; CHECK-NEXT: br label [[BACKEDGE]]
513 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
514 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
516 ; CHECK-NEXT: ret void
523 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
524 %iv.next = add i32 %iv, 1
525 %a = load i32, i32* %p
526 %invariant_cond = icmp ne i32 %a, 100
527 %variant_cond = icmp ne i32 %a, %iv
528 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
529 call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ]
533 %loop_cond = icmp slt i32 %iv.next, 1000
534 br i1 %loop_cond, label %loop, label %exit
540 declare void @llvm.experimental.guard(i1, ...)