1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basic-aa -dse -S | FileCheck %s
3
4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
5declare void @unknown_func()
6declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
7declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
8
9; Tests where the pointer/object is accessible after the function returns.
10
11; Overwriting store along one path to the exit.
12define void @accessible_after_return_1(i32* noalias %P, i1 %c) {
13; CHECK-LABEL: @accessible_after_return_1(
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
16; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
17; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i1 false)
18; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
19; CHECK:       bb1:
20; CHECK-NEXT:    br label [[BB3:%.*]]
21; CHECK:       bb2:
22; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
23; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
24; CHECK-NEXT:    br label [[BB3]]
25; CHECK:       bb3:
26; CHECK-NEXT:    ret void
27;
28entry:
29  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
30  %p3 = bitcast i32* %arrayidx0 to i8*
31  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
32  br i1 %c, label %bb1, label %bb2
33bb1:
34  br label %bb3
35bb2:
36  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
37  store i32 1, i32* %arrayidx1, align 4
38  br label %bb3
39bb3:
40  ret void
41}
42
43; Post-dominating store.
44; TODO: The memset can be shortened.
45define void @accessible_after_return_2(i32* noalias %P, i1 %c) {
46; CHECK-LABEL: @accessible_after_return_2(
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
49; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
50; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i1 false)
51; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
52; CHECK:       bb1:
53; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
54; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
55; CHECK-NEXT:    br label [[BB3:%.*]]
56; CHECK:       bb2:
57; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
58; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX2]], align 4
59; CHECK-NEXT:    br label [[BB3]]
60; CHECK:       bb3:
61; CHECK-NEXT:    ret void
62;
63entry:
64  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
65  %p3 = bitcast i32* %arrayidx0 to i8*
66  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
67  br i1 %c, label %bb1, label %bb2
68
69bb1:
70  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
71  store i32 1, i32* %arrayidx1, align 4
72  br label %bb3
73
74bb2:
75  %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1
76  store i32 1, i32* %arrayidx2, align 4
77  br label %bb3
78
79bb3:
80  ret void
81}
82
83; Stores along  both exit paths.
84define void @accessible_after_return_3(i32* noalias %P, i1 %c) {
85; CHECK-LABEL: @accessible_after_return_3(
86; CHECK-NEXT:  entry:
87; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
88; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
89; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
90; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
91; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
92; CHECK:       bb1:
93; CHECK-NEXT:    br label [[BB3:%.*]]
94; CHECK:       bb2:
95; CHECK-NEXT:    br label [[BB3]]
96; CHECK:       bb3:
97; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
98; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
99; CHECK-NEXT:    ret void
100;
101entry:
102  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
103  %p3 = bitcast i32* %arrayidx0 to i8*
104  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
105  br i1 %c, label %bb1, label %bb2
106
107bb1:
108  br label %bb3
109
110bb2:
111  br label %bb3
112
113bb3:
114  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
115  store i32 1, i32* %arrayidx1, align 4
116  ret void
117}
118
119
120; Tests where the pointer/object is *NOT* accessible after the function returns.
121
122; Overwriting store along one path to the exit.
123define void @alloca_1(i1 %c) {
124; CHECK-LABEL: @alloca_1(
125; CHECK-NEXT:  entry:
126; CHECK-NEXT:    [[P_ALLOCA:%.*]] = alloca [32 x i32], align 4
127; CHECK-NEXT:    [[P:%.*]] = bitcast [32 x i32]* [[P_ALLOCA]] to i32*
128; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
129; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
130; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
131; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
132; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
133; CHECK:       bb1:
134; CHECK-NEXT:    br label [[BB3:%.*]]
135; CHECK:       bb2:
136; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
137; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
138; CHECK-NEXT:    br label [[BB3]]
139; CHECK:       bb3:
140; CHECK-NEXT:    ret void
141;
142entry:
143  %P.alloca = alloca [32 x i32]
144  %P = bitcast [32 x i32]* %P.alloca to i32*
145  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
146  %p3 = bitcast i32* %arrayidx0 to i8*
147  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
148  br i1 %c, label %bb1, label %bb2
149bb1:
150  br label %bb3
151bb2:
152  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
153  store i32 1, i32* %arrayidx1, align 4
154  br label %bb3
155bb3:
156  ret void
157}
158
159; Post-dominating store.
160define void @alloca_2(i1 %c) {
161; CHECK-LABEL: @alloca_2(
162; CHECK-NEXT:  entry:
163; CHECK-NEXT:    [[P_ALLOCA:%.*]] = alloca [32 x i32], align 4
164; CHECK-NEXT:    [[P:%.*]] = bitcast [32 x i32]* [[P_ALLOCA]] to i32*
165; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
166; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
167; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
168; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
169; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
170; CHECK:       bb1:
171; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
172; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
173; CHECK-NEXT:    br label [[BB3:%.*]]
174; CHECK:       bb2:
175; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
176; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX2]], align 4
177; CHECK-NEXT:    br label [[BB3]]
178; CHECK:       bb3:
179; CHECK-NEXT:    ret void
180;
181entry:
182  %P.alloca = alloca [32 x i32]
183  %P = bitcast [32 x i32]* %P.alloca to i32*
184  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
185  %p3 = bitcast i32* %arrayidx0 to i8*
186  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
187  br i1 %c, label %bb1, label %bb2
188
189bb1:
190  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
191  store i32 1, i32* %arrayidx1, align 4
192  br label %bb3
193
194bb2:
195  %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1
196  store i32 1, i32* %arrayidx2, align 4
197  br label %bb3
198
199bb3:
200  ret void
201}
202
203; Stores along  both exit paths.
204define void @alloca_3(i1 %c) {
205; CHECK-LABEL: @alloca_3(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
208; CHECK:       bb1:
209; CHECK-NEXT:    br label [[BB3:%.*]]
210; CHECK:       bb2:
211; CHECK-NEXT:    br label [[BB3]]
212; CHECK:       bb3:
213; CHECK-NEXT:    ret void
214;
215entry:
216  %P.alloca = alloca [32 x i32]
217  %P = bitcast [32 x i32]* %P.alloca to i32*
218  %arrayidx0 = getelementptr inbounds i32, i32* %P, i64 1
219  %p3 = bitcast i32* %arrayidx0 to i8*
220  call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
221  br i1 %c, label %bb1, label %bb2
222
223bb1:
224  br label %bb3
225
226bb2:
227  br label %bb3
228
229bb3:
230  %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
231  store i32 1, i32* %arrayidx1, align 4
232  ret void
233}
234