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
3
4declare void @side_effect() nofree
5declare i1 @side_effect_cond() nofree
6declare void @may_free_memory()
7
8declare i32 @personality_function()
9
10; We can PRE the load from gc-managed memory away from the hot path.
11define 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(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    [[X_PRE1:%.*]] = load i32, i32 addrspace(1)* [[P:%.*]], align 4
15; CHECK-NEXT:    br label [[LOOP:%.*]]
16; CHECK:       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:%.*]]
21; CHECK:       hot_path:
22; CHECK-NEXT:    br label [[BACKEDGE]]
23; CHECK:       cold_path:
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]]
27; CHECK:       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:%.*]]
32; CHECK:       exit:
33; CHECK-NEXT:    ret i32 [[X]]
34;
35entry:
36  br label %loop
37
38loop:
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
43
44hot_path:
45  br label %backedge
46
47cold_path:
48  call void @may_free_memory()
49  br label %backedge
50
51backedge:
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
55
56exit:
57  ret i32 %x
58}
59
60; Do not PRE here because a loop-variant pointer.
61define 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(
63; CHECK-NEXT:  entry:
64; CHECK-NEXT:    br label [[LOOP:%.*]]
65; CHECK:       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:%.*]]
71; CHECK:       hot_path:
72; CHECK-NEXT:    br label [[BACKEDGE]]
73; CHECK:       cold_path:
74; CHECK-NEXT:    call void @may_free_memory()
75; CHECK-NEXT:    br label [[BACKEDGE]]
76; CHECK:       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:%.*]]
80; CHECK:       exit:
81; CHECK-NEXT:    ret i32 [[X]]
82;
83entry:
84  br label %loop
85
86loop:
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
92
93hot_path:
94  br label %backedge
95
96cold_path:
97  call void @may_free_memory()
98  br label %backedge
99
100backedge:
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
104
105exit:
106  ret i32 %x
107}
108
109
110; TODO: We can PRE the load away from the hot path.
111define i32 @test_load_on_cold_path(i32* %p) {
112; CHECK-LABEL: @test_load_on_cold_path(
113; CHECK-NEXT:  entry:
114; CHECK-NEXT:    br label [[LOOP:%.*]]
115; CHECK:       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:%.*]]
120; CHECK:       hot_path:
121; CHECK-NEXT:    br label [[BACKEDGE]]
122; CHECK:       cold_path:
123; CHECK-NEXT:    call void @side_effect() #[[ATTR0:[0-9]+]]
124; CHECK-NEXT:    br label [[BACKEDGE]]
125; CHECK:       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:%.*]]
129; CHECK:       exit:
130; CHECK-NEXT:    ret i32 [[X]]
131;
132entry:
133  br label %loop
134
135loop:
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
140
141hot_path:
142  br label %backedge
143
144cold_path:
145  call void @side_effect() nofree
146  br label %backedge
147
148backedge:
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
152
153exit:
154  ret i32 %x
155}
156
157; We should NOT PRE here because the function on the cold path may possibly
158; free the memory under the pointer.
159define i32 @test_load_on_cold_path_may_free_memory_neg(i32* %p) {
160; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_neg(
161; CHECK-NEXT:  entry:
162; CHECK-NEXT:    br label [[LOOP:%.*]]
163; CHECK:       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:%.*]]
168; CHECK:       hot_path:
169; CHECK-NEXT:    br label [[BACKEDGE]]
170; CHECK:       cold_path:
171; CHECK-NEXT:    call void @may_free_memory()
172; CHECK-NEXT:    br label [[BACKEDGE]]
173; CHECK:       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:%.*]]
177; CHECK:       exit:
178; CHECK-NEXT:    ret i32 [[X]]
179;
180entry:
181  br label %loop
182
183loop:
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
188
189hot_path:
190  br label %backedge
191
192cold_path:
193  call void @may_free_memory()
194  br label %backedge
195
196backedge:
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
200
201exit:
202  ret i32 %x
203}
204
205; TODO: Despite the fact that the function may free memory in general, it
206; cannot free memory allocated by alloca.
207define i32 @test_load_on_cold_path_may_free_memory_alloca() {
208; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca(
209; CHECK-NEXT:  entry:
210; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
211; CHECK-NEXT:    call void @may_free_memory()
212; CHECK-NEXT:    br label [[LOOP:%.*]]
213; CHECK:       loop:
214; CHECK-NEXT:    br i1 undef, label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
215; CHECK:       hot_path:
216; CHECK-NEXT:    br label [[BACKEDGE:%.*]]
217; CHECK:       cold_path:
218; CHECK-NEXT:    call void @may_free_memory()
219; CHECK-NEXT:    br label [[BACKEDGE]]
220; CHECK:       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]]
224; CHECK:       exit:
225; CHECK-NEXT:    ret i32 undef
226;
227entry:
228  %p = alloca i32
229  call void @may_free_memory()
230  br label %loop
231
232loop:
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
237
238hot_path:
239  br label %backedge
240
241cold_path:
242  call void @may_free_memory()
243  br label %backedge
244
245backedge:
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
249
250exit:
251  ret i32 %x
252}
253
254
255; PRE here is meaningless, so we should not do it.
256define i32 @test_load_on_both_paths(i32* %p) {
257; CHECK-LABEL: @test_load_on_both_paths(
258; CHECK-NEXT:  entry:
259; CHECK-NEXT:    br label [[LOOP:%.*]]
260; CHECK:       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:%.*]]
265; CHECK:       hot_path:
266; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
267; CHECK-NEXT:    br label [[BACKEDGE]]
268; CHECK:       cold_path:
269; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
270; CHECK-NEXT:    br label [[BACKEDGE]]
271; CHECK:       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:%.*]]
275; CHECK:       exit:
276; CHECK-NEXT:    ret i32 [[X]]
277;
278entry:
279  br label %loop
280
281loop:
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
286
287hot_path:
288  call void @side_effect() nofree
289  br label %backedge
290
291cold_path:
292  call void @side_effect() nofree
293  br label %backedge
294
295backedge:
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
299
300exit:
301  ret i32 %x
302}
303
304
305; We could PRE here, but it doesn't seem very profitable.
306define i32 @test_load_on_backedge(i32* %p) {
307; CHECK-LABEL: @test_load_on_backedge(
308; CHECK-NEXT:  entry:
309; CHECK-NEXT:    br label [[LOOP:%.*]]
310; CHECK:       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:%.*]]
315; CHECK:       hot_path:
316; CHECK-NEXT:    br label [[BACKEDGE]]
317; CHECK:       cold_path:
318; CHECK-NEXT:    br label [[BACKEDGE]]
319; CHECK:       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:%.*]]
324; CHECK:       exit:
325; CHECK-NEXT:    ret i32 [[X]]
326;
327entry:
328  br label %loop
329
330loop:
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
335
336hot_path:
337  br label %backedge
338
339cold_path:
340  br label %backedge
341
342backedge:
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
347
348exit:
349  ret i32 %x
350}
351
352; TODO: We can PRE via splitting of the critical edge in the cold path.
353define i32 @test_load_on_exiting_cold_path_01(i32* %p) {
354; CHECK-LABEL: @test_load_on_exiting_cold_path_01(
355; CHECK-NEXT:  entry:
356; CHECK-NEXT:    br label [[LOOP:%.*]]
357; CHECK:       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:%.*]]
362; CHECK:       hot_path:
363; CHECK-NEXT:    br label [[BACKEDGE]]
364; CHECK:       cold_path:
365; CHECK-NEXT:    [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
366; CHECK-NEXT:    br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]
367; CHECK:       backedge:
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:%.*]]
371; CHECK:       exit:
372; CHECK-NEXT:    ret i32 [[X]]
373; CHECK:       cold_exit:
374; CHECK-NEXT:    ret i32 -1
375;
376entry:
377  br label %loop
378
379loop:
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
384
385hot_path:
386  br label %backedge
387
388cold_path:
389  %side_cond = call i1 @side_effect_cond() nofree
390  br i1 %side_cond, label %backedge, label %cold_exit
391
392backedge:
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
396
397exit:
398  ret i32 %x
399
400cold_exit:
401  ret i32 -1
402}
403
404; TODO: We can PRE via splitting of the critical edge in the cold path.
405define 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(
407; CHECK-NEXT:  entry:
408; CHECK-NEXT:    br label [[LOOP:%.*]]
409; CHECK:       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:%.*]]
414; CHECK:       hot_path:
415; CHECK-NEXT:    br label [[BACKEDGE]]
416; CHECK:       cold_path:
417; CHECK-NEXT:    invoke void @side_effect()
418; CHECK-NEXT:    to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]]
419; CHECK:       backedge:
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:%.*]]
423; CHECK:       exit:
424; CHECK-NEXT:    ret i32 [[X]]
425; CHECK:       cold_exit:
426; CHECK-NEXT:    [[LANDING_PAD:%.*]] = landingpad token
427; CHECK-NEXT:    cleanup
428; CHECK-NEXT:    ret i32 -1
429;
430entry:
431  br label %loop
432
433loop:
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
438
439hot_path:
440  br label %backedge
441
442cold_path:
443  invoke void @side_effect() to label %backedge unwind label %cold_exit
444
445backedge:
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
449
450exit:
451  ret i32 %x
452
453cold_exit:
454  %landing_pad = landingpad token
455  cleanup
456  ret i32 -1
457}
458
459; Make sure we do not insert load into both cold path & backedge.
460define i32 @test_load_on_cold_path_and_backedge(i32* %p) {
461; CHECK-LABEL: @test_load_on_cold_path_and_backedge(
462; CHECK-NEXT:  entry:
463; CHECK-NEXT:    br label [[LOOP:%.*]]
464; CHECK:       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:%.*]]
469; CHECK:       hot_path:
470; CHECK-NEXT:    br label [[BACKEDGE]]
471; CHECK:       cold_path:
472; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
473; CHECK-NEXT:    br label [[BACKEDGE]]
474; CHECK:       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:%.*]]
479; CHECK:       exit:
480; CHECK-NEXT:    ret i32 [[X]]
481;
482entry:
483  br label %loop
484
485loop:
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
490
491hot_path:
492  br label %backedge
493
494cold_path:
495  call void @side_effect() nofree
496  br label %backedge
497
498backedge:
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
503
504exit:
505  ret i32 %x
506}
507
508; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load.
509define i32 @test_load_multi_block_cold_path(i32* %p) {
510; CHECK-LABEL: @test_load_multi_block_cold_path(
511; CHECK-NEXT:  entry:
512; CHECK-NEXT:    br label [[LOOP:%.*]]
513; CHECK:       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:%.*]]
518; CHECK:       hot_path:
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]]
525; CHECK:       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:%.*]]
530; CHECK:       exit:
531; CHECK-NEXT:    ret i32 [[X]]
532;
533entry:
534  br label %loop
535
536loop:
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
541
542hot_path:
543  br label %backedge
544
545cold_path.1:
546  call void @side_effect() nofree
547  br label %cold_path.2
548
549cold_path.2:
550  call void @side_effect() nofree
551  br label %cold_path.3
552
553cold_path.3:
554  call void @side_effect() nofree
555  br label %backedge
556
557backedge:
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
562
563exit:
564  ret i32 %x
565}
566
567; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load.
568define i32 @test_load_on_multi_exiting_cold_path(i32* %p) {
569; CHECK-LABEL: @test_load_on_multi_exiting_cold_path(
570; CHECK-NEXT:  entry:
571; CHECK-NEXT:    br label [[LOOP:%.*]]
572; CHECK:       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:%.*]]
577; CHECK:       hot_path:
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]]
588; CHECK:       backedge:
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:%.*]]
592; CHECK:       exit:
593; CHECK-NEXT:    ret i32 [[X]]
594; CHECK:       cold_exit:
595; CHECK-NEXT:    ret i32 -1
596;
597entry:
598  br label %loop
599
600loop:
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
605
606hot_path:
607  br label %backedge
608
609cold_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
612
613cold_path.2:
614  %side_cond.2 = call i1 @side_effect_cond() nofree
615  br i1 %side_cond.2, label %cold_path.3, label %cold_exit
616
617cold_path.3:
618  %side_cond.3 = call i1 @side_effect_cond() nofree
619  br i1 %side_cond.3, label %backedge, label %cold_exit
620
621backedge:
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
625
626exit:
627  ret i32 %x
628
629cold_exit:
630  ret i32 -1
631}
632
633; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop.
634define i32 @test_inner_loop(i32* %p) {
635; CHECK-LABEL: @test_inner_loop(
636; CHECK-NEXT:  entry:
637; CHECK-NEXT:    br label [[LOOP:%.*]]
638; CHECK:       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:%.*]]
643; CHECK:       hot_path:
644; CHECK-NEXT:    br label [[BACKEDGE]]
645; CHECK:       cold_path:
646; CHECK-NEXT:    br label [[INNER_LOOP:%.*]]
647; CHECK:       inner_loop:
648; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
649; CHECK-NEXT:    br i1 undef, label [[INNER_LOOP]], label [[BACKEDGE]]
650; CHECK:       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:%.*]]
654; CHECK:       exit:
655; CHECK-NEXT:    ret i32 [[X]]
656;
657entry:
658  br label %loop
659
660loop:
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
665
666hot_path:
667  br label %backedge
668
669cold_path:
670  br label %inner_loop
671
672inner_loop:
673  call void @side_effect() nofree
674  br i1 undef, label %inner_loop, label %backedge
675
676backedge:
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
680
681exit:
682  ret i32 %x
683}
684
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.
686define i32 @test_multiple_cold_paths(i32* %p) {
687; CHECK-LABEL: @test_multiple_cold_paths(
688; CHECK-NEXT:  entry:
689; CHECK-NEXT:    br label [[LOOP:%.*]]
690; CHECK:       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:%.*]]
695; CHECK:       hot_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]]
700; CHECK:       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:%.*]]
703; CHECK:       hot_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]]
708; CHECK:       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:%.*]]
711; CHECK:       hot_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]]
716; CHECK:       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:%.*]]
720; CHECK:       exit:
721; CHECK-NEXT:    ret i32 [[X]]
722;
723entry:
724  br label %loop
725
726loop:
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
731
732hot_path.1:
733  br label %dom.1
734
735cold_path.1:
736  call void @side_effect() nofree
737  br label %dom.1
738
739dom.1:
740  %cond.2 = icmp ne i32 %x, 1
741  br i1 %cond.2, label %hot_path.2, label %cold_path.2
742
743hot_path.2:
744  br label %dom.2
745
746cold_path.2:
747  call void @side_effect() nofree
748  br label %dom.2
749
750dom.2:
751  %cond.3 = icmp ne i32 %x, 2
752  br i1 %cond.3, label %hot_path.3, label %cold_path.3
753
754hot_path.3:
755  br label %backedge
756
757cold_path.3:
758  call void @side_effect() nofree
759  br label %backedge
760
761backedge:
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
765
766exit:
767  ret i32 %x
768}
769
770; TODO: We can PRE via split of critical edge.
771define i32 @test_side_exit_after_merge(i32* %p) {
772; CHECK-LABEL: @test_side_exit_after_merge(
773; CHECK-NEXT:  entry:
774; CHECK-NEXT:    br label [[LOOP:%.*]]
775; CHECK:       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:%.*]]
780; CHECK:       hot_path:
781; CHECK-NEXT:    br label [[BACKEDGE]]
782; CHECK:       cold_path:
783; CHECK-NEXT:    [[COND_1:%.*]] = icmp ne i32 [[IV]], 1
784; CHECK-NEXT:    br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]]
785; CHECK:       do_call:
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:%.*]]
791; CHECK:       backedge:
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:%.*]]
795; CHECK:       exit:
796; CHECK-NEXT:    ret i32 [[X]]
797; CHECK:       cold_exit:
798; CHECK-NEXT:    ret i32 -1
799;
800entry:
801  br label %loop
802
803loop:
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
808
809hot_path:
810  br label %backedge
811
812cold_path:
813  %cond.1 = icmp ne i32 %iv, 1
814  br i1 %cond.1, label %do_call, label %side_exiting
815
816do_call:
817  %side_cond = call i1 @side_effect_cond() nofree
818  br label %side_exiting
819
820side_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
823
824backedge:
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
828
829exit:
830  ret i32 %x
831
832cold_exit:
833  ret i32 -1
834}
835
836declare void @llvm.experimental.guard(i1, ...)
837
838define i32 @test_guard_1(i32* %p, i32 %g) {
839; CHECK-LABEL: @test_guard_1(
840; CHECK-NEXT:  entry:
841; CHECK-NEXT:    br label [[LOOP:%.*]]
842; CHECK:       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:%.*]]
849; CHECK:       hot_path:
850; CHECK-NEXT:    br label [[BACKEDGE]]
851; CHECK:       cold_path:
852; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
853; CHECK-NEXT:    br label [[BACKEDGE]]
854; CHECK:       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:%.*]]
858; CHECK:       exit:
859; CHECK-NEXT:    ret i32 [[X]]
860;
861entry:
862  br label %loop
863
864loop:
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
871
872hot_path:
873  br label %backedge
874
875cold_path:
876  call void @side_effect() nofree
877  br label %backedge
878
879backedge:
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
883
884exit:
885  ret i32 %x
886}
887
888define i32 @test_guard_2(i32* %p, i32 %g) {
889; CHECK-LABEL: @test_guard_2(
890; CHECK-NEXT:  entry:
891; CHECK-NEXT:    br label [[LOOP:%.*]]
892; CHECK:       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:%.*]]
899; CHECK:       hot_path:
900; CHECK-NEXT:    br label [[BACKEDGE]]
901; CHECK:       cold_path:
902; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
903; CHECK-NEXT:    br label [[BACKEDGE]]
904; CHECK:       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:%.*]]
908; CHECK:       exit:
909; CHECK-NEXT:    ret i32 [[X]]
910;
911entry:
912  br label %loop
913
914loop:
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
921
922hot_path:
923  br label %backedge
924
925cold_path:
926  call void @side_effect() nofree
927  br label %backedge
928
929backedge:
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
933
934exit:
935  ret i32 %x
936}
937