1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -instcombine -S < %s | FileCheck %s
4 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
5 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
7 declare void @unknown()
9 declare void @f2(i8*, i8*)
10 declare i8* @f3(i8*, i8*)
12 ; Basic case for DSEing a trivially dead writing call
13 define void @test_dead() {
14 ; CHECK-LABEL: @test_dead(
15 ; CHECK-NEXT: ret void
17 %a = alloca i32, align 4
18 %bitcast = bitcast i32* %a to i8*
19 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
23 ; Add in canonical lifetime intrinsics
24 define void @test_lifetime() {
25 ; CHECK-LABEL: @test_lifetime(
26 ; CHECK-NEXT: ret void
28 %a = alloca i32, align 4
29 %bitcast = bitcast i32* %a to i8*
30 call void @llvm.lifetime.start.p0i8(i64 4, i8* %bitcast)
31 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
32 call void @llvm.lifetime.end.p0i8(i64 4, i8* %bitcast)
36 ; Add some unknown calls just to point out that this is use based, not
37 ; instruction order sensitive
38 define void @test_lifetime2() {
39 ; CHECK-LABEL: @test_lifetime2(
40 ; CHECK-NEXT: call void @unknown()
41 ; CHECK-NEXT: call void @unknown()
42 ; CHECK-NEXT: ret void
44 %a = alloca i32, align 4
45 %bitcast = bitcast i32* %a to i8*
46 call void @llvm.lifetime.start.p0i8(i64 4, i8* %bitcast)
48 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
50 call void @llvm.lifetime.end.p0i8(i64 4, i8* %bitcast)
54 ; As long as the result is unused, we can even remove reads of the alloca
55 ; itself since the write will be dropped.
56 define void @test_dead_readwrite() {
57 ; CHECK-LABEL: @test_dead_readwrite(
58 ; CHECK-NEXT: ret void
60 %a = alloca i32, align 4
61 %bitcast = bitcast i32* %a to i8*
62 call void @f(i8* nocapture %bitcast) argmemonly nounwind willreturn
66 define i32 @test_neg_read_after() {
67 ; CHECK-LABEL: @test_neg_read_after(
68 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
69 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
70 ; CHECK-NEXT: call void @f(i8* nocapture nonnull writeonly [[BITCAST]]) #[[ATTR3:[0-9]+]]
71 ; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[A]], align 4
72 ; CHECK-NEXT: ret i32 [[RES]]
74 %a = alloca i32, align 4
75 %bitcast = bitcast i32* %a to i8*
76 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
77 %res = load i32, i32* %a
82 define void @test_neg_infinite_loop() {
83 ; CHECK-LABEL: @test_neg_infinite_loop(
84 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
85 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
86 ; CHECK-NEXT: call void @f(i8* nocapture nonnull writeonly [[BITCAST]]) #[[ATTR4:[0-9]+]]
87 ; CHECK-NEXT: ret void
89 %a = alloca i32, align 4
90 %bitcast = bitcast i32* %a to i8*
91 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind
95 define void @test_neg_throw() {
96 ; CHECK-LABEL: @test_neg_throw(
97 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
98 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
99 ; CHECK-NEXT: call void @f(i8* nocapture nonnull writeonly [[BITCAST]]) #[[ATTR5:[0-9]+]]
100 ; CHECK-NEXT: ret void
102 %a = alloca i32, align 4
103 %bitcast = bitcast i32* %a to i8*
104 call void @f(i8* writeonly nocapture %bitcast) argmemonly willreturn
108 define void @test_neg_extra_write() {
109 ; CHECK-LABEL: @test_neg_extra_write(
110 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
111 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
112 ; CHECK-NEXT: call void @f(i8* nocapture nonnull writeonly [[BITCAST]]) #[[ATTR6:[0-9]+]]
113 ; CHECK-NEXT: ret void
115 %a = alloca i32, align 4
116 %bitcast = bitcast i32* %a to i8*
117 call void @f(i8* writeonly nocapture %bitcast) nounwind willreturn
121 ; In this case, we can't remove a1 because we need to preserve the write to
122 ; a2, and if we leave the call around, we need memory to pass to the first arg.
123 define void @test_neg_unmodeled_write() {
124 ; CHECK-LABEL: @test_neg_unmodeled_write(
125 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
126 ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
127 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
128 ; CHECK-NEXT: [[BITCAST2:%.*]] = bitcast i32* [[A2]] to i8*
129 ; CHECK-NEXT: call void @f2(i8* nocapture nonnull writeonly [[BITCAST]], i8* nonnull [[BITCAST2]]) #[[ATTR3]]
130 ; CHECK-NEXT: ret void
132 %a = alloca i32, align 4
133 %a2 = alloca i32, align 4
134 %bitcast = bitcast i32* %a to i8*
135 %bitcast2 = bitcast i32* %a2 to i8*
136 call void @f2(i8* nocapture writeonly %bitcast, i8* %bitcast2) argmemonly nounwind willreturn
140 define i32 @test_neg_captured_by_call() {
141 ; CHECK-LABEL: @test_neg_captured_by_call(
142 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
143 ; CHECK-NEXT: [[A2:%.*]] = alloca i8*, align 8
144 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
145 ; CHECK-NEXT: [[BITCAST2:%.*]] = bitcast i8** [[A2]] to i8*
146 ; CHECK-NEXT: call void @f2(i8* nonnull writeonly [[BITCAST]], i8* nonnull [[BITCAST2]]) #[[ATTR3]]
147 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8** [[A2]] to i32**
148 ; CHECK-NEXT: [[A_COPY_CAST1:%.*]] = load i32*, i32** [[TMP1]], align 8
149 ; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[A_COPY_CAST1]], align 4
150 ; CHECK-NEXT: ret i32 [[RES]]
152 %a = alloca i32, align 4
153 %a2 = alloca i8*, align 4
154 %bitcast = bitcast i32* %a to i8*
155 %bitcast2 = bitcast i8** %a2 to i8*
156 call void @f2(i8* writeonly %bitcast, i8* %bitcast2) argmemonly nounwind willreturn
157 %a_copy_cast = load i8*, i8** %a2
158 %a_copy = bitcast i8* %a_copy_cast to i32*
159 %res = load i32, i32* %a_copy
163 define i32 @test_neg_captured_before() {
164 ; CHECK-LABEL: @test_neg_captured_before(
165 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
166 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
167 ; CHECK-NEXT: call void @f(i8* nocapture nonnull writeonly [[BITCAST]]) #[[ATTR3]]
168 ; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[A]], align 4
169 ; CHECK-NEXT: ret i32 [[RES]]
171 %a = alloca i32, align 4
172 %a2 = alloca i8*, align 4
173 %bitcast = bitcast i32* %a to i8*
174 %bitcast2 = bitcast i8** %a2 to i8*
175 store i8* %bitcast, i8** %a2
176 call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
177 %a_copy_cast = load i8*, i8** %a2
178 %a_copy = bitcast i8* %a_copy_cast to i32*
179 %res = load i32, i32* %a_copy
183 ; Show that reading from unrelated memory is okay
184 define void @test_unreleated_read() {
185 ; CHECK-LABEL: @test_unreleated_read(
186 ; CHECK-NEXT: ret void
188 %a = alloca i32, align 4
189 %a2 = alloca i32, align 4
190 %bitcast = bitcast i32* %a to i8*
191 %bitcast2 = bitcast i32* %a2 to i8*
192 call void @f2(i8* nocapture writeonly %bitcast, i8* nocapture readonly %bitcast2) argmemonly nounwind willreturn
196 ; Removing a capture is also okay. The capture can only be in the return value
197 ; (which is unused) or written into the dead out parameter.
198 define void @test_unrelated_capture() {
199 ; CHECK-LABEL: @test_unrelated_capture(
200 ; CHECK-NEXT: ret void
202 %a = alloca i32, align 4
203 %a2 = alloca i32, align 4
204 %bitcast = bitcast i32* %a to i8*
205 %bitcast2 = bitcast i32* %a2 to i8*
206 call i8* @f3(i8* nocapture writeonly %bitcast, i8* readonly %bitcast2) argmemonly nounwind willreturn
210 ; Cannot remove call, as %bitcast2 is captured via the return value.
211 define i8 @test_neg_unrelated_capture_used_via_return() {
212 ; CHECK-LABEL: @test_neg_unrelated_capture_used_via_return(
213 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
214 ; CHECK-NEXT: [[A2:%.*]] = alloca i32, align 4
215 ; CHECK-NEXT: [[BITCAST:%.*]] = bitcast i32* [[A]] to i8*
216 ; CHECK-NEXT: [[BITCAST2:%.*]] = bitcast i32* [[A2]] to i8*
217 ; CHECK-NEXT: [[CAPTURE:%.*]] = call i8* @f3(i8* nocapture nonnull writeonly [[BITCAST]], i8* nonnull readonly [[BITCAST2]]) #[[ATTR3]]
218 ; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[CAPTURE]], align 1
219 ; CHECK-NEXT: ret i8 [[V]]
221 %a = alloca i32, align 4
222 %a2 = alloca i32, align 4
223 %bitcast = bitcast i32* %a to i8*
224 %bitcast2 = bitcast i32* %a2 to i8*
225 %capture = call i8* @f3(i8* nocapture writeonly %bitcast, i8* readonly %bitcast2) argmemonly nounwind willreturn
226 %v = load i8, i8* %capture
230 ; As long as the result is unused, we can even remove reads of the alloca
231 ; itself since the write will be dropped.
232 define void @test_self_read() {
233 ; CHECK-LABEL: @test_self_read(
234 ; CHECK-NEXT: ret void
236 %a = alloca i32, align 4
237 %bitcast = bitcast i32* %a to i8*
238 call void @f2(i8* nocapture writeonly %bitcast, i8* nocapture readonly %bitcast) argmemonly nounwind willreturn
243 declare void @removable_readnone() readnone nounwind willreturn
244 declare void @removable_ro() readonly nounwind willreturn
246 define void @test_readnone() {
247 ; CHECK-LABEL: @test_readnone(
248 ; CHECK-NEXT: ret void
250 call void @removable_readnone()
254 define void @test_readnone_with_deopt() {
255 ; CHECK-LABEL: @test_readnone_with_deopt(
256 ; CHECK-NEXT: ret void
258 call void @removable_readnone() [ "deopt"() ]
262 define void @test_readonly() {
263 ; CHECK-LABEL: @test_readonly(
264 ; CHECK-NEXT: ret void
266 call void @removable_ro()
270 define void @test_readonly_with_deopt() {
271 ; CHECK-LABEL: @test_readonly_with_deopt(
272 ; CHECK-NEXT: ret void
274 call void @removable_ro() [ "deopt"() ]