[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / lifetime.ll
blobc54f1593a93df461a7b35e3d20ace2a28c0ec069
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-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
6 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
7 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
8 declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i1) nounwind
10 define void @test1() {
11 ; CHECK-LABEL: @test1(
12 ; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 1
13 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[A]])
14 ; CHECK-NEXT:    ret void
16   %A = alloca i8
18   store i8 0, i8* %A  ;; Written to by memset
19   call void @llvm.lifetime.end.p0i8(i64 1, i8* %A)
21   call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 -1, i1 false)
23   ret void
26 define void @test2(i32* %P) {
27 ; CHECK-LABEL: @test2(
28 ; CHECK-NEXT:    [[Q:%.*]] = getelementptr i32, i32* [[P:%.*]], i32 1
29 ; CHECK-NEXT:    [[R:%.*]] = bitcast i32* [[Q]] to i8*
30 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 4, i8* [[R]])
31 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 4, i8* [[R]])
32 ; CHECK-NEXT:    ret void
34   %Q = getelementptr i32, i32* %P, i32 1
35   %R = bitcast i32* %Q to i8*
36   call void @llvm.lifetime.start.p0i8(i64 4, i8* %R)
37   store i32 0, i32* %Q  ;; This store is dead.
38   call void @llvm.lifetime.end.p0i8(i64 4, i8* %R)
39   ret void
42 ; lifetime.end only marks the first two bytes of %A as dead. Make sure
43 ; `store i8 20, i8* %A.2 is not removed.
44 define void @test3_lifetime_end_partial() {
45 ; CHECK-LABEL: @test3_lifetime_end_partial(
46 ; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
47 ; CHECK-NEXT:    [[A_0:%.*]] = bitcast i32* [[A]] to i8*
48 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]])
49 ; CHECK-NEXT:    [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1
50 ; CHECK-NEXT:    [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2
51 ; CHECK-NEXT:    store i8 20, i8* [[A_2]], align 1
52 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]])
53 ; CHECK-NEXT:    call void @use(i8* [[A_1]])
54 ; CHECK-NEXT:    ret void
56   %A = alloca i32
58   %A.0 = bitcast i32 * %A to i8*
59   call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0)
60   %A.1 = getelementptr i8, i8* %A.0, i64 1
61   %A.2 = getelementptr i8, i8* %A.0, i64 2
63   store i8 0, i8* %A.0
64   store i8 10, i8* %A.1
65   store i8 20, i8* %A.2
67   call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0)
68   call void @use(i8* %A.1)
69   ret void
72 ; lifetime.end only marks the first two bytes of %A as dead. Make sure
73 ; `store i8 20, i8* %A.2 is not removed.
74 define void @test4_lifetime_end_partial_loop() {
75 ; CHECK-LABEL: @test4_lifetime_end_partial_loop(
76 ; CHECK-NEXT:  entry:
77 ; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
78 ; CHECK-NEXT:    [[A_0:%.*]] = bitcast i32* [[A]] to i8*
79 ; CHECK-NEXT:    br label [[LOOP:%.*]]
80 ; CHECK:       loop:
81 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
82 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]])
83 ; CHECK-NEXT:    [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1
84 ; CHECK-NEXT:    [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2
85 ; CHECK-NEXT:    call void @use(i8* [[A_1]])
86 ; CHECK-NEXT:    store i8 20, i8* [[A_2]], align 1
87 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]])
88 ; CHECK-NEXT:    [[IV_NEXT]] = add i8 [[IV]], 10
89 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i8 [[IV_NEXT]], 10
90 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]]
91 ; CHECK:       exit:
92 ; CHECK-NEXT:    ret void
94 entry:
95   %A = alloca i32
97   %A.0 = bitcast i32 * %A to i8*
98   br label %loop
100 loop:
101   %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
102   call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0)
103   %A.1 = getelementptr i8, i8* %A.0, i64 1
104   %A.2 = getelementptr i8, i8* %A.0, i64 2
106   call void @use(i8* %A.1)
108   store i8 20, i8* %A.2
109   store i8 10, i8* %A.1
110   store i8 0, i8* %A.0
111   call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0)
113   %iv.next = add i8 %iv, 10
114   %exitcond = icmp eq i8 %iv.next, 10
115   br i1 %exitcond, label %exit, label %loop
117 exit:
118   ret void
121 ; lifetime.end only marks the first two bytes of %A as dead. Make sure
122 ; `store i8 20, i8* %A.2 is not removed.
123 define void @test5_lifetime_end_partial(i32* %A) {
124 ; CHECK-LABEL: @test5_lifetime_end_partial(
125 ; CHECK-NEXT:    [[A_0:%.*]] = bitcast i32* [[A:%.*]] to i8*
126 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 2, i8* [[A_0]])
127 ; CHECK-NEXT:    [[A_1:%.*]] = getelementptr i8, i8* [[A_0]], i64 1
128 ; CHECK-NEXT:    [[A_2:%.*]] = getelementptr i8, i8* [[A_0]], i64 2
129 ; CHECK-NEXT:    store i8 20, i8* [[A_2]], align 1
130 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 2, i8* [[A_0]])
131 ; CHECK-NEXT:    call void @use(i8* [[A_1]])
132 ; CHECK-NEXT:    store i8 30, i8* [[A_1]], align 1
133 ; CHECK-NEXT:    store i8 40, i8* [[A_2]], align 1
134 ; CHECK-NEXT:    ret void
137   %A.0 = bitcast i32 * %A to i8*
138   call void @llvm.lifetime.start.p0i8(i64 2, i8* %A.0)
139   %A.1 = getelementptr i8, i8* %A.0, i64 1
140   %A.2 = getelementptr i8, i8* %A.0, i64 2
142   store i8 0, i8* %A.0
143   store i8 10, i8* %A.1
144   store i8 20, i8* %A.2
146   call void @llvm.lifetime.end.p0i8(i64 2, i8* %A.0)
148   call void @use(i8* %A.1)
149   store i8 30, i8* %A.1
150   store i8 40, i8* %A.2
151   ret void
154 declare void @use(i8*) readonly