1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -basic-aa -enable-load-pre -enable-pre -lcssa -gvn -S < %s | FileCheck %s
4 declare void @side_effect() nofree
5 declare i1 @side_effect_cond() nofree
6 declare void @may_free_memory()
8 declare i32 @personality_function()
10 ; We can PRE the load from gc-managed memory away from the hot path.
11 define i32 @test_load_on_cold_path_gc(i32 addrspace(1)* %p) gc "statepoint-example" personality i32 ()* @"personality_function" {
12 ; CHECK-LABEL: @test_load_on_cold_path_gc(
14 ; CHECK-NEXT: [[X_PRE1:%.*]] = load i32, i32 addrspace(1)* [[P:%.*]], align 4
15 ; CHECK-NEXT: br label [[LOOP:%.*]]
17 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[X_PRE1]], [[ENTRY:%.*]] ], [ [[X2:%.*]], [[BACKEDGE:%.*]] ]
18 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE]] ]
19 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
20 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
22 ; CHECK-NEXT: br label [[BACKEDGE]]
24 ; CHECK-NEXT: call void @may_free_memory()
25 ; CHECK-NEXT: [[X_PRE:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4
26 ; CHECK-NEXT: br label [[BACKEDGE]]
28 ; CHECK-NEXT: [[X2]] = phi i32 [ [[X_PRE]], [[COLD_PATH]] ], [ [[X]], [[HOT_PATH]] ]
29 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
30 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
31 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
33 ; CHECK-NEXT: ret i32 [[X]]
39 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
40 %x = load i32, i32 addrspace(1)* %p
41 %cond = icmp ne i32 %x, 0
42 br i1 %cond, label %hot_path, label %cold_path
48 call void @may_free_memory()
52 %iv.next = add i32 %iv, %x
53 %loop.cond = icmp ult i32 %iv.next, 1000
54 br i1 %loop.cond, label %loop, label %exit
60 ; Do not PRE here because a loop-variant pointer.
61 define i32 @test_load_on_cold_path_gc_variant_neg(i32 addrspace(1)* addrspace(1)* %pp) gc "statepoint-example" personality i32 ()* @"personality_function" {
62 ; CHECK-LABEL: @test_load_on_cold_path_gc_variant_neg(
64 ; CHECK-NEXT: br label [[LOOP:%.*]]
66 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
67 ; CHECK-NEXT: [[P:%.*]] = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* [[PP:%.*]], align 8
68 ; CHECK-NEXT: [[X:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4
69 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
70 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
72 ; CHECK-NEXT: br label [[BACKEDGE]]
74 ; CHECK-NEXT: call void @may_free_memory()
75 ; CHECK-NEXT: br label [[BACKEDGE]]
77 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
78 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
79 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
81 ; CHECK-NEXT: ret i32 [[X]]
87 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
88 %p = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pp
89 %x = load i32, i32 addrspace(1)* %p
90 %cond = icmp ne i32 %x, 0
91 br i1 %cond, label %hot_path, label %cold_path
97 call void @may_free_memory()
101 %iv.next = add i32 %iv, %x
102 %loop.cond = icmp ult i32 %iv.next, 1000
103 br i1 %loop.cond, label %loop, label %exit
110 ; TODO: We can PRE the load away from the hot path.
111 define i32 @test_load_on_cold_path(i32* %p) {
112 ; CHECK-LABEL: @test_load_on_cold_path(
114 ; CHECK-NEXT: br label [[LOOP:%.*]]
116 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
117 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
118 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
119 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
121 ; CHECK-NEXT: br label [[BACKEDGE]]
123 ; CHECK-NEXT: call void @side_effect() #[[ATTR0:[0-9]+]]
124 ; CHECK-NEXT: br label [[BACKEDGE]]
126 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
127 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
128 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
130 ; CHECK-NEXT: ret i32 [[X]]
136 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
137 %x = load i32, i32* %p
138 %cond = icmp ne i32 %x, 0
139 br i1 %cond, label %hot_path, label %cold_path
145 call void @side_effect() nofree
149 %iv.next = add i32 %iv, %x
150 %loop.cond = icmp ult i32 %iv.next, 1000
151 br i1 %loop.cond, label %loop, label %exit
157 ; We should NOT PRE here because the function on the cold path may possibly
158 ; free the memory under the pointer.
159 define i32 @test_load_on_cold_path_may_free_memory_neg(i32* %p) {
160 ; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_neg(
162 ; CHECK-NEXT: br label [[LOOP:%.*]]
164 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
165 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
166 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
167 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
169 ; CHECK-NEXT: br label [[BACKEDGE]]
171 ; CHECK-NEXT: call void @may_free_memory()
172 ; CHECK-NEXT: br label [[BACKEDGE]]
174 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
175 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
176 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
178 ; CHECK-NEXT: ret i32 [[X]]
184 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
185 %x = load i32, i32* %p
186 %cond = icmp ne i32 %x, 0
187 br i1 %cond, label %hot_path, label %cold_path
193 call void @may_free_memory()
197 %iv.next = add i32 %iv, %x
198 %loop.cond = icmp ult i32 %iv.next, 1000
199 br i1 %loop.cond, label %loop, label %exit
205 ; TODO: Despite the fact that the function may free memory in general, it
206 ; cannot free memory allocated by alloca.
207 define i32 @test_load_on_cold_path_may_free_memory_alloca() {
208 ; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca(
210 ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
211 ; CHECK-NEXT: call void @may_free_memory()
212 ; CHECK-NEXT: br label [[LOOP:%.*]]
214 ; CHECK-NEXT: br i1 undef, label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
216 ; CHECK-NEXT: br label [[BACKEDGE:%.*]]
218 ; CHECK-NEXT: call void @may_free_memory()
219 ; CHECK-NEXT: br label [[BACKEDGE]]
221 ; CHECK-NEXT: br i1 false, label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[EXIT:%.*]]
222 ; CHECK: backedge.loop_crit_edge:
223 ; CHECK-NEXT: br label [[LOOP]]
225 ; CHECK-NEXT: ret i32 undef
229 call void @may_free_memory()
233 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
234 %x = load i32, i32* %p
235 %cond = icmp ne i32 %x, 0
236 br i1 %cond, label %hot_path, label %cold_path
242 call void @may_free_memory()
246 %iv.next = add i32 %iv, %x
247 %loop.cond = icmp ult i32 %iv.next, 1000
248 br i1 %loop.cond, label %loop, label %exit
255 ; PRE here is meaningless, so we should not do it.
256 define i32 @test_load_on_both_paths(i32* %p) {
257 ; CHECK-LABEL: @test_load_on_both_paths(
259 ; CHECK-NEXT: br label [[LOOP:%.*]]
261 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
262 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
263 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
264 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
266 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
267 ; CHECK-NEXT: br label [[BACKEDGE]]
269 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
270 ; CHECK-NEXT: br label [[BACKEDGE]]
272 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
273 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
274 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
276 ; CHECK-NEXT: ret i32 [[X]]
282 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
283 %x = load i32, i32* %p
284 %cond = icmp ne i32 %x, 0
285 br i1 %cond, label %hot_path, label %cold_path
288 call void @side_effect() nofree
292 call void @side_effect() nofree
296 %iv.next = add i32 %iv, %x
297 %loop.cond = icmp ult i32 %iv.next, 1000
298 br i1 %loop.cond, label %loop, label %exit
305 ; We could PRE here, but it doesn't seem very profitable.
306 define i32 @test_load_on_backedge(i32* %p) {
307 ; CHECK-LABEL: @test_load_on_backedge(
309 ; CHECK-NEXT: br label [[LOOP:%.*]]
311 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
312 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
313 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
314 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
316 ; CHECK-NEXT: br label [[BACKEDGE]]
318 ; CHECK-NEXT: br label [[BACKEDGE]]
320 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
321 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
322 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
323 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
325 ; CHECK-NEXT: ret i32 [[X]]
331 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
332 %x = load i32, i32* %p
333 %cond = icmp ne i32 %x, 0
334 br i1 %cond, label %hot_path, label %cold_path
343 %iv.next = add i32 %iv, %x
344 call void @side_effect() nofree
345 %loop.cond = icmp ult i32 %iv.next, 1000
346 br i1 %loop.cond, label %loop, label %exit
352 ; TODO: We can PRE via splitting of the critical edge in the cold path.
353 define i32 @test_load_on_exiting_cold_path_01(i32* %p) {
354 ; CHECK-LABEL: @test_load_on_exiting_cold_path_01(
356 ; CHECK-NEXT: br label [[LOOP:%.*]]
358 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
359 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
360 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
361 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
363 ; CHECK-NEXT: br label [[BACKEDGE]]
365 ; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
366 ; CHECK-NEXT: br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]
368 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
369 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
370 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
372 ; CHECK-NEXT: ret i32 [[X]]
374 ; CHECK-NEXT: ret i32 -1
380 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
381 %x = load i32, i32* %p
382 %cond = icmp ne i32 %x, 0
383 br i1 %cond, label %hot_path, label %cold_path
389 %side_cond = call i1 @side_effect_cond() nofree
390 br i1 %side_cond, label %backedge, label %cold_exit
393 %iv.next = add i32 %iv, %x
394 %loop.cond = icmp ult i32 %iv.next, 1000
395 br i1 %loop.cond, label %loop, label %exit
404 ; TODO: We can PRE via splitting of the critical edge in the cold path.
405 define i32 @test_load_on_exiting_cold_path_02(i32* %p) gc "statepoint-example" personality i32 ()* @personality_function {
406 ; CHECK-LABEL: @test_load_on_exiting_cold_path_02(
408 ; CHECK-NEXT: br label [[LOOP:%.*]]
410 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
411 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
412 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
413 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
415 ; CHECK-NEXT: br label [[BACKEDGE]]
417 ; CHECK-NEXT: invoke void @side_effect()
418 ; CHECK-NEXT: to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]]
420 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
421 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
422 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
424 ; CHECK-NEXT: ret i32 [[X]]
426 ; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad token
427 ; CHECK-NEXT: cleanup
428 ; CHECK-NEXT: ret i32 -1
434 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
435 %x = load i32, i32* %p
436 %cond = icmp ne i32 %x, 0
437 br i1 %cond, label %hot_path, label %cold_path
443 invoke void @side_effect() to label %backedge unwind label %cold_exit
446 %iv.next = add i32 %iv, %x
447 %loop.cond = icmp ult i32 %iv.next, 1000
448 br i1 %loop.cond, label %loop, label %exit
454 %landing_pad = landingpad token
459 ; Make sure we do not insert load into both cold path & backedge.
460 define i32 @test_load_on_cold_path_and_backedge(i32* %p) {
461 ; CHECK-LABEL: @test_load_on_cold_path_and_backedge(
463 ; CHECK-NEXT: br label [[LOOP:%.*]]
465 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
466 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
467 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
468 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
470 ; CHECK-NEXT: br label [[BACKEDGE]]
472 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
473 ; CHECK-NEXT: br label [[BACKEDGE]]
475 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
476 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
477 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
478 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
480 ; CHECK-NEXT: ret i32 [[X]]
486 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
487 %x = load i32, i32* %p
488 %cond = icmp ne i32 %x, 0
489 br i1 %cond, label %hot_path, label %cold_path
495 call void @side_effect() nofree
499 %iv.next = add i32 %iv, %x
500 %loop.cond = icmp ult i32 %iv.next, 1000
501 call void @side_effect() nofree
502 br i1 %loop.cond, label %loop, label %exit
508 ; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load.
509 define i32 @test_load_multi_block_cold_path(i32* %p) {
510 ; CHECK-LABEL: @test_load_multi_block_cold_path(
512 ; CHECK-NEXT: br label [[LOOP:%.*]]
514 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
515 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
516 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
517 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]
519 ; CHECK-NEXT: br label [[BACKEDGE]]
520 ; CHECK: cold_path.1:
521 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
522 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
523 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
524 ; CHECK-NEXT: br label [[BACKEDGE]]
526 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
527 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
528 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
529 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
531 ; CHECK-NEXT: ret i32 [[X]]
537 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
538 %x = load i32, i32* %p
539 %cond = icmp ne i32 %x, 0
540 br i1 %cond, label %hot_path, label %cold_path.1
546 call void @side_effect() nofree
547 br label %cold_path.2
550 call void @side_effect() nofree
551 br label %cold_path.3
554 call void @side_effect() nofree
558 %iv.next = add i32 %iv, %x
559 %loop.cond = icmp ult i32 %iv.next, 1000
560 call void @side_effect() nofree
561 br i1 %loop.cond, label %loop, label %exit
567 ; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load.
568 define i32 @test_load_on_multi_exiting_cold_path(i32* %p) {
569 ; CHECK-LABEL: @test_load_on_multi_exiting_cold_path(
571 ; CHECK-NEXT: br label [[LOOP:%.*]]
573 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
574 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
575 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
576 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]
578 ; CHECK-NEXT: br label [[BACKEDGE]]
579 ; CHECK: cold_path.1:
580 ; CHECK-NEXT: [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
581 ; CHECK-NEXT: br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]]
582 ; CHECK: cold_path.2:
583 ; CHECK-NEXT: [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
584 ; CHECK-NEXT: br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]]
585 ; CHECK: cold_path.3:
586 ; CHECK-NEXT: [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
587 ; CHECK-NEXT: br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]]
589 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
590 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
591 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
593 ; CHECK-NEXT: ret i32 [[X]]
595 ; CHECK-NEXT: ret i32 -1
601 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
602 %x = load i32, i32* %p
603 %cond = icmp ne i32 %x, 0
604 br i1 %cond, label %hot_path, label %cold_path.1
610 %side_cond.1 = call i1 @side_effect_cond() nofree
611 br i1 %side_cond.1, label %cold_path.2, label %cold_exit
614 %side_cond.2 = call i1 @side_effect_cond() nofree
615 br i1 %side_cond.2, label %cold_path.3, label %cold_exit
618 %side_cond.3 = call i1 @side_effect_cond() nofree
619 br i1 %side_cond.3, label %backedge, label %cold_exit
622 %iv.next = add i32 %iv, %x
623 %loop.cond = icmp ult i32 %iv.next, 1000
624 br i1 %loop.cond, label %loop, label %exit
633 ; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop.
634 define i32 @test_inner_loop(i32* %p) {
635 ; CHECK-LABEL: @test_inner_loop(
637 ; CHECK-NEXT: br label [[LOOP:%.*]]
639 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
640 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
641 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
642 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
644 ; CHECK-NEXT: br label [[BACKEDGE]]
646 ; CHECK-NEXT: br label [[INNER_LOOP:%.*]]
648 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
649 ; CHECK-NEXT: br i1 undef, label [[INNER_LOOP]], label [[BACKEDGE]]
651 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
652 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
653 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
655 ; CHECK-NEXT: ret i32 [[X]]
661 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
662 %x = load i32, i32* %p
663 %cond = icmp ne i32 %x, 0
664 br i1 %cond, label %hot_path, label %cold_path
673 call void @side_effect() nofree
674 br i1 undef, label %inner_loop, label %backedge
677 %iv.next = add i32 %iv, %x
678 %loop.cond = icmp ult i32 %iv.next, 1000
679 br i1 %loop.cond, label %loop, label %exit
685 ; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason.
686 define i32 @test_multiple_cold_paths(i32* %p) {
687 ; CHECK-LABEL: @test_multiple_cold_paths(
689 ; CHECK-NEXT: br label [[LOOP:%.*]]
691 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
692 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
693 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[X]], 0
694 ; CHECK-NEXT: br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]]
696 ; CHECK-NEXT: br label [[DOM_1:%.*]]
697 ; CHECK: cold_path.1:
698 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
699 ; CHECK-NEXT: br label [[DOM_1]]
701 ; CHECK-NEXT: [[COND_2:%.*]] = icmp ne i32 [[X]], 1
702 ; CHECK-NEXT: br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]]
704 ; CHECK-NEXT: br label [[DOM_2:%.*]]
705 ; CHECK: cold_path.2:
706 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
707 ; CHECK-NEXT: br label [[DOM_2]]
709 ; CHECK-NEXT: [[COND_3:%.*]] = icmp ne i32 [[X]], 2
710 ; CHECK-NEXT: br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]]
712 ; CHECK-NEXT: br label [[BACKEDGE]]
713 ; CHECK: cold_path.3:
714 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
715 ; CHECK-NEXT: br label [[BACKEDGE]]
717 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
718 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
719 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
721 ; CHECK-NEXT: ret i32 [[X]]
727 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
728 %x = load i32, i32* %p
729 %cond.1 = icmp ne i32 %x, 0
730 br i1 %cond.1, label %hot_path.1, label %cold_path.1
736 call void @side_effect() nofree
740 %cond.2 = icmp ne i32 %x, 1
741 br i1 %cond.2, label %hot_path.2, label %cold_path.2
747 call void @side_effect() nofree
751 %cond.3 = icmp ne i32 %x, 2
752 br i1 %cond.3, label %hot_path.3, label %cold_path.3
758 call void @side_effect() nofree
762 %iv.next = add i32 %iv, %x
763 %loop.cond = icmp ult i32 %iv.next, 1000
764 br i1 %loop.cond, label %loop, label %exit
770 ; TODO: We can PRE via split of critical edge.
771 define i32 @test_side_exit_after_merge(i32* %p) {
772 ; CHECK-LABEL: @test_side_exit_after_merge(
774 ; CHECK-NEXT: br label [[LOOP:%.*]]
776 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
777 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
778 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
779 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
781 ; CHECK-NEXT: br label [[BACKEDGE]]
783 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[IV]], 1
784 ; CHECK-NEXT: br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]]
786 ; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
787 ; CHECK-NEXT: br label [[SIDE_EXITING]]
788 ; CHECK: side_exiting:
789 ; CHECK-NEXT: [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ]
790 ; CHECK-NEXT: br i1 [[SIDE_COND_PHI]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]
792 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
793 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
794 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
796 ; CHECK-NEXT: ret i32 [[X]]
798 ; CHECK-NEXT: ret i32 -1
804 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
805 %x = load i32, i32* %p
806 %cond = icmp ne i32 %x, 0
807 br i1 %cond, label %hot_path, label %cold_path
813 %cond.1 = icmp ne i32 %iv, 1
814 br i1 %cond.1, label %do_call, label %side_exiting
817 %side_cond = call i1 @side_effect_cond() nofree
818 br label %side_exiting
821 %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path]
822 br i1 %side_cond_phi, label %backedge, label %cold_exit
825 %iv.next = add i32 %iv, %x
826 %loop.cond = icmp ult i32 %iv.next, 1000
827 br i1 %loop.cond, label %loop, label %exit
836 declare void @llvm.experimental.guard(i1, ...)
838 define i32 @test_guard_1(i32* %p, i32 %g) {
839 ; CHECK-LABEL: @test_guard_1(
841 ; CHECK-NEXT: br label [[LOOP:%.*]]
843 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
844 ; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]
845 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]
846 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
847 ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100
848 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
850 ; CHECK-NEXT: br label [[BACKEDGE]]
852 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
853 ; CHECK-NEXT: br label [[BACKEDGE]]
855 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
856 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
857 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
859 ; CHECK-NEXT: ret i32 [[X]]
865 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
866 %guard_cond = icmp ne i32 %iv, %g
867 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
868 %x = load i32, i32* %p
869 %cond = icmp ult i32 %x, 100
870 br i1 %cond, label %hot_path, label %cold_path
876 call void @side_effect() nofree
880 %iv.next = add i32 %iv, %x
881 %loop.cond = icmp ult i32 %iv.next, 1000
882 br i1 %loop.cond, label %loop, label %exit
888 define i32 @test_guard_2(i32* %p, i32 %g) {
889 ; CHECK-LABEL: @test_guard_2(
891 ; CHECK-NEXT: br label [[LOOP:%.*]]
893 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
894 ; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]
895 ; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
896 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]
897 ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100
898 ; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
900 ; CHECK-NEXT: br label [[BACKEDGE]]
902 ; CHECK-NEXT: call void @side_effect() #[[ATTR0]]
903 ; CHECK-NEXT: br label [[BACKEDGE]]
905 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]
906 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
907 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
909 ; CHECK-NEXT: ret i32 [[X]]
915 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
916 %guard_cond = icmp ne i32 %iv, %g
917 %x = load i32, i32* %p
918 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
919 %cond = icmp ult i32 %x, 100
920 br i1 %cond, label %hot_path, label %cold_path
926 call void @side_effect() nofree
930 %iv.next = add i32 %iv, %x
931 %loop.cond = icmp ult i32 %iv.next, 1000
932 br i1 %loop.cond, label %loop, label %exit