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
205declare void @may_modify_or_free_pointer(i32* %p)
206
207; TODO: Despite the fact that the function may free memory in general, it
208; cannot free memory allocated by alloca.
209define i32 @test_load_on_cold_path_may_free_memory_alloca() {
210; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca(
211; CHECK-NEXT:  entry:
212; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4
213; CHECK-NEXT:    call void @may_modify_or_free_pointer(i32* [[P]])
214; CHECK-NEXT:    br label [[LOOP:%.*]]
215; CHECK:       loop:
216; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
217; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P]], align 4
218; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
219; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
220; CHECK:       hot_path:
221; CHECK-NEXT:    br label [[BACKEDGE]]
222; CHECK:       cold_path:
223; CHECK-NEXT:    call void @may_modify_or_free_pointer(i32* [[P]])
224; CHECK-NEXT:    br label [[BACKEDGE]]
225; CHECK:       backedge:
226; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
227; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
228; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
229; CHECK:       exit:
230; CHECK-NEXT:    ret i32 [[X]]
231;
232entry:
233  %p = alloca i32
234  call void @may_modify_or_free_pointer(i32* %p)
235  br label %loop
236
237loop:
238  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
239  %x = load i32, i32* %p
240  %cond = icmp ne i32 %x, 0
241  br i1 %cond, label %hot_path, label %cold_path
242
243hot_path:
244  br label %backedge
245
246cold_path:
247  call void @may_modify_or_free_pointer(i32* %p)
248  br label %backedge
249
250backedge:
251  %iv.next = add i32 %iv, %x
252  %loop.cond = icmp ult i32 %iv.next, 1000
253  br i1 %loop.cond, label %loop, label %exit
254
255exit:
256  ret i32 %x
257}
258
259
260; PRE here is meaningless, so we should not do it.
261define i32 @test_load_on_both_paths(i32* %p) {
262; CHECK-LABEL: @test_load_on_both_paths(
263; CHECK-NEXT:  entry:
264; CHECK-NEXT:    br label [[LOOP:%.*]]
265; CHECK:       loop:
266; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
267; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
268; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
269; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
270; CHECK:       hot_path:
271; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
272; CHECK-NEXT:    br label [[BACKEDGE]]
273; CHECK:       cold_path:
274; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
275; CHECK-NEXT:    br label [[BACKEDGE]]
276; CHECK:       backedge:
277; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
278; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
279; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
280; CHECK:       exit:
281; CHECK-NEXT:    ret i32 [[X]]
282;
283entry:
284  br label %loop
285
286loop:
287  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
288  %x = load i32, i32* %p
289  %cond = icmp ne i32 %x, 0
290  br i1 %cond, label %hot_path, label %cold_path
291
292hot_path:
293  call void @side_effect() nofree
294  br label %backedge
295
296cold_path:
297  call void @side_effect() nofree
298  br label %backedge
299
300backedge:
301  %iv.next = add i32 %iv, %x
302  %loop.cond = icmp ult i32 %iv.next, 1000
303  br i1 %loop.cond, label %loop, label %exit
304
305exit:
306  ret i32 %x
307}
308
309
310; We could PRE here, but it doesn't seem very profitable.
311define i32 @test_load_on_backedge(i32* %p) {
312; CHECK-LABEL: @test_load_on_backedge(
313; CHECK-NEXT:  entry:
314; CHECK-NEXT:    br label [[LOOP:%.*]]
315; CHECK:       loop:
316; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
317; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
318; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
319; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
320; CHECK:       hot_path:
321; CHECK-NEXT:    br label [[BACKEDGE]]
322; CHECK:       cold_path:
323; CHECK-NEXT:    br label [[BACKEDGE]]
324; CHECK:       backedge:
325; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
326; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
327; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
328; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
329; CHECK:       exit:
330; CHECK-NEXT:    ret i32 [[X]]
331;
332entry:
333  br label %loop
334
335loop:
336  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
337  %x = load i32, i32* %p
338  %cond = icmp ne i32 %x, 0
339  br i1 %cond, label %hot_path, label %cold_path
340
341hot_path:
342  br label %backedge
343
344cold_path:
345  br label %backedge
346
347backedge:
348  %iv.next = add i32 %iv, %x
349  call void @side_effect() nofree
350  %loop.cond = icmp ult i32 %iv.next, 1000
351  br i1 %loop.cond, label %loop, label %exit
352
353exit:
354  ret i32 %x
355}
356
357; TODO: We can PRE via splitting of the critical edge in the cold path.
358define i32 @test_load_on_exiting_cold_path_01(i32* %p) {
359; CHECK-LABEL: @test_load_on_exiting_cold_path_01(
360; CHECK-NEXT:  entry:
361; CHECK-NEXT:    br label [[LOOP:%.*]]
362; CHECK:       loop:
363; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
364; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
365; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
366; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
367; CHECK:       hot_path:
368; CHECK-NEXT:    br label [[BACKEDGE]]
369; CHECK:       cold_path:
370; CHECK-NEXT:    [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
371; CHECK-NEXT:    br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]
372; CHECK:       backedge:
373; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
374; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
375; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
376; CHECK:       exit:
377; CHECK-NEXT:    ret i32 [[X]]
378; CHECK:       cold_exit:
379; CHECK-NEXT:    ret i32 -1
380;
381entry:
382  br label %loop
383
384loop:
385  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
386  %x = load i32, i32* %p
387  %cond = icmp ne i32 %x, 0
388  br i1 %cond, label %hot_path, label %cold_path
389
390hot_path:
391  br label %backedge
392
393cold_path:
394  %side_cond = call i1 @side_effect_cond() nofree
395  br i1 %side_cond, label %backedge, label %cold_exit
396
397backedge:
398  %iv.next = add i32 %iv, %x
399  %loop.cond = icmp ult i32 %iv.next, 1000
400  br i1 %loop.cond, label %loop, label %exit
401
402exit:
403  ret i32 %x
404
405cold_exit:
406  ret i32 -1
407}
408
409; TODO: We can PRE via splitting of the critical edge in the cold path.
410define i32 @test_load_on_exiting_cold_path_02(i32* %p) gc "statepoint-example" personality i32 ()* @personality_function {
411; CHECK-LABEL: @test_load_on_exiting_cold_path_02(
412; CHECK-NEXT:  entry:
413; CHECK-NEXT:    br label [[LOOP:%.*]]
414; CHECK:       loop:
415; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
416; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
417; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
418; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
419; CHECK:       hot_path:
420; CHECK-NEXT:    br label [[BACKEDGE]]
421; CHECK:       cold_path:
422; CHECK-NEXT:    invoke void @side_effect()
423; CHECK-NEXT:    to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]]
424; CHECK:       backedge:
425; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
426; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
427; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
428; CHECK:       exit:
429; CHECK-NEXT:    ret i32 [[X]]
430; CHECK:       cold_exit:
431; CHECK-NEXT:    [[LANDING_PAD:%.*]] = landingpad token
432; CHECK-NEXT:    cleanup
433; CHECK-NEXT:    ret i32 -1
434;
435entry:
436  br label %loop
437
438loop:
439  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
440  %x = load i32, i32* %p
441  %cond = icmp ne i32 %x, 0
442  br i1 %cond, label %hot_path, label %cold_path
443
444hot_path:
445  br label %backedge
446
447cold_path:
448  invoke void @side_effect() to label %backedge unwind label %cold_exit
449
450backedge:
451  %iv.next = add i32 %iv, %x
452  %loop.cond = icmp ult i32 %iv.next, 1000
453  br i1 %loop.cond, label %loop, label %exit
454
455exit:
456  ret i32 %x
457
458cold_exit:
459  %landing_pad = landingpad token
460  cleanup
461  ret i32 -1
462}
463
464; Make sure we do not insert load into both cold path & backedge.
465define i32 @test_load_on_cold_path_and_backedge(i32* %p) {
466; CHECK-LABEL: @test_load_on_cold_path_and_backedge(
467; CHECK-NEXT:  entry:
468; CHECK-NEXT:    br label [[LOOP:%.*]]
469; CHECK:       loop:
470; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
471; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
472; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
473; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
474; CHECK:       hot_path:
475; CHECK-NEXT:    br label [[BACKEDGE]]
476; CHECK:       cold_path:
477; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
478; CHECK-NEXT:    br label [[BACKEDGE]]
479; CHECK:       backedge:
480; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
481; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
482; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
483; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
484; CHECK:       exit:
485; CHECK-NEXT:    ret i32 [[X]]
486;
487entry:
488  br label %loop
489
490loop:
491  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
492  %x = load i32, i32* %p
493  %cond = icmp ne i32 %x, 0
494  br i1 %cond, label %hot_path, label %cold_path
495
496hot_path:
497  br label %backedge
498
499cold_path:
500  call void @side_effect() nofree
501  br label %backedge
502
503backedge:
504  %iv.next = add i32 %iv, %x
505  %loop.cond = icmp ult i32 %iv.next, 1000
506  call void @side_effect() nofree
507  br i1 %loop.cond, label %loop, label %exit
508
509exit:
510  ret i32 %x
511}
512
513; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load.
514define i32 @test_load_multi_block_cold_path(i32* %p) {
515; CHECK-LABEL: @test_load_multi_block_cold_path(
516; CHECK-NEXT:  entry:
517; CHECK-NEXT:    br label [[LOOP:%.*]]
518; CHECK:       loop:
519; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
520; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
521; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
522; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]
523; CHECK:       hot_path:
524; CHECK-NEXT:    br label [[BACKEDGE]]
525; CHECK:       cold_path.1:
526; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
527; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
528; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
529; CHECK-NEXT:    br label [[BACKEDGE]]
530; CHECK:       backedge:
531; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
532; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
533; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
534; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
535; CHECK:       exit:
536; CHECK-NEXT:    ret i32 [[X]]
537;
538entry:
539  br label %loop
540
541loop:
542  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
543  %x = load i32, i32* %p
544  %cond = icmp ne i32 %x, 0
545  br i1 %cond, label %hot_path, label %cold_path.1
546
547hot_path:
548  br label %backedge
549
550cold_path.1:
551  call void @side_effect() nofree
552  br label %cold_path.2
553
554cold_path.2:
555  call void @side_effect() nofree
556  br label %cold_path.3
557
558cold_path.3:
559  call void @side_effect() nofree
560  br label %backedge
561
562backedge:
563  %iv.next = add i32 %iv, %x
564  %loop.cond = icmp ult i32 %iv.next, 1000
565  call void @side_effect() nofree
566  br i1 %loop.cond, label %loop, label %exit
567
568exit:
569  ret i32 %x
570}
571
572; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load.
573define i32 @test_load_on_multi_exiting_cold_path(i32* %p) {
574; CHECK-LABEL: @test_load_on_multi_exiting_cold_path(
575; CHECK-NEXT:  entry:
576; CHECK-NEXT:    br label [[LOOP:%.*]]
577; CHECK:       loop:
578; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
579; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
580; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
581; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]
582; CHECK:       hot_path:
583; CHECK-NEXT:    br label [[BACKEDGE]]
584; CHECK:       cold_path.1:
585; CHECK-NEXT:    [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
586; CHECK-NEXT:    br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]]
587; CHECK:       cold_path.2:
588; CHECK-NEXT:    [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
589; CHECK-NEXT:    br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]]
590; CHECK:       cold_path.3:
591; CHECK-NEXT:    [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
592; CHECK-NEXT:    br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]]
593; CHECK:       backedge:
594; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
595; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
596; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
597; CHECK:       exit:
598; CHECK-NEXT:    ret i32 [[X]]
599; CHECK:       cold_exit:
600; CHECK-NEXT:    ret i32 -1
601;
602entry:
603  br label %loop
604
605loop:
606  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
607  %x = load i32, i32* %p
608  %cond = icmp ne i32 %x, 0
609  br i1 %cond, label %hot_path, label %cold_path.1
610
611hot_path:
612  br label %backedge
613
614cold_path.1:
615  %side_cond.1 = call i1 @side_effect_cond() nofree
616  br i1 %side_cond.1, label %cold_path.2, label %cold_exit
617
618cold_path.2:
619  %side_cond.2 = call i1 @side_effect_cond() nofree
620  br i1 %side_cond.2, label %cold_path.3, label %cold_exit
621
622cold_path.3:
623  %side_cond.3 = call i1 @side_effect_cond() nofree
624  br i1 %side_cond.3, label %backedge, label %cold_exit
625
626backedge:
627  %iv.next = add i32 %iv, %x
628  %loop.cond = icmp ult i32 %iv.next, 1000
629  br i1 %loop.cond, label %loop, label %exit
630
631exit:
632  ret i32 %x
633
634cold_exit:
635  ret i32 -1
636}
637
638; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop.
639define i32 @test_inner_loop(i32* %p) {
640; CHECK-LABEL: @test_inner_loop(
641; CHECK-NEXT:  entry:
642; CHECK-NEXT:    br label [[LOOP:%.*]]
643; CHECK:       loop:
644; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
645; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
646; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
647; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
648; CHECK:       hot_path:
649; CHECK-NEXT:    br label [[BACKEDGE]]
650; CHECK:       cold_path:
651; CHECK-NEXT:    br label [[INNER_LOOP:%.*]]
652; CHECK:       inner_loop:
653; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
654; CHECK-NEXT:    br i1 undef, label [[INNER_LOOP]], label [[BACKEDGE]]
655; CHECK:       backedge:
656; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
657; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
658; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
659; CHECK:       exit:
660; CHECK-NEXT:    ret i32 [[X]]
661;
662entry:
663  br label %loop
664
665loop:
666  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
667  %x = load i32, i32* %p
668  %cond = icmp ne i32 %x, 0
669  br i1 %cond, label %hot_path, label %cold_path
670
671hot_path:
672  br label %backedge
673
674cold_path:
675  br label %inner_loop
676
677inner_loop:
678  call void @side_effect() nofree
679  br i1 undef, label %inner_loop, label %backedge
680
681backedge:
682  %iv.next = add i32 %iv, %x
683  %loop.cond = icmp ult i32 %iv.next, 1000
684  br i1 %loop.cond, label %loop, label %exit
685
686exit:
687  ret i32 %x
688}
689
690; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason.
691define i32 @test_multiple_cold_paths(i32* %p) {
692; CHECK-LABEL: @test_multiple_cold_paths(
693; CHECK-NEXT:  entry:
694; CHECK-NEXT:    br label [[LOOP:%.*]]
695; CHECK:       loop:
696; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
697; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
698; CHECK-NEXT:    [[COND_1:%.*]] = icmp ne i32 [[X]], 0
699; CHECK-NEXT:    br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]]
700; CHECK:       hot_path.1:
701; CHECK-NEXT:    br label [[DOM_1:%.*]]
702; CHECK:       cold_path.1:
703; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
704; CHECK-NEXT:    br label [[DOM_1]]
705; CHECK:       dom.1:
706; CHECK-NEXT:    [[COND_2:%.*]] = icmp ne i32 [[X]], 1
707; CHECK-NEXT:    br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]]
708; CHECK:       hot_path.2:
709; CHECK-NEXT:    br label [[DOM_2:%.*]]
710; CHECK:       cold_path.2:
711; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
712; CHECK-NEXT:    br label [[DOM_2]]
713; CHECK:       dom.2:
714; CHECK-NEXT:    [[COND_3:%.*]] = icmp ne i32 [[X]], 2
715; CHECK-NEXT:    br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]]
716; CHECK:       hot_path.3:
717; CHECK-NEXT:    br label [[BACKEDGE]]
718; CHECK:       cold_path.3:
719; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
720; CHECK-NEXT:    br label [[BACKEDGE]]
721; CHECK:       backedge:
722; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
723; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
724; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
725; CHECK:       exit:
726; CHECK-NEXT:    ret i32 [[X]]
727;
728entry:
729  br label %loop
730
731loop:
732  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
733  %x = load i32, i32* %p
734  %cond.1 = icmp ne i32 %x, 0
735  br i1 %cond.1, label %hot_path.1, label %cold_path.1
736
737hot_path.1:
738  br label %dom.1
739
740cold_path.1:
741  call void @side_effect() nofree
742  br label %dom.1
743
744dom.1:
745  %cond.2 = icmp ne i32 %x, 1
746  br i1 %cond.2, label %hot_path.2, label %cold_path.2
747
748hot_path.2:
749  br label %dom.2
750
751cold_path.2:
752  call void @side_effect() nofree
753  br label %dom.2
754
755dom.2:
756  %cond.3 = icmp ne i32 %x, 2
757  br i1 %cond.3, label %hot_path.3, label %cold_path.3
758
759hot_path.3:
760  br label %backedge
761
762cold_path.3:
763  call void @side_effect() nofree
764  br label %backedge
765
766backedge:
767  %iv.next = add i32 %iv, %x
768  %loop.cond = icmp ult i32 %iv.next, 1000
769  br i1 %loop.cond, label %loop, label %exit
770
771exit:
772  ret i32 %x
773}
774
775; TODO: We can PRE via split of critical edge.
776define i32 @test_side_exit_after_merge(i32* %p) {
777; CHECK-LABEL: @test_side_exit_after_merge(
778; CHECK-NEXT:  entry:
779; CHECK-NEXT:    br label [[LOOP:%.*]]
780; CHECK:       loop:
781; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
782; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
783; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0
784; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
785; CHECK:       hot_path:
786; CHECK-NEXT:    br label [[BACKEDGE]]
787; CHECK:       cold_path:
788; CHECK-NEXT:    [[COND_1:%.*]] = icmp ne i32 [[IV]], 1
789; CHECK-NEXT:    br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]]
790; CHECK:       do_call:
791; CHECK-NEXT:    [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]
792; CHECK-NEXT:    br label [[SIDE_EXITING]]
793; CHECK:       side_exiting:
794; CHECK-NEXT:    [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ]
795; CHECK-NEXT:    br i1 [[SIDE_COND_PHI]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]
796; CHECK:       backedge:
797; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
798; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
799; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
800; CHECK:       exit:
801; CHECK-NEXT:    ret i32 [[X]]
802; CHECK:       cold_exit:
803; CHECK-NEXT:    ret i32 -1
804;
805entry:
806  br label %loop
807
808loop:
809  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
810  %x = load i32, i32* %p
811  %cond = icmp ne i32 %x, 0
812  br i1 %cond, label %hot_path, label %cold_path
813
814hot_path:
815  br label %backedge
816
817cold_path:
818  %cond.1 = icmp ne i32 %iv, 1
819  br i1 %cond.1, label %do_call, label %side_exiting
820
821do_call:
822  %side_cond = call i1 @side_effect_cond() nofree
823  br label %side_exiting
824
825side_exiting:
826  %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path]
827  br i1 %side_cond_phi, label %backedge, label %cold_exit
828
829backedge:
830  %iv.next = add i32 %iv, %x
831  %loop.cond = icmp ult i32 %iv.next, 1000
832  br i1 %loop.cond, label %loop, label %exit
833
834exit:
835  ret i32 %x
836
837cold_exit:
838  ret i32 -1
839}
840
841declare void @llvm.experimental.guard(i1, ...)
842
843define i32 @test_guard_1(i32* %p, i32 %g) {
844; CHECK-LABEL: @test_guard_1(
845; CHECK-NEXT:  entry:
846; CHECK-NEXT:    br label [[LOOP:%.*]]
847; CHECK:       loop:
848; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
849; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]
850; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]
851; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
852; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[X]], 100
853; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
854; CHECK:       hot_path:
855; CHECK-NEXT:    br label [[BACKEDGE]]
856; CHECK:       cold_path:
857; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
858; CHECK-NEXT:    br label [[BACKEDGE]]
859; CHECK:       backedge:
860; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
861; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
862; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
863; CHECK:       exit:
864; CHECK-NEXT:    ret i32 [[X]]
865;
866entry:
867  br label %loop
868
869loop:
870  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
871  %guard_cond = icmp ne i32 %iv, %g
872  call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
873  %x = load i32, i32* %p
874  %cond = icmp ult i32 %x, 100
875  br i1 %cond, label %hot_path, label %cold_path
876
877hot_path:
878  br label %backedge
879
880cold_path:
881  call void @side_effect() nofree
882  br label %backedge
883
884backedge:
885  %iv.next = add i32 %iv, %x
886  %loop.cond = icmp ult i32 %iv.next, 1000
887  br i1 %loop.cond, label %loop, label %exit
888
889exit:
890  ret i32 %x
891}
892
893define i32 @test_guard_2(i32* %p, i32 %g) {
894; CHECK-LABEL: @test_guard_2(
895; CHECK-NEXT:  entry:
896; CHECK-NEXT:    br label [[LOOP:%.*]]
897; CHECK:       loop:
898; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
899; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]
900; CHECK-NEXT:    [[X:%.*]] = load i32, i32* [[P:%.*]], align 4
901; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]
902; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[X]], 100
903; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]
904; CHECK:       hot_path:
905; CHECK-NEXT:    br label [[BACKEDGE]]
906; CHECK:       cold_path:
907; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]
908; CHECK-NEXT:    br label [[BACKEDGE]]
909; CHECK:       backedge:
910; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]
911; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
912; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
913; CHECK:       exit:
914; CHECK-NEXT:    ret i32 [[X]]
915;
916entry:
917  br label %loop
918
919loop:
920  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]
921  %guard_cond = icmp ne i32 %iv, %g
922  %x = load i32, i32* %p
923  call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]
924  %cond = icmp ult i32 %x, 100
925  br i1 %cond, label %hot_path, label %cold_path
926
927hot_path:
928  br label %backedge
929
930cold_path:
931  call void @side_effect() nofree
932  br label %backedge
933
934backedge:
935  %iv.next = add i32 %iv, %x
936  %loop.cond = icmp ult i32 %iv.next, 1000
937  br i1 %loop.cond, label %loop, label %exit
938
939exit:
940  ret i32 %x
941}
942