xref: /llvm-project/llvm/test/Transforms/DeadStoreElimination/captures-before-load.ll (revision 1ee4a93b15bb5dee7a1045fd035e1a286bb5d162)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='dse' -S %s | FileCheck %s
3
4declare void @escape_and_clobber(ptr)
5declare void @escape_writeonly(ptr) writeonly
6declare void @clobber()
7
8define i32 @test_not_captured_before_load_same_bb(ptr %in.ptr) {
9; CHECK-LABEL: @test_not_captured_before_load_same_bb(
10; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
11; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
12; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
13; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
14; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
15; CHECK-NEXT:    ret i32 [[IN_LV_2]]
16;
17  %a = alloca i32, align 4
18  store i32 55, ptr %a
19  %in.lv.1 = load ptr , ptr %in.ptr, align 2
20  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
21  store i32 99, ptr %a, align 4
22  call void @escape_and_clobber(ptr %a)
23  ret i32 %in.lv.2
24}
25
26define i32 @test_not_captured_before_load_same_bb_escape_unreachable_block(ptr %in.ptr) {
27; CHECK-LABEL: @test_not_captured_before_load_same_bb_escape_unreachable_block(
28; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
29; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
30; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
31; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
32; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
33; CHECK-NEXT:    ret i32 [[IN_LV_2]]
34; CHECK:       unreach:
35; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
36; CHECK-NEXT:    ret i32 0
37;
38  %a = alloca i32, align 4
39  store i32 55, ptr %a
40  %in.lv.1 = load ptr , ptr %in.ptr, align 2
41  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
42  store i32 99, ptr %a, align 4
43  call void @escape_and_clobber(ptr %a)
44  ret i32 %in.lv.2
45
46unreach:
47  call void @escape_and_clobber(ptr %a)
48  ret i32 0
49}
50
51define i32 @test_not_captured_before_load_same_bb_escape_unreachable_block2(ptr %in.ptr) {
52; CHECK-LABEL: @test_not_captured_before_load_same_bb_escape_unreachable_block2(
53; CHECK-NEXT:    br label [[BB:%.*]]
54; CHECK:       unreach:
55; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A:%.*]])
56; CHECK-NEXT:    ret i32 0
57; CHECK:       bb:
58; CHECK-NEXT:    [[A]] = alloca i32, align 4
59; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
60; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
61; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
62; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
63; CHECK-NEXT:    ret i32 [[IN_LV_2]]
64;
65  br label %bb
66
67unreach:
68  call void @escape_and_clobber(ptr %a)
69  ret i32 0
70
71bb:
72  %a = alloca i32, align 4
73  store i32 55, ptr %a
74  %in.lv.1 = load ptr , ptr %in.ptr, align 2
75  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
76  store i32 99, ptr %a, align 4
77  call void @escape_and_clobber(ptr %a)
78  ret i32 %in.lv.2
79}
80
81define i32 @test_captured_and_clobbered_after_load_same_bb_2(ptr %in.ptr) {
82; CHECK-LABEL: @test_captured_and_clobbered_after_load_same_bb_2(
83; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
84; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
85; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
86; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
87; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
88; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
89; CHECK-NEXT:    call void @clobber()
90; CHECK-NEXT:    ret i32 [[IN_LV_2]]
91;
92  %a = alloca i32, align 4
93  store i32 55, ptr %a
94  %in.lv.1 = load ptr , ptr %in.ptr, align 2
95  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
96  call void @escape_and_clobber(ptr %a)
97  store i32 99, ptr %a, align 4
98  call void @clobber()
99  ret i32 %in.lv.2
100}
101
102define i32 @test_captured_after_load_same_bb_2_clobbered_later(ptr %in.ptr) {
103; CHECK-LABEL: @test_captured_after_load_same_bb_2_clobbered_later(
104; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
105; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
106; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
107; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
108; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
109; CHECK-NEXT:    call void @clobber()
110; CHECK-NEXT:    ret i32 [[IN_LV_2]]
111;
112  %a = alloca i32, align 4
113  store i32 55, ptr %a
114  %in.lv.1 = load ptr , ptr %in.ptr, align 2
115  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
116  call void @escape_writeonly(ptr %a)
117  store i32 99, ptr %a, align 4
118  call void @clobber()
119  ret i32 %in.lv.2
120}
121
122define i32 @test_captured_and_clobbered_before_load_same_bb_1(ptr %in.ptr) {
123; CHECK-LABEL: @test_captured_and_clobbered_before_load_same_bb_1(
124; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
125; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
126; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
127; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
128; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
129; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
130; CHECK-NEXT:    call void @clobber()
131; CHECK-NEXT:    ret i32 [[IN_LV_2]]
132;
133  %a = alloca i32, align 4
134  store i32 55, ptr %a
135  %in.lv.1 = load ptr , ptr %in.ptr, align 2
136  call void @escape_and_clobber(ptr %a)
137  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
138  store i32 99, ptr %a, align 4
139  call void @clobber()
140  ret i32 %in.lv.2
141}
142
143define i32 @test_captured_before_load_same_bb_1_clobbered_later(ptr %in.ptr) {
144; CHECK-LABEL: @test_captured_before_load_same_bb_1_clobbered_later(
145; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
146; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
147; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
148; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
149; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
150; CHECK-NEXT:    call void @clobber()
151; CHECK-NEXT:    ret i32 [[IN_LV_2]]
152;
153  %a = alloca i32, align 4
154  store i32 55, ptr %a
155  %in.lv.1 = load ptr , ptr %in.ptr, align 2
156  call void @escape_writeonly(ptr %a)
157  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
158  store i32 99, ptr %a, align 4
159  call void @clobber()
160  ret i32 %in.lv.2
161}
162
163define i32 @test_captured_before_load_same_bb_2(ptr %in.ptr) {
164; CHECK-LABEL: @test_captured_before_load_same_bb_2(
165; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
166; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
167; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
168; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
169; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
170; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
171; CHECK-NEXT:    call void @clobber()
172; CHECK-NEXT:    ret i32 [[IN_LV_2]]
173;
174  %a = alloca i32, align 4
175  store i32 55, ptr %a
176  call void @escape_writeonly(ptr %a)
177  %in.lv.1 = load ptr , ptr %in.ptr, align 2
178  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
179  store i32 99, ptr %a, align 4
180  call void @clobber()
181  ret i32 %in.lv.2
182}
183
184define i32 @test_not_captured_before_load_same_bb_clobber(ptr %in.ptr) {
185; CHECK-LABEL: @test_not_captured_before_load_same_bb_clobber(
186; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
187; CHECK-NEXT:    call void @clobber()
188; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
189; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
190; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
191; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
192; CHECK-NEXT:    ret i32 [[IN_LV_2]]
193;
194  %a = alloca i32, align 4
195  store i32 55, ptr %a
196  call void @clobber()
197  %in.lv.1 = load ptr , ptr %in.ptr, align 2
198  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
199  store i32 99, ptr %a, align 4
200  call void @escape_and_clobber(ptr %a)
201  ret i32 %in.lv.2
202}
203
204define i32 @test_captured_before_load_same_bb(ptr %in.ptr) {
205; CHECK-LABEL: @test_captured_before_load_same_bb(
206; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
207; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
208; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
209; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
210; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
211; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
212; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
213; CHECK-NEXT:    ret i32 [[IN_LV_2]]
214;
215  %a = alloca i32, align 4
216  store i32 55, ptr %a
217  call void @escape_and_clobber(ptr %a)
218  %in.lv.1 = load ptr , ptr %in.ptr, align 2
219  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
220  store i32 99, ptr %a, align 4
221  call void @escape_and_clobber(ptr %a)
222  ret i32 %in.lv.2
223}
224
225define i32 @test_captured_sibling_path_to_load_other_blocks_1(ptr %in.ptr, i1 %c.1) {
226; CHECK-LABEL: @test_captured_sibling_path_to_load_other_blocks_1(
227; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
228; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
229; CHECK:       then:
230; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
231; CHECK-NEXT:    br label [[EXIT:%.*]]
232; CHECK:       else:
233; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
234; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
235; CHECK-NEXT:    br label [[EXIT]]
236; CHECK:       exit:
237; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ]
238; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
239; CHECK-NEXT:    call void @clobber()
240; CHECK-NEXT:    ret i32 [[P]]
241;
242  %a = alloca i32, align 4
243  store i32 55, ptr %a
244  br i1 %c.1, label %then, label %else
245
246then:
247  call void @escape_writeonly(ptr %a)
248  br label %exit
249
250else:
251  %in.lv.1 = load ptr , ptr %in.ptr, align 2
252  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
253  br label %exit
254
255exit:
256  %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ]
257  store i32 99, ptr %a, align 4
258  call void @clobber()
259  ret i32 %p
260}
261
262define i32 @test_only_captured_sibling_path_with_ret_to_load_other_blocks(ptr %in.ptr, i1 %c.1) {
263; CHECK-LABEL: @test_only_captured_sibling_path_with_ret_to_load_other_blocks(
264; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
265; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
266; CHECK:       then:
267; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
268; CHECK-NEXT:    ret i32 0
269; CHECK:       else:
270; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
271; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
272; CHECK-NEXT:    br label [[EXIT:%.*]]
273; CHECK:       exit:
274; CHECK-NEXT:    call void @clobber()
275; CHECK-NEXT:    ret i32 [[IN_LV_2]]
276;
277  %a = alloca i32, align 4
278  store i32 55, ptr %a
279  br i1 %c.1, label %then, label %else
280
281then:
282  call void @escape_writeonly(ptr %a)
283  ret i32 0
284
285else:
286  %in.lv.1 = load ptr , ptr %in.ptr, align 2
287  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
288  br label %exit
289
290exit:
291  store i32 99, ptr %a, align 4
292  call void @clobber()
293  ret i32 %in.lv.2
294}
295
296define i32 @test_captured_before_load_other_blocks_2(ptr %in.ptr, i1 %c.1) {
297; CHECK-LABEL: @test_captured_before_load_other_blocks_2(
298; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
299; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
300; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
301; CHECK:       then:
302; CHECK-NEXT:    br label [[EXIT:%.*]]
303; CHECK:       else:
304; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
305; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
306; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
307; CHECK-NEXT:    br label [[EXIT]]
308; CHECK:       exit:
309; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ]
310; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
311; CHECK-NEXT:    call void @clobber()
312; CHECK-NEXT:    ret i32 [[P]]
313;
314  %a = alloca i32, align 4
315  store i32 55, ptr %a
316  br i1 %c.1, label %then, label %else
317
318then:
319  br label %exit
320
321else:
322  call void @escape_and_clobber(ptr %a)
323  %in.lv.1 = load ptr , ptr %in.ptr, align 2
324  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
325  br label %exit
326
327exit:
328  %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ]
329  store i32 99, ptr %a, align 4
330  call void @clobber()
331  ret i32 %p
332}
333
334define i32 @test_captured_before_load_other_blocks_4(ptr %in.ptr, i1 %c.1) {
335; CHECK-LABEL: @test_captured_before_load_other_blocks_4(
336; CHECK-NEXT:  entry:
337; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
338; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
339; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
340; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
341; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
342; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
343; CHECK:       then:
344; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
345; CHECK-NEXT:    br label [[EXIT]]
346; CHECK:       exit:
347; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ENTRY:%.*]] ]
348; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
349; CHECK-NEXT:    call void @clobber()
350; CHECK-NEXT:    ret i32 [[P]]
351;
352entry:
353  %a = alloca i32, align 4
354  store i32 55, ptr %a
355  call void @escape_writeonly(ptr %a)
356  %in.lv.1 = load ptr , ptr %in.ptr, align 2
357  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
358  br i1 %c.1, label %then, label %exit
359
360then:
361  call void @escape_writeonly(ptr %a)
362  br label %exit
363
364exit:
365  %p = phi i32 [ 0, %then ], [ %in.lv.2, %entry ]
366  store i32 99, ptr %a, align 4
367  call void @clobber()
368  ret i32 %p
369}
370
371define i32 @test_captured_before_load_other_blocks_5(ptr %in.ptr, i1 %c.1) {
372; CHECK-LABEL: @test_captured_before_load_other_blocks_5(
373; CHECK-NEXT:  entry:
374; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
375; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
376; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
377; CHECK:       then:
378; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
379; CHECK-NEXT:    br label [[EXIT]]
380; CHECK:       exit:
381; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
382; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
383; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
384; CHECK-NEXT:    call void @clobber()
385; CHECK-NEXT:    ret i32 [[IN_LV_2]]
386;
387entry:
388  %a = alloca i32, align 4
389  store i32 55, ptr %a
390  br i1 %c.1, label %then, label %exit
391
392then:
393  call void @escape_writeonly(ptr %a)
394  br label %exit
395
396exit:
397  %in.lv.1 = load ptr , ptr %in.ptr, align 2
398  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
399  store i32 99, ptr %a, align 4
400  call void @clobber()
401  ret i32 %in.lv.2
402}
403
404define i32 @test_captured_before_load_other_blocks_6(ptr %in.ptr, i1 %c.1) {
405; CHECK-LABEL: @test_captured_before_load_other_blocks_6(
406; CHECK-NEXT:  entry:
407; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
408; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
409; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
410; CHECK:       then:
411; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
412; CHECK-NEXT:    br label [[EXIT]]
413; CHECK:       exit:
414; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
415; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
416; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
417; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
418; CHECK-NEXT:    call void @clobber()
419; CHECK-NEXT:    ret i32 [[IN_LV_2]]
420;
421entry:
422  %a = alloca i32, align 4
423  store i32 55, ptr %a
424  br i1 %c.1, label %then, label %exit
425
426then:
427  call void @escape_writeonly(ptr %a)
428  br label %exit
429
430exit:
431  %in.lv.1 = load ptr , ptr %in.ptr, align 2
432  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
433  store i32 99, ptr %a, align 4
434  call void @escape_writeonly(ptr %a)
435  call void @clobber()
436  ret i32 %in.lv.2
437}
438
439define i32 @test_not_captured_before_load_other_blocks_1(ptr %in.ptr, i1 %c.1) {
440; CHECK-LABEL: @test_not_captured_before_load_other_blocks_1(
441; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
442; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
443; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
444; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
445; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
446; CHECK:       then:
447; CHECK-NEXT:    br label [[EXIT:%.*]]
448; CHECK:       else:
449; CHECK-NEXT:    br label [[EXIT]]
450; CHECK:       exit:
451; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
452; CHECK-NEXT:    ret i32 [[IN_LV_2]]
453;
454  %a = alloca i32, align 4
455  store i32 55, ptr %a
456  %in.lv.1 = load ptr , ptr %in.ptr, align 2
457  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
458  store i32 99, ptr %a, align 4
459  br i1 %c.1, label %then, label %else
460
461then:
462  br label %exit
463
464else:
465  br label %exit
466
467exit:
468  call void @escape_and_clobber(ptr %a)
469  ret i32 %in.lv.2
470}
471
472define i32 @test_not_captured_before_load_other_blocks_2(ptr %in.ptr, i1 %c.1) {
473; CHECK-LABEL: @test_not_captured_before_load_other_blocks_2(
474; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
475; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
476; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
477; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
478; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
479; CHECK:       then:
480; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
481; CHECK-NEXT:    br label [[EXIT:%.*]]
482; CHECK:       else:
483; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
484; CHECK-NEXT:    br label [[EXIT]]
485; CHECK:       exit:
486; CHECK-NEXT:    ret i32 [[IN_LV_2]]
487;
488  %a = alloca i32, align 4
489  store i32 55, ptr %a
490  %in.lv.1 = load ptr , ptr %in.ptr, align 2
491  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
492  store i32 99, ptr %a, align 4
493  br i1 %c.1, label %then, label %else
494
495then:
496  call void @escape_and_clobber(ptr %a)
497  br label %exit
498
499else:
500  call void @escape_and_clobber(ptr %a)
501  br label %exit
502
503exit:
504  ret i32 %in.lv.2
505}
506
507define i32 @test_not_captured_before_load_other_blocks_3(ptr %in.ptr, i1 %c.1) {
508; CHECK-LABEL: @test_not_captured_before_load_other_blocks_3(
509; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
510; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
511; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
512; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
513; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
514; CHECK:       then:
515; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
516; CHECK-NEXT:    br label [[EXIT:%.*]]
517; CHECK:       else:
518; CHECK-NEXT:    br label [[EXIT]]
519; CHECK:       exit:
520; CHECK-NEXT:    ret i32 [[IN_LV_2]]
521;
522  %a = alloca i32, align 4
523  store i32 55, ptr %a
524  %in.lv.1 = load ptr , ptr %in.ptr, align 2
525  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
526  store i32 99, ptr %a, align 4
527  br i1 %c.1, label %then, label %else
528
529then:
530  call void @escape_and_clobber(ptr %a)
531  br label %exit
532
533else:
534  br label %exit
535
536exit:
537  ret i32 %in.lv.2
538}
539
540define i32 @test_not_captured_before_load_other_blocks_4(ptr %in.ptr, i1 %c.1) {
541; CHECK-LABEL: @test_not_captured_before_load_other_blocks_4(
542; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
543; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
544; CHECK:       then:
545; CHECK-NEXT:    br label [[EXIT:%.*]]
546; CHECK:       else:
547; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
548; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
549; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
550; CHECK-NEXT:    br label [[EXIT]]
551; CHECK:       exit:
552; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ]
553; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
554; CHECK-NEXT:    call void @clobber()
555; CHECK-NEXT:    ret i32 [[P]]
556;
557  %a = alloca i32, align 4
558  store i32 55, ptr %a
559  br i1 %c.1, label %then, label %else
560
561then:
562  br label %exit
563
564else:
565  %in.lv.1 = load ptr , ptr %in.ptr, align 2
566  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
567  call void @escape_writeonly(ptr %a)
568  br label %exit
569
570exit:
571  %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ]
572  store i32 99, ptr %a, align 4
573  call void @clobber()
574  ret i32 %p
575}
576
577define i32 @test_not_captured_before_load_other_blocks_5(ptr %in.ptr, i1 %c.1) {
578; CHECK-LABEL: @test_not_captured_before_load_other_blocks_5(
579; CHECK-NEXT:  entry:
580; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
581; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
582; CHECK:       then:
583; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
584; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
585; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
586; CHECK-NEXT:    br label [[EXIT]]
587; CHECK:       exit:
588; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ENTRY:%.*]] ]
589; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
590; CHECK-NEXT:    call void @clobber()
591; CHECK-NEXT:    ret i32 [[P]]
592;
593entry:
594  %a = alloca i32, align 4
595  store i32 55, ptr %a
596  br i1 %c.1, label %then, label %exit
597
598then:
599  %in.lv.1 = load ptr , ptr %in.ptr, align 2
600  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
601  call void @escape_writeonly(ptr %a)
602  br label %exit
603
604exit:
605  %p = phi i32 [ %in.lv.2, %then ], [ 0, %entry ]
606  store i32 99, ptr %a, align 4
607  call void @clobber()
608  ret i32 %p
609}
610
611define i32 @test_not_captured_before_load_other_blocks_6(ptr %in.ptr, i1 %c.1) {
612; CHECK-LABEL: @test_not_captured_before_load_other_blocks_6(
613; CHECK-NEXT:  entry:
614; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
615; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
616; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
617; CHECK:       then:
618; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
619; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
620; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
621; CHECK-NEXT:    br label [[EXIT]]
622; CHECK:       exit:
623; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ENTRY:%.*]] ]
624; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
625; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
626; CHECK-NEXT:    call void @clobber()
627; CHECK-NEXT:    ret i32 [[P]]
628;
629entry:
630  %a = alloca i32, align 4
631  store i32 55, ptr %a
632  br i1 %c.1, label %then, label %exit
633
634then:
635  %in.lv.1 = load ptr , ptr %in.ptr, align 2
636  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
637  call void @escape_writeonly(ptr %a)
638  br label %exit
639
640exit:
641  %p = phi i32 [ %in.lv.2, %then ], [ 0, %entry ]
642  store i32 99, ptr %a, align 4
643  call void @escape_writeonly(ptr %a)
644  call void @clobber()
645  ret i32 %p
646}
647
648define i32 @test_not_captured_before_load_other_blocks_7(ptr %in.ptr, i1 %c.1) {
649; CHECK-LABEL: @test_not_captured_before_load_other_blocks_7(
650; CHECK-NEXT:  entry:
651; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
652; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
653; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
654; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
655; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]]
656; CHECK:       then:
657; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
658; CHECK-NEXT:    br label [[EXIT]]
659; CHECK:       exit:
660; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ENTRY:%.*]] ]
661; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
662; CHECK-NEXT:    call void @clobber()
663; CHECK-NEXT:    ret i32 [[P]]
664;
665entry:
666  %a = alloca i32, align 4
667  store i32 55, ptr %a
668  %in.lv.1 = load ptr , ptr %in.ptr, align 2
669  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
670  call void @escape_writeonly(ptr %a)
671  br i1 %c.1, label %then, label %exit
672
673then:
674  call void @escape_writeonly(ptr %a)
675  br label %exit
676
677exit:
678  %p = phi i32 [ 0, %then ], [ %in.lv.2, %entry ]
679  store i32 99, ptr %a, align 4
680  call void @clobber()
681  ret i32 %p
682}
683
684define i32 @test_not_captured_before_load_same_bb_but_read(ptr %in.ptr) {
685; CHECK-LABEL: @test_not_captured_before_load_same_bb_but_read(
686; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
687; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
688; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
689; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
690; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[A]], align 4
691; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
692; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
693; CHECK-NEXT:    [[RES:%.*]] = add i32 [[IN_LV_2]], [[LV]]
694; CHECK-NEXT:    ret i32 [[RES]]
695;
696  %a = alloca i32, align 4
697  store i32 55, ptr %a
698  %in.lv.1 = load ptr , ptr %in.ptr, align 2
699  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
700  %lv = load i32, ptr %a
701  store i32 99, ptr %a, align 4
702  call void @escape_and_clobber(ptr %a)
703  %res = add i32 %in.lv.2, %lv
704  ret i32 %res
705}
706
707define i32 @test_not_captured_before_load_may_alias_same_bb_but_read(ptr %in.ptr, ptr %b, i1 %c) {
708; CHECK-LABEL: @test_not_captured_before_load_may_alias_same_bb_but_read(
709; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
710; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
711; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
712; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
713; CHECK-NEXT:    [[PTR:%.*]] = select i1 [[C:%.*]], ptr [[A]], ptr [[B:%.*]]
714; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[PTR]], align 4
715; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
716; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
717; CHECK-NEXT:    [[RES:%.*]] = add i32 [[IN_LV_2]], [[LV]]
718; CHECK-NEXT:    ret i32 [[RES]]
719;
720  %a = alloca i32, align 4
721  store i32 55, ptr %a
722  %in.lv.1 = load ptr , ptr %in.ptr, align 2
723  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
724  %ptr = select i1 %c, ptr %a, ptr %b
725  %lv = load i32, ptr %ptr
726  store i32 99, ptr %a, align 4
727  call void @escape_and_clobber(ptr %a)
728  %res = add i32 %in.lv.2, %lv
729  ret i32 %res
730}
731
732define i32 @test_captured_after_loop(ptr %in.ptr, i1 %c.1) {
733; CHECK-LABEL: @test_captured_after_loop(
734; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
735; CHECK-NEXT:    br label [[LOOP:%.*]]
736; CHECK:       loop:
737; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
738; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
739; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
740; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[LOOP]], label [[EXIT:%.*]]
741; CHECK:       exit:
742; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
743; CHECK-NEXT:    ret i32 [[IN_LV_2]]
744;
745  %a = alloca i32, align 4
746  store i32 55, ptr %a
747  br label %loop
748
749loop:
750  %in.lv.1 = load ptr , ptr %in.ptr, align 2
751  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
752  store i32 99, ptr %a, align 4
753  br i1 %c.1, label %loop, label %exit
754
755exit:
756  call void @escape_and_clobber(ptr %a)
757  ret i32 %in.lv.2
758}
759
760define i32 @test_captured_in_loop(ptr %in.ptr, i1 %c.1) {
761; CHECK-LABEL: @test_captured_in_loop(
762; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
763; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
764; CHECK-NEXT:    br label [[LOOP:%.*]]
765; CHECK:       loop:
766; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
767; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
768; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
769; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
770; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[LOOP]], label [[EXIT:%.*]]
771; CHECK:       exit:
772; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
773; CHECK-NEXT:    ret i32 [[IN_LV_2]]
774;
775  %a = alloca i32, align 4
776  store i32 55, ptr %a
777  br label %loop
778
779loop:
780  %in.lv.1 = load ptr , ptr %in.ptr, align 2
781  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
782  call void @escape_writeonly(ptr %a)
783  store i32 99, ptr %a, align 4
784  br i1 %c.1, label %loop, label %exit
785
786exit:
787  call void @escape_and_clobber(ptr %a)
788  ret i32 %in.lv.2
789}
790
791declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
792
793@global = external global ptr
794
795define void @test_memset_not_captured_before_load() {
796; CHECK-LABEL: @test_memset_not_captured_before_load(
797; CHECK-NEXT:    [[A:%.*]] = alloca [2 x i32], align 4
798; CHECK-NEXT:    [[LV_1:%.*]] = load ptr, ptr @global, align 8
799; CHECK-NEXT:    store i32 1, ptr [[A]], align 4
800; CHECK-NEXT:    [[GEP_LV:%.*]] = getelementptr inbounds [10 x i16], ptr [[LV_1]], i64 0, i32 1
801; CHECK-NEXT:    [[LV_2:%.*]] = load i16, ptr [[GEP_LV]], align 2
802; CHECK-NEXT:    [[EXT_LV_2:%.*]] = zext i16 [[LV_2]] to i32
803; CHECK-NEXT:    [[GEP_A_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1
804; CHECK-NEXT:    store i32 [[EXT_LV_2]], ptr [[GEP_A_1]], align 4
805; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
806; CHECK-NEXT:    ret void
807;
808  %a = alloca [2 x i32], align 4
809  call void @llvm.memset.p0.i32(ptr %a, i8 0, i32 8, i1 false)
810  %lv.1 = load ptr, ptr @global, align 8
811  store i32 1, ptr %a, align 4
812  %gep.lv = getelementptr inbounds [10 x i16], ptr %lv.1, i64 0, i32 1
813  %lv.2 = load i16, ptr %gep.lv, align 2
814  %ext.lv.2 = zext i16 %lv.2 to i32
815  %gep.a.1 = getelementptr inbounds [2 x i32], ptr %a, i32 0, i32 1
816  store i32 %ext.lv.2, ptr %gep.a.1, align 4
817  call void @escape_and_clobber(ptr %a)
818  ret void
819}
820
821define void @test_test_not_captured_before_load(i1 %c.1) {
822; CHECK-LABEL: @test_test_not_captured_before_load(
823; CHECK-NEXT:  bb:
824; CHECK-NEXT:    [[A:%.*]] = alloca [2 x i32], align 4
825; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 4
826; CHECK-NEXT:    call void @llvm.memset.p0.i32(ptr align 1 [[TMP0]], i8 0, i32 4, i1 false)
827; CHECK-NEXT:    [[LV_1:%.*]] = load ptr, ptr @global, align 8
828; CHECK-NEXT:    [[GEP_LV:%.*]] = getelementptr inbounds [10 x i16], ptr [[LV_1]], i64 0, i32 1
829; CHECK-NEXT:    [[LV_2:%.*]] = load i16, ptr [[GEP_LV]], align 2
830; CHECK-NEXT:    store i32 1, ptr [[A]], align 4
831; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
832; CHECK:       then:
833; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
834; CHECK-NEXT:    br label [[EXIT:%.*]]
835; CHECK:       else:
836; CHECK-NEXT:    br label [[EXIT]]
837; CHECK:       exit:
838; CHECK-NEXT:    [[EXT_LV_2:%.*]] = zext i16 [[LV_2]] to i32
839; CHECK-NEXT:    [[GEP_A_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1
840; CHECK-NEXT:    store i32 [[EXT_LV_2]], ptr [[GEP_A_1]], align 4
841; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
842; CHECK-NEXT:    ret void
843;
844bb:
845  %a = alloca [2 x i32], align 4
846  call void @llvm.memset.p0.i32(ptr %a, i8 0, i32 8, i1 false)
847  %lv.1 = load ptr, ptr @global, align 8
848  %gep.lv = getelementptr inbounds [10 x i16], ptr %lv.1, i64 0, i32 1
849  %lv.2 = load i16, ptr %gep.lv, align 2
850  store i32 1, ptr %a, align 4
851  br i1 %c.1, label %then, label %else
852
853then:
854  call void @escape_and_clobber(ptr %a)
855  br label %exit
856
857else:
858  br label %exit
859
860exit:
861  %ext.lv.2 = zext i16 %lv.2 to i32
862  %gep.a.1 = getelementptr inbounds [2 x i32], ptr %a, i32 0, i32 1
863  store i32 %ext.lv.2, ptr %gep.a.1, align 4
864  call void @escape_and_clobber(ptr %a)
865  ret void
866}
867
868declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0
869declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
870
871declare void @use.i64(i64)
872
873define i64 @test_a_not_captured_at_all(ptr %ptr, ptr %ptr.2, i1 %c) {
874; CHECK-LABEL: @test_a_not_captured_at_all(
875; CHECK-NEXT:  entry:
876; CHECK-NEXT:    [[A:%.*]] = alloca i64, align 8
877; CHECK-NEXT:    [[B:%.*]] = alloca i64, align 8
878; CHECK-NEXT:    store ptr [[B]], ptr [[PTR:%.*]], align 8
879; CHECK-NEXT:    [[LV_1:%.*]] = load ptr, ptr [[PTR_2:%.*]], align 8
880; CHECK-NEXT:    br i1 [[C:%.*]], label [[EXIT:%.*]], label [[THEN:%.*]]
881; CHECK:       then:
882; CHECK-NEXT:    [[LV_2:%.*]] = load i64, ptr [[LV_1]], align 4
883; CHECK-NEXT:    call void @use.i64(i64 [[LV_2]])
884; CHECK-NEXT:    br label [[EXIT]]
885; CHECK:       exit:
886; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr [[A]])
887; CHECK-NEXT:    call void @clobber()
888; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[A]], i8 0, i64 8, i1 false)
889; CHECK-NEXT:    [[L:%.*]] = load i64, ptr [[A]], align 4
890; CHECK-NEXT:    ret i64 [[L]]
891;
892entry:
893  %a = alloca i64, align 8
894  %b = alloca i64, align 8
895  store ptr %b, ptr %ptr, align 8
896  %lv.1 = load ptr, ptr %ptr.2, align 8
897  br i1 %c, label %exit, label %then
898
899then:
900  %lv.2 = load i64, ptr %lv.1
901  call void @use.i64(i64 %lv.2)
902  br label %exit
903
904exit:
905  call void @llvm.lifetime.start.p0(i64 8, ptr %a)
906  store i64 99, ptr %a
907  call void @clobber()
908  call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 8, i1 false)
909  %l = load i64, ptr %a
910  ret i64 %l
911}
912
913define i32 @test_not_captured_both_paths_1(ptr %in.ptr, i1 %c.1) {
914; CHECK-LABEL: @test_not_captured_both_paths_1(
915; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
916; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
917; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
918; CHECK:       then:
919; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
920; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
921; CHECK-NEXT:    br label [[EXIT:%.*]]
922; CHECK:       else:
923; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
924; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
925; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
926; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
927; CHECK-NEXT:    br label [[EXIT]]
928; CHECK:       exit:
929; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ]
930; CHECK-NEXT:    call void @clobber()
931; CHECK-NEXT:    ret i32 [[P]]
932;
933  %a = alloca i32, align 4
934  store i32 55, ptr %a
935  br i1 %c.1, label %then, label %else
936
937then:
938  store i32 99, ptr %a, align 4
939  call void @escape_writeonly(ptr %a)
940  br label %exit
941
942else:
943  %in.lv.1 = load ptr , ptr %in.ptr, align 2
944  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
945  store i32 99, ptr %a, align 4
946  call void @escape_writeonly(ptr %a)
947  br label %exit
948
949exit:
950  %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ]
951  call void @clobber()
952  ret i32 %p
953}
954
955define i32 @test_not_captured_both_paths_2(ptr %in.ptr, i1 %c.1) {
956; CHECK-LABEL: @test_not_captured_both_paths_2(
957; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
958; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
959; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
960; CHECK:       then:
961; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
962; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
963; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
964; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
965; CHECK-NEXT:    br label [[EXIT:%.*]]
966; CHECK:       else:
967; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
968; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
969; CHECK-NEXT:    br label [[EXIT]]
970; CHECK:       exit:
971; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ELSE]] ]
972; CHECK-NEXT:    call void @clobber()
973; CHECK-NEXT:    ret i32 [[P]]
974;
975  %a = alloca i32, align 4
976  store i32 55, ptr %a
977  br i1 %c.1, label %then, label %else
978
979then:
980  %in.lv.1 = load ptr , ptr %in.ptr, align 2
981  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
982  store i32 99, ptr %a, align 4
983  call void @escape_writeonly(ptr %a)
984  br label %exit
985
986else:
987  store i32 99, ptr %a, align 4
988  call void @escape_writeonly(ptr %a)
989  br label %exit
990
991exit:
992  %p = phi i32 [ %in.lv.2, %then ], [ 0, %else ]
993  call void @clobber()
994  ret i32 %p
995}
996
997define i32 @test_captured_before_store_both_paths_2(ptr %in.ptr, i1 %c.1) {
998; CHECK-LABEL: @test_captured_before_store_both_paths_2(
999; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
1000; CHECK-NEXT:    store i32 55, ptr [[A]], align 4
1001; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
1002; CHECK:       then:
1003; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
1004; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
1005; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
1006; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
1007; CHECK-NEXT:    br label [[EXIT:%.*]]
1008; CHECK:       else:
1009; CHECK-NEXT:    call void @escape_writeonly(ptr [[A]])
1010; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
1011; CHECK-NEXT:    br label [[EXIT]]
1012; CHECK:       exit:
1013; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ELSE]] ]
1014; CHECK-NEXT:    call void @clobber()
1015; CHECK-NEXT:    ret i32 [[P]]
1016;
1017  %a = alloca i32, align 4
1018  store i32 55, ptr %a
1019  br i1 %c.1, label %then, label %else
1020
1021then:
1022  call void @escape_writeonly(ptr %a)
1023  %in.lv.1 = load ptr , ptr %in.ptr, align 2
1024  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
1025  store i32 99, ptr %a, align 4
1026  br label %exit
1027
1028else:
1029  call void @escape_writeonly(ptr %a)
1030  store i32 99, ptr %a, align 4
1031  br label %exit
1032
1033exit:
1034  %p = phi i32 [ %in.lv.2, %then ], [ 0, %else ]
1035  call void @clobber()
1036  ret i32 %p
1037}
1038
1039
1040declare noalias ptr @alloc() nounwind
1041
1042define i32 @test_not_captured_before_load_same_bb_noalias_call(ptr %in.ptr) {
1043; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_call(
1044; CHECK-NEXT:    [[A:%.*]] = call ptr @alloc()
1045; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
1046; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
1047; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
1048; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
1049; CHECK-NEXT:    ret i32 [[IN_LV_2]]
1050;
1051  %a = call ptr @alloc()
1052  store i32 55, ptr %a
1053  %in.lv.1 = load ptr , ptr %in.ptr, align 2
1054  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
1055  store i32 99, ptr %a, align 4
1056  call void @escape_and_clobber(ptr %a)
1057  ret i32 %in.lv.2
1058}
1059
1060define i32 @test_not_captured_before_load_same_bb_noalias_arg(ptr %in.ptr, ptr noalias %a) {
1061; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_arg(
1062; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
1063; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
1064; CHECK-NEXT:    store i32 99, ptr [[A:%.*]], align 4
1065; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
1066; CHECK-NEXT:    ret i32 [[IN_LV_2]]
1067;
1068  store i32 55, ptr %a
1069  %in.lv.1 = load ptr , ptr %in.ptr, align 2
1070  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
1071  store i32 99, ptr %a, align 4
1072  call void @escape_and_clobber(ptr %a)
1073  ret i32 %in.lv.2
1074}
1075
1076define i32 @instruction_captures_multiple_objects(ptr %p.1, ptr %p.2, ptr %p.3, i1 %c) {
1077; CHECK-LABEL: @instruction_captures_multiple_objects(
1078; CHECK-NEXT:  entry:
1079; CHECK-NEXT:    [[A_1:%.*]] = alloca i32, align 4
1080; CHECK-NEXT:    [[A_2:%.*]] = alloca i32, align 4
1081; CHECK-NEXT:    store i32 0, ptr [[P_1:%.*]], align 8
1082; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
1083; CHECK:       then:
1084; CHECK-NEXT:    [[LV_2:%.*]] = load ptr, ptr [[P_2:%.*]], align 8
1085; CHECK-NEXT:    [[LV_2_2:%.*]] = load i32, ptr [[LV_2]], align 4
1086; CHECK-NEXT:    ret i32 [[LV_2_2]]
1087; CHECK:       else:
1088; CHECK-NEXT:    [[LV_3:%.*]] = load ptr, ptr [[P_3:%.*]], align 8
1089; CHECK-NEXT:    [[LV_3_2:%.*]] = load i32, ptr [[LV_3]], align 4
1090; CHECK-NEXT:    call void @capture_and_clobber_multiple(ptr [[A_1]], ptr [[A_2]])
1091; CHECK-NEXT:    ret i32 [[LV_3_2]]
1092;
1093entry:
1094  %a.1 = alloca i32
1095  %a.2 = alloca i32
1096  store i32 0, ptr %p.1, align 8
1097  br i1 %c, label %then, label %else
1098
1099then:
1100  store i32 99, ptr %a.2, align 4
1101  %lv.2 = load ptr, ptr %p.2
1102  %lv.2.2 = load i32, ptr %lv.2
1103  store i32 0, ptr %a.1, align 8
1104  ret i32 %lv.2.2
1105
1106else:
1107  %lv.3 = load ptr, ptr %p.3
1108  %lv.3.2 = load i32, ptr %lv.3
1109  call void @capture_and_clobber_multiple(ptr %a.1, ptr %a.2)
1110  ret i32 %lv.3.2
1111}
1112
1113declare void @capture_and_clobber_multiple(ptr, ptr)
1114
1115declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
1116
1117define i64 @earliest_escape_ptrtoint(ptr %p.1) {
1118; CHECK-LABEL: @earliest_escape_ptrtoint(
1119; CHECK-NEXT:  entry:
1120; CHECK-NEXT:    [[A_1:%.*]] = alloca i64, align 8
1121; CHECK-NEXT:    [[A_2:%.*]] = alloca i64, align 8
1122; CHECK-NEXT:    [[LV_1:%.*]] = load ptr, ptr [[P_1:%.*]], align 8
1123; CHECK-NEXT:    [[LV_2:%.*]] = load i64, ptr [[LV_1]], align 4
1124; CHECK-NEXT:    store ptr [[A_1]], ptr [[P_1]], align 8
1125; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr [[A_2]])
1126; CHECK-NEXT:    ret i64 [[LV_2]]
1127;
1128entry:
1129  %a.1 = alloca i64
1130  %a.2 = alloca i64
1131  store i64 99, ptr %a.1
1132  %lv.1 = load ptr, ptr %p.1
1133  %lv.2 = load i64, ptr %lv.1
1134  store ptr %a.1, ptr %p.1, align 8
1135  %int = ptrtoint ptr %a.2 to i64
1136  store i64 %int , ptr %a.2, align 8
1137  call void @llvm.lifetime.end.p0(i64 8, ptr %a.2)
1138  ret i64 %lv.2
1139}
1140
1141define i32 @test_not_captured_before_load_of_ptrtoint(i64 %in) {
1142; CHECK-LABEL: @test_not_captured_before_load_of_ptrtoint(
1143; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
1144; CHECK-NEXT:    [[IN_PTR:%.*]] = inttoptr i64 [[IN:%.*]] to ptr
1145; CHECK-NEXT:    [[IN_PTR_LOAD:%.*]] = load i32, ptr [[IN_PTR]], align 4
1146; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
1147; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
1148; CHECK-NEXT:    ret i32 [[IN_PTR_LOAD]]
1149;
1150  %a = alloca i32, align 4
1151  store i32 55, ptr %a
1152  %in.ptr = inttoptr i64 %in to ptr
1153  %in.ptr.load = load i32, ptr %in.ptr
1154  store i32 99, ptr %a
1155  call void @escape_and_clobber(ptr %a)
1156  ret i32 %in.ptr.load
1157}
1158
1159declare ptr @getptr()
1160
1161define i32 @test_not_captured_before_load_of_call() {
1162; CHECK-LABEL: @test_not_captured_before_load_of_call(
1163; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
1164; CHECK-NEXT:    [[IN_PTR:%.*]] = call ptr @getptr() #[[ATTR4:[0-9]+]]
1165; CHECK-NEXT:    [[IN_PTR_LOAD:%.*]] = load i32, ptr [[IN_PTR]], align 4
1166; CHECK-NEXT:    store i32 99, ptr [[A]], align 4
1167; CHECK-NEXT:    call void @escape_and_clobber(ptr [[A]])
1168; CHECK-NEXT:    ret i32 [[IN_PTR_LOAD]]
1169;
1170  %a = alloca i32, align 4
1171  store i32 55, ptr %a
1172  %in.ptr = call ptr @getptr() readnone
1173  %in.ptr.load = load i32, ptr %in.ptr
1174  store i32 99, ptr %a
1175  call void @escape_and_clobber(ptr %a)
1176  ret i32 %in.ptr.load
1177}
1178
1179define i32 @test_not_captured_multiple_objects(i1 %c, ptr %in.ptr) {
1180; CHECK-LABEL: @test_not_captured_multiple_objects(
1181; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
1182; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
1183; CHECK-NEXT:    [[O:%.*]] = select i1 [[C:%.*]], ptr [[A]], ptr [[B]]
1184; CHECK-NEXT:    [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2
1185; CHECK-NEXT:    [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2
1186; CHECK-NEXT:    store i32 99, ptr [[O]], align 4
1187; CHECK-NEXT:    call void @escape_and_clobber(ptr [[O]])
1188; CHECK-NEXT:    ret i32 [[IN_LV_2]]
1189;
1190  %a = alloca i32, align 4
1191  %b = alloca i32, align 4
1192  %o = select i1 %c, ptr %a, ptr %b
1193  store i32 55, ptr %o
1194  %in.lv.1 = load ptr , ptr %in.ptr, align 2
1195  %in.lv.2 = load i32 , ptr %in.lv.1, align 2
1196  store i32 99, ptr %o
1197  call void @escape_and_clobber(ptr %o)
1198  ret i32 %in.lv.2
1199}
1200