[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / trivial-dse-calls.ll
blob29755575ddd98037ab4d8e8d279aa1a06072fb11
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()
8 declare void @f(i8*)
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
20   ret void
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)
33   ret void
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)
47   call void @unknown()
48   call void @f(i8* writeonly nocapture %bitcast) argmemonly nounwind willreturn
49   call void @unknown()
50   call void @llvm.lifetime.end.p0i8(i64 4, i8* %bitcast)
51   ret void
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
63   ret void
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
78   ret i32 %res
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
92   ret void
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
105   ret void
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
118   ret void
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
137   ret void
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
160   ret i32 %res
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
180   ret i32 %res
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
193   ret void
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
207   ret void
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
227   ret i8 %v
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
239   ret void
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()
251   ret void
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"() ]
259   ret void
262 define void @test_readonly() {
263 ; CHECK-LABEL: @test_readonly(
264 ; CHECK-NEXT:    ret void
266   call void @removable_ro()
267   ret void
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"() ]
275   ret void