1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -basic-aa -dse -S | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
6 declare void @use(i32 *)
8 ; Tests where the pointer/object is accessible after the function returns.
10 define void @accessible_after_return_1(i32* noalias %P, i1 %c1) {
11 ; CHECK-LABEL: @accessible_after_return_1(
12 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
14 ; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
15 ; CHECK-NEXT: br label [[BB5:%.*]]
17 ; CHECK-NEXT: store i32 3, i32* [[P]], align 4
18 ; CHECK-NEXT: br label [[BB5]]
20 ; CHECK-NEXT: call void @use(i32* [[P]])
21 ; CHECK-NEXT: ret void
24 br i1 %c1, label %bb1, label %bb2
34 call void @use(i32* %P)
38 define void @accessible_after_return_2(i32* noalias %P, i1 %c.1, i1 %c.2) {
39 ; CHECK-LABEL: @accessible_after_return_2(
40 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
42 ; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
43 ; CHECK-NEXT: br label [[BB5:%.*]]
45 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
47 ; CHECK-NEXT: store i32 3, i32* [[P]], align 4
48 ; CHECK-NEXT: br label [[BB5]]
50 ; CHECK-NEXT: store i32 5, i32* [[P]], align 4
51 ; CHECK-NEXT: br label [[BB5]]
53 ; CHECK-NEXT: call void @use(i32* [[P]])
54 ; CHECK-NEXT: ret void
57 br i1 %c.1, label %bb1, label %bb2
63 br i1 %c.2, label %bb3, label %bb4
74 call void @use(i32* %P)
78 ; Cannot remove store in entry block because it is not overwritten on path
80 define void @accessible_after_return_3(i32* noalias %P, i1 %c1) {
81 ; CHECK-LABEL: @accessible_after_return_3(
82 ; CHECK-NEXT: store i32 1, i32* [[P:%.*]], align 4
83 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
85 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
86 ; CHECK-NEXT: br label [[BB5:%.*]]
88 ; CHECK-NEXT: br label [[BB5]]
90 ; CHECK-NEXT: call void @use(i32* [[P]])
91 ; CHECK-NEXT: ret void
94 br i1 %c1, label %bb1, label %bb2
104 call void @use(i32* %P)
108 ; Cannot remove store in entry block because it is not overwritten on path
110 define void @accessible_after_return_4(i32* noalias %P, i1 %c1) {
111 ; CHECK-LABEL: @accessible_after_return_4(
112 ; CHECK-NEXT: store i32 1, i32* [[P:%.*]], align 4
113 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
115 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
116 ; CHECK-NEXT: call void @use(i32* [[P]])
117 ; CHECK-NEXT: br label [[BB5:%.*]]
119 ; CHECK-NEXT: br label [[BB5]]
121 ; CHECK-NEXT: ret void
124 br i1 %c1, label %bb1, label %bb2
128 call void @use(i32* %P)
138 ; Cannot remove the store in entry, as it is not overwritten on all paths to an
139 ; exit (patch including bb4).
140 define void @accessible_after_return5(i32* %P, i1 %c.1, i1 %c.2) {
141 ; CHECK-LABEL: @accessible_after_return5(
143 ; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
144 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
146 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
148 ; CHECK-NEXT: store i32 1, i32* [[P]], align 4
149 ; CHECK-NEXT: br label [[BB5:%.*]]
151 ; CHECK-NEXT: store i32 2, i32* [[P]], align 4
152 ; CHECK-NEXT: br label [[BB5]]
154 ; CHECK-NEXT: br label [[BB5]]
156 ; CHECK-NEXT: ret void
160 br i1 %c.1, label %bb1, label %bb2
163 br i1 %c.2, label %bb3, label %bb4
180 ; Can remove store in entry block, because it is overwritten before each return.
181 define void @accessible_after_return6(i32* %P, i1 %c.1, i1 %c.2) {
182 ; CHECK-LABEL: @accessible_after_return6(
184 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
186 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
188 ; CHECK-NEXT: store i32 1, i32* [[P:%.*]], align 4
189 ; CHECK-NEXT: ret void
191 ; CHECK-NEXT: store i32 2, i32* [[P]], align 4
192 ; CHECK-NEXT: ret void
194 ; CHECK-NEXT: store i32 3, i32* [[P]], align 4
195 ; CHECK-NEXT: ret void
199 br i1 %c.1, label %bb1, label %bb2
202 br i1 %c.2, label %bb3, label %bb4
217 ; Can remove store in bb1, because it is overwritten along each path
218 ; from bb1 to the exit.
219 define void @accessible_after_return7(i32* %P, i1 %c.1, i1 %c.2) {
220 ; CHECK-LABEL: @accessible_after_return7(
222 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
224 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
226 ; CHECK-NEXT: store i32 2, i32* [[P:%.*]], align 4
227 ; CHECK-NEXT: br label [[BB5:%.*]]
229 ; CHECK-NEXT: store i32 1, i32* [[P]], align 4
230 ; CHECK-NEXT: br label [[BB5]]
232 ; CHECK-NEXT: br label [[BB5]]
234 ; CHECK-NEXT: ret void
237 br i1 %c.1, label %bb1, label %bb2
241 br i1 %c.2, label %bb3, label %bb4
259 ; Cannot remove store in entry block, because it is overwritten along each path to
260 ; the exit (entry->bb1->bb4->bb5).
261 define void @accessible_after_return8(i32* %P, i1 %c.1, i1 %c.2) {
262 ; CHECK-LABEL: @accessible_after_return8(
264 ; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
265 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
267 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
269 ; CHECK-NEXT: store i32 1, i32* [[P]], align 4
270 ; CHECK-NEXT: br label [[BB5:%.*]]
272 ; CHECK-NEXT: store i32 2, i32* [[P]], align 4
273 ; CHECK-NEXT: br label [[BB5]]
275 ; CHECK-NEXT: br label [[BB5]]
277 ; CHECK-NEXT: ret void
281 br i1 %c.1, label %bb1, label %bb2
284 br i1 %c.2, label %bb3, label %bb4
301 ; Make sure no stores are removed here. In particular, the store in if.then
302 ; should not be removed.
303 define void @accessible_after_return9(i8* noalias %ptr) {
304 ; CHECK-LABEL: @accessible_after_return9(
306 ; CHECK-NEXT: [[C_0:%.*]] = call i1 @cond()
307 ; CHECK-NEXT: br i1 [[C_0]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
309 ; CHECK-NEXT: store i8 99, i8* [[PTR:%.*]], align 8
310 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
311 ; CHECK-NEXT: br i1 [[C_1]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
313 ; CHECK-NEXT: store i8 20, i8* [[PTR]], align 8
314 ; CHECK-NEXT: br label [[IF_END]]
316 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
317 ; CHECK-NEXT: br i1 [[C_2]], label [[IF_THEN10:%.*]], label [[FOR_INC:%.*]]
319 ; CHECK-NEXT: store i8 0, i8* [[PTR]], align 8
320 ; CHECK-NEXT: br label [[FOR_INC]]
322 ; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond()
323 ; CHECK-NEXT: br i1 [[C_3]], label [[FOR_BODY]], label [[FOR_END]]
325 ; CHECK-NEXT: ret void
328 %c.0 = call i1 @cond()
329 br i1 %c.0, label %for.body, label %for.end
332 store i8 99, i8* %ptr, align 8
333 %c.1 = call i1 @cond()
334 br i1 %c.1, label %if.end, label %if.then
337 store i8 20, i8* %ptr, align 8
341 %c.2 = call i1 @cond()
342 br i1 %c.2, label %if.then10, label %for.inc
345 store i8 0, i8* %ptr, align 8
349 %c.3 = call i1 @cond()
350 br i1 %c.3, label %for.body, label %for.end
356 ; Cannot remove store in entry block because it is not overwritten on path
357 ; entry->bb2->bb4. Also make sure we deal with dead exit blocks without
359 define void @accessible_after_return10_dead_block(i32* %P, i1 %c.1, i1 %c.2) {
360 ; CHECK-LABEL: @accessible_after_return10_dead_block(
362 ; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4
363 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
365 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
367 ; CHECK-NEXT: store i32 1, i32* [[P]], align 4
368 ; CHECK-NEXT: ret void
370 ; CHECK-NEXT: store i32 2, i32* [[P]], align 4
371 ; CHECK-NEXT: ret void
373 ; CHECK-NEXT: ret void
375 ; CHECK-NEXT: ret void
379 br i1 %c.1, label %bb1, label %bb2
382 br i1 %c.2, label %bb3, label %bb4
399 @linenum = external local_unnamed_addr global i32, align 4
401 define void @accessible_after_return11_loop() {
402 ; CHECK-LABEL: @accessible_after_return11_loop(
404 ; CHECK-NEXT: br label [[FOR_BODY_I:%.*]]
406 ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond()
407 ; CHECK-NEXT: br i1 [[C_1]], label [[FOR_BODY_I]], label [[INIT_PARSE_EXIT:%.*]]
408 ; CHECK: init_parse.exit:
409 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull undef)
410 ; CHECK-NEXT: store i32 0, i32* @linenum, align 4
411 ; CHECK-NEXT: br label [[FOR_BODY_I20:%.*]]
412 ; CHECK: for.body.i20:
413 ; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
414 ; CHECK-NEXT: br i1 [[C_2]], label [[FOR_BODY_I20]], label [[EXIT:%.*]]
416 ; CHECK-NEXT: ret void
421 for.body.i: ; preds = %for.body.i, %entry
422 %c.1 = call i1 @cond()
423 br i1 %c.1, label %for.body.i, label %init_parse.exit
425 init_parse.exit: ; preds = %for.body.i
426 store i32 0, i32* @linenum, align 4
427 call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull undef) #2
428 store i32 0, i32* @linenum, align 4
429 br label %for.body.i20
431 for.body.i20: ; preds = %for.body.i20, %init_parse.exit
432 %c.2 = call i1 @cond()
433 br i1 %c.2, label %for.body.i20, label %exit
438 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
439 declare i1 @cond() readnone nounwind
441 ; Tests where the pointer/object is *NOT* accessible after the function returns.
443 ; The store in the entry block can be eliminated, because it is overwritten
444 ; on all paths to the exit.
445 define void @alloca_1(i1 %c1) {
446 ; CHECK-LABEL: @alloca_1(
447 ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
448 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
450 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
451 ; CHECK-NEXT: br label [[BB5:%.*]]
453 ; CHECK-NEXT: store i32 3, i32* [[P]], align 4
454 ; CHECK-NEXT: br label [[BB5]]
456 ; CHECK-NEXT: call void @use(i32* [[P]])
457 ; CHECK-NEXT: ret void
461 br i1 %c1, label %bb1, label %bb2
471 call void @use(i32* %P)
475 ; The store in the entry block can be eliminated, because it is overwritten
476 ; on all paths to the exit.
477 define void @alloca_2(i1 %c.1, i1 %c.2) {
478 ; CHECK-LABEL: @alloca_2(
479 ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
480 ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
482 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
483 ; CHECK-NEXT: br label [[BB5:%.*]]
485 ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
487 ; CHECK-NEXT: store i32 3, i32* [[P]], align 4
488 ; CHECK-NEXT: br label [[BB5]]
490 ; CHECK-NEXT: store i32 5, i32* [[P]], align 4
491 ; CHECK-NEXT: br label [[BB5]]
493 ; CHECK-NEXT: call void @use(i32* [[P]])
494 ; CHECK-NEXT: ret void
498 br i1 %c.1, label %bb1, label %bb2
505 br i1 %c.2, label %bb3, label %bb4
516 call void @use(i32* %P)
520 ; The store in the entry block cannot be eliminated. There's a path from the
521 ; first store to the read in bb5, where the location is not overwritten.
522 define void @alloca_3(i1 %c1) {
523 ; CHECK-LABEL: @alloca_3(
524 ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
525 ; CHECK-NEXT: store i32 1, i32* [[P]], align 4
526 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
528 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
529 ; CHECK-NEXT: br label [[BB5:%.*]]
531 ; CHECK-NEXT: br label [[BB5]]
533 ; CHECK-NEXT: call void @use(i32* [[P]])
534 ; CHECK-NEXT: ret void
538 br i1 %c1, label %bb1, label %bb2
547 call void @use(i32* %P)
551 ; The store in the entry block can be eliminated, because it is overwritten
552 ; before the use in bb1 and not read on other paths to the function exit. The
553 ; object cannot be accessed by the caller.
554 define void @alloca_4(i1 %c1) {
555 ; CHECK-LABEL: @alloca_4(
556 ; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4
557 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
559 ; CHECK-NEXT: store i32 0, i32* [[P]], align 4
560 ; CHECK-NEXT: call void @use(i32* [[P]])
561 ; CHECK-NEXT: br label [[BB5:%.*]]
563 ; CHECK-NEXT: br label [[BB5]]
565 ; CHECK-NEXT: ret void
569 br i1 %c1, label %bb1, label %bb2
573 call void @use(i32* %P)
583 %struct.blam.4 = type { %struct.bar.5, [4 x i8] }
584 %struct.bar.5 = type <{ i64, i64*, i32, i64 }>
586 ; Make sure we do not eliminate the store in %bb.
587 define void @alloca_5(i1 %c) {
588 ; CHECK-LABEL: @alloca_5(
590 ; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_BLAM_4:%.*]], align 8
591 ; CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT_BLAM_4]], %struct.blam.4* [[TMP]], i64 0, i32 0, i32 3
592 ; CHECK-NEXT: [[TMP39:%.*]] = bitcast i64* [[TMP38]] to i64*
593 ; CHECK-NEXT: store i64 0, i64* [[TMP39]], align 4
594 ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB46:%.*]], label [[BB47:%.*]]
596 ; CHECK-NEXT: ret void
598 ; CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT_BLAM_4]], %struct.blam.4* [[TMP]], i64 0, i32 0, i32 2
599 ; CHECK-NEXT: store i32 20, i32* [[TMP48]], align 8
600 ; CHECK-NEXT: br label [[BB52:%.*]]
602 ; CHECK-NEXT: br i1 [[C]], label [[BB68:%.*]], label [[BB59:%.*]]
604 ; CHECK-NEXT: call void @use.2(%struct.blam.4* [[TMP]])
605 ; CHECK-NEXT: ret void
607 ; CHECK-NEXT: ret void
610 %tmp = alloca %struct.blam.4, align 8
611 %tmp36 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 1
612 %tmp37 = bitcast i64** %tmp36 to i8*
613 %tmp38 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 3
614 %tmp39 = bitcast i64* %tmp38 to i64*
615 store i64 0, i64* %tmp39, align 4
616 br i1 %c, label %bb46, label %bb47
618 bb46: ; preds = %bb12
619 call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(20) %tmp37, i8 0, i64 26, i1 false)
622 bb47: ; preds = %bb12
623 %tmp48 = getelementptr inbounds %struct.blam.4, %struct.blam.4* %tmp, i64 0, i32 0, i32 2
624 store i32 20, i32* %tmp48, align 8
627 bb52: ; preds = %bb47
628 br i1 %c, label %bb68, label %bb59
630 bb59: ; preds = %bb52
631 call void @use.2(%struct.blam.4* %tmp)
634 bb68: ; preds = %bb52
638 declare void @use.2(%struct.blam.4*)
640 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)