[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / libcalls.ll
blob619287748d3e3750722c5c1937a62ce2e03e594e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -inferattrs -basic-aa -dse | FileCheck %s
3 ; RUN: opt < %s -S -aa-pipeline=basic-aa -passes=inferattrs,dse | FileCheck %s
5 target triple = "x86_64-unknown-linux-gnu"
7 declare i8* @strcpy(i8* %dest, i8* %src) nounwind
8 define void @test1(i8* %src) {
9 ; CHECK-LABEL: @test1(
10 ; CHECK-NEXT:    ret void
12   %B = alloca [16 x i8]
13   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
14   %call = call i8* @strcpy(i8* %dest, i8* %src)
15   ret void
18 define void @strcpy_reads_after(i8* noalias %dest, i8* %src) {
19 ; CHECK-LABEL: @strcpy_reads_after(
20 ; CHECK-NEXT:    [[SRC_2:%.*]] = getelementptr inbounds i8, i8* [[SRC:%.*]], i64 1
21 ; CHECK-NEXT:    store i8 99, i8* [[SRC_2]], align 1
22 ; CHECK-NEXT:    [[SRC_1:%.*]] = getelementptr inbounds i8, i8* [[SRC]], i64 1
23 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @strcpy(i8* [[DEST:%.*]], i8* [[SRC_1]])
24 ; CHECK-NEXT:    store i8 2, i8* [[SRC]], align 1
25 ; CHECK-NEXT:    store i8 2, i8* [[SRC_2]], align 1
26 ; CHECK-NEXT:    ret void
28   %src.2 = getelementptr inbounds i8, i8* %src, i64 1
29   store i8 1, i8* %src
30   store i8 99, i8* %src.2
31   %src.1 = getelementptr inbounds i8, i8* %src, i64 1
32   %call = call i8* @strcpy(i8* %dest, i8* %src.1)
33   store i8 2, i8* %src
34   store i8 2, i8* %src.2
35   ret void
38 declare i8* @strncpy(i8* %dest, i8* %src, i64 %n) nounwind
39 define void @test2(i8* %src) {
40 ; CHECK-LABEL: @test2(
41 ; CHECK-NEXT:    ret void
43   %B = alloca [16 x i8]
44   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
45   %call = call i8* @strncpy(i8* %dest, i8* %src, i64 12)
46   ret void
49 declare i8* @strcat(i8* %dest, i8* %src) nounwind
50 define void @test3(i8* %src) {
51 ; CHECK-LABEL: @test3(
52 ; CHECK-NEXT:    ret void
54   %B = alloca [16 x i8]
55   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
56   %call = call i8* @strcat(i8* %dest, i8* %src)
57   ret void
60 define void @test_strcat_with_lifetime(i8* %src) {
61 ; CHECK-LABEL: @test_strcat_with_lifetime(
62 ; CHECK-NEXT:    [[B:%.*]] = alloca [16 x i8], align 1
63 ; CHECK-NEXT:    [[B_CAST:%.*]] = bitcast [16 x i8]* [[B]] to i8*
64 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[B_CAST]])
65 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[B_CAST]])
66 ; CHECK-NEXT:    ret void
68   %B = alloca [16 x i8]
69   %B.cast = bitcast [16 x i8]* %B to i8*
70   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %B.cast)
71   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
72   %call = call i8* @strcat(i8* %dest, i8* %src)
73   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %B.cast)
74   ret void
77 define void @test_strcat_with_lifetime_nonlocal(i8* %dest, i8* %src) {
78 ; CHECK-LABEL: @test_strcat_with_lifetime_nonlocal(
79 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[DEST:%.*]])
80 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @strcat(i8* [[DEST]], i8* [[SRC:%.*]])
81 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[DEST]])
82 ; CHECK-NEXT:    ret void
84   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %dest)
85   %call = call i8* @strcat(i8* %dest, i8* %src)
86   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %dest)
87   ret void
90 declare i8* @strncat(i8* %dest, i8* %src, i64 %n) nounwind
91 define void @test4(i8* %src) {
92 ; CHECK-LABEL: @test4(
93 ; CHECK-NEXT:    ret void
95   %B = alloca [16 x i8]
96   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
97   %call = call i8* @strncat(i8* %dest, i8* %src, i64 12)
98   ret void
101 define void @test5(i8* nocapture %src) {
102 ; CHECK-LABEL: @test5(
103 ; CHECK-NEXT:    ret void
105   %dest = alloca [100 x i8], align 16
106   %arraydecay = getelementptr inbounds [100 x i8], [100 x i8]* %dest, i64 0, i64 0
107   %call = call i8* @strcpy(i8* %arraydecay, i8* %src)
108   %arrayidx = getelementptr inbounds i8, i8* %call, i64 10
109   store i8 97, i8* %arrayidx, align 1
110   ret void
113 declare void @user(i8* %p)
114 define void @test6(i8* %src) {
115 ; CHECK-LABEL: @test6(
116 ; CHECK-NEXT:    [[B:%.*]] = alloca [16 x i8], align 1
117 ; CHECK-NEXT:    [[DEST:%.*]] = getelementptr inbounds [16 x i8], [16 x i8]* [[B]], i64 0, i64 0
118 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @strcpy(i8* [[DEST]], i8* [[SRC:%.*]])
119 ; CHECK-NEXT:    call void @user(i8* [[DEST]])
120 ; CHECK-NEXT:    ret void
122   %B = alloca [16 x i8]
123   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
124   %call = call i8* @strcpy(i8* %dest, i8* %src)
125   call void @user(i8* %dest)
126   ret void
129 declare i32 @memcmp(i8*, i8*, i64)
131 define i32 @test_memcmp_const_size(i8* noalias %foo) {
132 ; CHECK-LABEL: @test_memcmp_const_size(
133 ; CHECK-NEXT:  entry:
134 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
135 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
136 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
137 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
138 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
139 ; CHECK-NEXT:    [[RES:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2)
140 ; CHECK-NEXT:    ret i32 [[RES]]
142 entry:
143   %stack = alloca [10 x i8]
144   %stack.ptr = bitcast [10 x i8]* %stack to i8*
145   store i8 49, i8* %stack.ptr, align 1
146   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
147   store i8 50, i8* %gep.1, align 1
148   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
149   store i8 51, i8* %gep.2, align 1
150   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
151   store i8 52, i8* %gep.3, align 1
152   %res = call i32 @memcmp(i8* nonnull dereferenceable(2) %foo, i8* nonnull dereferenceable(2) %stack.ptr, i64 2)
153   ret i32 %res
156 define i32 @test_memcmp_variable_size(i8* noalias %foo, i64 %n) {
157 ; CHECK-LABEL: @test_memcmp_variable_size(
158 ; CHECK-NEXT:  entry:
159 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
160 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
161 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
162 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
163 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
164 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
165 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
166 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
167 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
168 ; CHECK-NEXT:    [[RES:%.*]] = call i32 @memcmp(i8* nonnull [[FOO:%.*]], i8* nonnull [[STACK_PTR]], i64 [[N:%.*]])
169 ; CHECK-NEXT:    ret i32 [[RES]]
171 entry:
172   %stack = alloca [10 x i8]
173   %stack.ptr = bitcast [10 x i8]* %stack to i8*
174   store i8 49, i8* %stack.ptr, align 1
175   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
176   store i8 50, i8* %gep.1, align 1
177   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
178   store i8 51, i8* %gep.2, align 1
179   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
180   store i8 52, i8* %gep.3, align 1
181   %res = call i32 @memcmp(i8* nonnull %foo, i8* nonnull %stack.ptr, i64 %n)
182   ret i32 %res
185 declare i32 @bcmp(i8*, i8*, i64)
187 define i1 @test_bcmp_const_size(i8* noalias %foo) {
188 ; CHECK-LABEL: @test_bcmp_const_size(
189 ; CHECK-NEXT:  entry:
190 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
191 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
192 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
193 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
194 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
195 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @bcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2)
196 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[CALL]], 0
197 ; CHECK-NEXT:    ret i1 [[RES]]
199 entry:
200   %stack = alloca [10 x i8]
201   %stack.ptr = bitcast [10 x i8]* %stack to i8*
202   store i8 49, i8* %stack.ptr, align 1
203   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
204   store i8 50, i8* %gep.1, align 1
205   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
206   store i8 51, i8* %gep.2, align 1
207   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
208   store i8 52, i8* %gep.3, align 1
209   %call = call i32 @bcmp(i8* nonnull dereferenceable(2) %foo, i8* nonnull dereferenceable(2) %stack.ptr, i64 2)
210   %res = icmp eq i32 %call, 0
211   ret i1 %res
214 define i1 @test_bcmp_variable_size(i8* noalias %foo, i64 %n) {
215 ; CHECK-LABEL: @test_bcmp_variable_size(
216 ; CHECK-NEXT:  entry:
217 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
218 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
219 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
220 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
221 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
222 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
223 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
224 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
225 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
226 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @bcmp(i8* nonnull [[FOO:%.*]], i8* nonnull [[STACK_PTR]], i64 [[N:%.*]])
227 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[CALL]], 0
228 ; CHECK-NEXT:    ret i1 [[RES]]
230 entry:
231   %stack = alloca [10 x i8]
232   %stack.ptr = bitcast [10 x i8]* %stack to i8*
233   store i8 49, i8* %stack.ptr, align 1
234   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
235   store i8 50, i8* %gep.1, align 1
236   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
237   store i8 51, i8* %gep.2, align 1
238   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
239   store i8 52, i8* %gep.3, align 1
240   %call = call i32 @bcmp(i8* nonnull %foo, i8* nonnull %stack.ptr, i64 %n)
241   %res = icmp eq i32 %call, 0
242   ret i1 %res
245 declare i8* @memchr(i8*, i32, i64)
247 define i8* @test_memchr_const_size() {
248 ; CHECK-LABEL: @test_memchr_const_size(
249 ; CHECK-NEXT:  entry:
250 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
251 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
252 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
253 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
254 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
255 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 2)
256 ; CHECK-NEXT:    ret i8* [[CALL]]
258 entry:
259   %stack = alloca [10 x i8]
260   %stack.ptr = bitcast [10 x i8]* %stack to i8*
261   store i8 49, i8* %stack.ptr, align 1
262   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
263   store i8 50, i8* %gep.1, align 1
264   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
265   store i8 51, i8* %gep.2, align 1
266   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
267   store i8 52, i8* %gep.3, align 1
268   %call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 2)
269   ret i8* %call
272 define i8* @test_memchr_variable_size(i64 %n) {
273 ; CHECK-LABEL: @test_memchr_variable_size(
274 ; CHECK-NEXT:  entry:
275 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
276 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
277 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
278 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
279 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
280 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
281 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
282 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 4
283 ; CHECK-NEXT:    store i8 52, i8* [[GEP]], align 1
284 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
285 ; CHECK-NEXT:    ret i8* [[CALL]]
287 entry:
288   %stack = alloca [10 x i8]
289   %stack.ptr = bitcast [10 x i8]* %stack to i8*
290   store i8 49, i8* %stack.ptr, align 1
291   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
292   store i8 50, i8* %gep.1, align 1
293   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
294   store i8 51, i8* %gep.2, align 1
295   %gep = getelementptr i8, i8* %stack.ptr, i64 4
296   store i8 52, i8* %gep, align 1
297   %call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 %n)
298   ret i8* %call
301 declare i8* @memccpy(i8*, i8*, i32, i64)
303 define i8* @test_memccpy_const_size(i8* %foo) {
304 ; CHECK-LABEL: @test_memccpy_const_size(
305 ; CHECK-NEXT:  entry:
306 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
307 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
308 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
309 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
310 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
311 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 2)
312 ; CHECK-NEXT:    ret i8* [[RES]]
314 entry:
315   %stack = alloca [10 x i8]
316   %stack.ptr = bitcast [10 x i8]* %stack to i8*
317   store i8 49, i8* %stack.ptr, align 1
318   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
319   store i8 50, i8* %gep.1, align 1
320   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
321   store i8 51, i8* %gep.2, align 1
322   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
323   store i8 52, i8* %gep.3, align 1
324   %res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 2)
325   ret i8* %res
328 define i8* @test_memccpy_variable_size(i8* %foo, i64 %n) {
329 ; CHECK-LABEL: @test_memccpy_variable_size(
330 ; CHECK-NEXT:  entry:
331 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
332 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
333 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
334 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
335 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
336 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
337 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
338 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
339 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
340 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
341 ; CHECK-NEXT:    ret i8* [[RES]]
343 entry:
344   %stack = alloca [10 x i8]
345   %stack.ptr = bitcast [10 x i8]* %stack to i8*
346   store i8 49, i8* %stack.ptr, align 1
347   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
348   store i8 50, i8* %gep.1, align 1
349   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
350   store i8 51, i8* %gep.2, align 1
351   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
352   store i8 52, i8* %gep.3, align 1
353   %res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 %n)
354   ret i8* %res
357 ; Make sure memccpy does not kill any stores, because it is not known how many
358 ; bytes are written.
359 define i8* @test_memccpy_const_size_does_not_kill_stores(i8* noalias %dest, i8* noalias %foo) {
360 ; CHECK-LABEL: @test_memccpy_const_size_does_not_kill_stores(
361 ; CHECK-NEXT:  entry:
362 ; CHECK-NEXT:    store i8 49, i8* [[DEST:%.*]], align 1
363 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[DEST]], i64 1
364 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
365 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[DEST]], i64 2
366 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
367 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[DEST]], i64 3
368 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
369 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[DEST]], i8* [[FOO:%.*]], i32 42, i64 2)
370 ; CHECK-NEXT:    ret i8* [[RES]]
372 entry:
373   store i8 49, i8* %dest, align 1
374   %gep.1 = getelementptr i8, i8* %dest, i64 1
375   store i8 50, i8* %gep.1, align 1
376   %gep.2 = getelementptr i8, i8* %dest, i64 2
377   store i8 51, i8* %gep.2, align 1
378   %gep.3 = getelementptr i8, i8* %dest, i64 3
379   store i8 52, i8* %gep.3, align 1
380   %res = call i8* @memccpy(i8* %dest, i8* %foo, i32 42, i64 2)
381   ret i8* %res
384 define void @dse_strcpy(i8* nocapture readonly %src) {
385 ; CHECK-LABEL: @dse_strcpy(
386 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
387 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
388 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
389 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
390 ; CHECK-NEXT:    ret void
392   %a = alloca [256 x i8], align 16
393   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
394   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
395   call i8* @strcpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src)
396   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
397   ret void
400 define void @dse_strncpy(i8* nocapture readonly %src) {
401 ; CHECK-LABEL: @dse_strncpy(
402 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
403 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
404 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
405 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
406 ; CHECK-NEXT:    ret void
408   %a = alloca [256 x i8], align 16
409   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
410   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
411   call i8* @strncpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6)
412   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
413   ret void
416 define void @dse_strcat(i8* nocapture readonly %src) {
417 ; CHECK-LABEL: @dse_strcat(
418 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
419 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
420 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
421 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
422 ; CHECK-NEXT:    ret void
424   %a = alloca [256 x i8], align 16
425   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
426   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
427   call i8* @strcat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src)
428   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
429   ret void
432 define void @dse_strncat(i8* nocapture readonly %src) {
433 ; CHECK-LABEL: @dse_strncat(
434 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
435 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
436 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
437 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
438 ; CHECK-NEXT:    ret void
440   %a = alloca [256 x i8], align 16
441   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
442   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
443   call i8* @strncat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6)
444   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
445   ret void
448 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
449 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
451 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
453 ; Test that strncpy/memset overwriting each other is optimized out
455 ; strncpy -> memset, full overwrite
456 define void @dse_strncpy_test1(i8* noalias %out, i8* noalias %in) {
457 ; CHECK-LABEL: @dse_strncpy_test1(
458 ; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* [[OUT:%.*]], i8 42, i64 100, i1 false)
459 ; CHECK-NEXT:    ret void
461   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100)
462   tail call void @llvm.memset.p0i8.i64(i8* %out, i8 42, i64 100, i1 false)
463   ret void
466 declare i8* @__memset_chk(i8* writeonly, i32, i64, i64) argmemonly
468 ; strncpy -> __memset_chk, full overwrite
469 define void @dse_strncpy_memset_chk_test1(i8* noalias %out, i8* noalias %in, i64 %n) {
470 ; CHECK-LABEL: @dse_strncpy_memset_chk_test1(
471 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT:%.*]], i8* [[IN:%.*]], i64 100)
472 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
473 ; CHECK-NEXT:    ret void
475   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100)
476   %call.2 = tail call i8* @__memset_chk(i8* %out, i32 42, i64 100, i64 %n)
477   ret void
480 declare void @use(i8*)
482 define void @dse_memset_chk_cannot_eliminates_store(i8* %out, i64 %n) {
483 ; CHECK-LABEL: @dse_memset_chk_cannot_eliminates_store(
484 ; CHECK-NEXT:    store i8 10, i8* [[OUT:%.*]], align 1
485 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
486 ; CHECK-NEXT:    ret void
488   store i8 10, i8* %out
489   %call.2 = tail call i8* @__memset_chk(i8* %out, i32 42, i64 100, i64 %n)
490   ret void
493 define void @dse_memset_chk_eliminates_store_local_object_escapes_after(i64 %n) {
494 ; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_after(
495 ; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
496 ; CHECK-NEXT:    [[OUT:%.*]] = bitcast [200 x i8]* [[A]] to i8*
497 ; CHECK-NEXT:    store i8 10, i8* [[OUT]], align 1
498 ; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, i8* [[OUT]], i64 100
499 ; CHECK-NEXT:    store i8 10, i8* [[OUT_100]], align 1
500 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
501 ; CHECK-NEXT:    call void @use(i8* [[OUT]])
502 ; CHECK-NEXT:    ret void
504   %a = alloca [200 x i8]
505   %out = bitcast [200 x i8]* %a to i8*
506   store i8 10, i8* %out
507   %out.100 = getelementptr i8, i8* %out, i64 100
508   store i8 10, i8* %out.100
509   %call.2 = tail call i8* @__memset_chk(i8* %out, i32 42, i64 100, i64 %n)
510   call void @use(i8* %out)
511   ret void
514 define void @dse_memset_chk_eliminates_store_local_object_escapes_before(i64 %n) {
515 ; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_before(
516 ; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
517 ; CHECK-NEXT:    [[OUT:%.*]] = bitcast [200 x i8]* [[A]] to i8*
518 ; CHECK-NEXT:    call void @use(i8* [[OUT]])
519 ; CHECK-NEXT:    store i8 10, i8* [[OUT]], align 1
520 ; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, i8* [[OUT]], i64 100
521 ; CHECK-NEXT:    store i8 0, i8* [[OUT_100]], align 1
522 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
523 ; CHECK-NEXT:    call void @use(i8* [[OUT]])
524 ; CHECK-NEXT:    ret void
526   %a = alloca [200 x i8]
527   %out = bitcast [200 x i8]* %a to i8*
528   call void @use(i8* %out)
529   store i8 10, i8* %out
530   %out.100 = getelementptr i8, i8* %out, i64 100
531   store i8 0, i8* %out.100
532   %call.2 = tail call i8* @__memset_chk(i8* %out, i32 42, i64 100, i64 %n)
533   call void @use(i8* %out)
534   ret void
537 ; strncpy -> memset, partial overwrite
538 define void @dse_strncpy_test2(i8* noalias %out, i8* noalias %in) {
539 ; CHECK-LABEL: @dse_strncpy_test2(
540 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT:%.*]], i8* [[IN:%.*]], i64 100)
541 ; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* [[OUT]], i8 42, i64 99, i1 false)
542 ; CHECK-NEXT:    ret void
544   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100)
545   tail call void @llvm.memset.p0i8.i64(i8* %out, i8 42, i64 99, i1 false)
546   ret void
549 ; strncpy -> memset_chk, partial overwrite
550 define void @dse_strncpy_memset_chk_test2(i8* noalias %out, i8* noalias %in, i64 %n) {
551 ; CHECK-LABEL: @dse_strncpy_memset_chk_test2(
552 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT:%.*]], i8* [[IN:%.*]], i64 100)
553 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT]], i32 42, i64 99, i64 [[N:%.*]])
554 ; CHECK-NEXT:    ret void
556   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100)
557   %call.2 = tail call i8* @__memset_chk(i8* %out, i32 42, i64 99, i64 %n)
558   ret void
561 ; strncpy -> memset, different destination
562 define void @dse_strncpy_test3(i8* noalias %out1, i8* noalias %out2, i8* noalias %in) {
563 ; CHECK-LABEL: @dse_strncpy_test3(
564 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT1:%.*]], i8* [[IN:%.*]], i64 100)
565 ; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* [[OUT2:%.*]], i8 42, i64 100, i1 false)
566 ; CHECK-NEXT:    ret void
568   %call = tail call i8* @strncpy(i8* %out1, i8* %in, i64 100)
569   tail call void @llvm.memset.p0i8.i64(i8* %out2, i8 42, i64 100, i1 false)
570   ret void
573 ; strncpy -> memset_chk, different destination
574 define void @dse_strncpy_chk_test3(i8* noalias %out1, i8* noalias %out2, i8* noalias %in, i64 %n) {
575 ; CHECK-LABEL: @dse_strncpy_chk_test3(
576 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT1:%.*]], i8* [[IN:%.*]], i64 100)
577 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call i8* @__memset_chk(i8* [[OUT2:%.*]], i32 42, i64 100, i64 [[N:%.*]])
578 ; CHECK-NEXT:    ret void
580   %call = tail call i8* @strncpy(i8* %out1, i8* %in, i64 100)
581   %call.2 = tail call i8* @__memset_chk(i8* %out2, i32 42, i64 100, i64 %n)
582   ret void
585 ; memset -> strncpy, full overwrite
586 define void @dse_strncpy_test4(i8* noalias %out, i8* noalias %in) {
587 ; CHECK-LABEL: @dse_strncpy_test4(
588 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT:%.*]], i8* [[IN:%.*]], i64 100)
589 ; CHECK-NEXT:    ret void
591   tail call void @llvm.memset.p0i8.i64(i8* %out, i8 42, i64 100, i1 false)
592   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 100)
593   ret void
596 ; memset -> strncpy, partial overwrite
597 define void @dse_strncpy_test5(i8* noalias %out, i8* noalias %in) {
598 ; CHECK-LABEL: @dse_strncpy_test5(
599 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[OUT:%.*]], i64 99
600 ; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* align 1 [[TMP1]], i8 42, i64 1, i1 false)
601 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT]], i8* [[IN:%.*]], i64 99)
602 ; CHECK-NEXT:    ret void
604   tail call void @llvm.memset.p0i8.i64(i8* %out, i8 42, i64 100, i1 false)
605   %call = tail call i8* @strncpy(i8* %out, i8* %in, i64 99)
606   ret void
609 ; memset -> strncpy, different destination
610 define void @dse_strncpy_test6(i8* noalias %out1, i8* noalias %out2, i8* noalias %in) {
611 ; CHECK-LABEL: @dse_strncpy_test6(
612 ; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* [[OUT1:%.*]], i8 42, i64 100, i1 false)
613 ; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strncpy(i8* [[OUT2:%.*]], i8* [[IN:%.*]], i64 100)
614 ; CHECK-NEXT:    ret void
616   tail call void @llvm.memset.p0i8.i64(i8* %out1, i8 42, i64 100, i1 false)
617   %call = tail call i8* @strncpy(i8* %out2, i8* %in, i64 100)
618   ret void