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"
5 declare void @unknown_func()
6 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
7 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
9 ; Tests where the pointer/object is accessible after the function returns.
11 ; Overwriting store along one path to the exit.
12 define void @accessible_after_return_1(i32* noalias %P, i1 %c) {
13 ; CHECK-LABEL: @accessible_after_return_1(
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:%.*]]
20 ; CHECK-NEXT: br label [[BB3:%.*]]
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]]
26 ; CHECK-NEXT: ret void
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
36 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
37 store i32 1, i32* %arrayidx1, align 4
43 ; Post-dominating store.
44 ; TODO: The memset can be shortened.
45 define void @accessible_after_return_2(i32* noalias %P, i1 %c) {
46 ; CHECK-LABEL: @accessible_after_return_2(
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:%.*]]
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:%.*]]
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]]
61 ; CHECK-NEXT: ret void
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
70 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
71 store i32 1, i32* %arrayidx1, align 4
75 %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1
76 store i32 1, i32* %arrayidx2, align 4
83 ; Stores along both exit paths.
84 define void @accessible_after_return_3(i32* noalias %P, i1 %c) {
85 ; CHECK-LABEL: @accessible_after_return_3(
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:%.*]]
93 ; CHECK-NEXT: br label [[BB3:%.*]]
95 ; CHECK-NEXT: br label [[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
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
114 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
115 store i32 1, i32* %arrayidx1, align 4
120 ; Tests where the pointer/object is *NOT* accessible after the function returns.
122 ; Overwriting store along one path to the exit.
123 define void @alloca_1(i1 %c) {
124 ; CHECK-LABEL: @alloca_1(
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:%.*]]
134 ; CHECK-NEXT: br label [[BB3:%.*]]
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]]
140 ; CHECK-NEXT: ret void
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
152 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
153 store i32 1, i32* %arrayidx1, align 4
159 ; Post-dominating store.
160 define void @alloca_2(i1 %c) {
161 ; CHECK-LABEL: @alloca_2(
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:%.*]]
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:%.*]]
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]]
179 ; CHECK-NEXT: ret void
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
190 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
191 store i32 1, i32* %arrayidx1, align 4
195 %arrayidx2 = getelementptr inbounds i32, i32* %P, i64 1
196 store i32 1, i32* %arrayidx2, align 4
203 ; Stores along both exit paths.
204 define void @alloca_3(i1 %c) {
205 ; CHECK-LABEL: @alloca_3(
207 ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
209 ; CHECK-NEXT: br label [[BB3:%.*]]
211 ; CHECK-NEXT: br label [[BB3]]
213 ; CHECK-NEXT: ret void
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
230 %arrayidx1 = getelementptr inbounds i32, i32* %P, i64 1
231 store i32 1, i32* %arrayidx1, align 4