[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / libcalls.ll
blob48addc9bbd7fe49fed12d21feadd2c6fc218d678
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 declare i8* @strncpy(i8* %dest, i8* %src, i64 %n) nounwind
19 define void @test2(i8* %src) {
20 ; CHECK-LABEL: @test2(
21 ; CHECK-NEXT:    ret void
23   %B = alloca [16 x i8]
24   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
25   %call = call i8* @strncpy(i8* %dest, i8* %src, i64 12)
26   ret void
29 declare i8* @strcat(i8* %dest, i8* %src) nounwind
30 define void @test3(i8* %src) {
31 ; CHECK-LABEL: @test3(
32 ; CHECK-NEXT:    ret void
34   %B = alloca [16 x i8]
35   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
36   %call = call i8* @strcat(i8* %dest, i8* %src)
37   ret void
40 define void @test_strcat_with_lifetime(i8* %src) {
41 ; CHECK-LABEL: @test_strcat_with_lifetime(
42 ; CHECK-NEXT:    [[B:%.*]] = alloca [16 x i8], align 1
43 ; CHECK-NEXT:    [[B_CAST:%.*]] = bitcast [16 x i8]* [[B]] to i8*
44 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[B_CAST]])
45 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[B_CAST]])
46 ; CHECK-NEXT:    ret void
48   %B = alloca [16 x i8]
49   %B.cast = bitcast [16 x i8]* %B to i8*
50   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %B.cast)
51   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
52   %call = call i8* @strcat(i8* %dest, i8* %src)
53   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %B.cast)
54   ret void
57 define void @test_strcat_with_lifetime_nonlocal(i8* %dest, i8* %src) {
58 ; CHECK-LABEL: @test_strcat_with_lifetime_nonlocal(
59 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[DEST:%.*]])
60 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @strcat(i8* [[DEST]], i8* [[SRC:%.*]])
61 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[DEST]])
62 ; CHECK-NEXT:    ret void
64   call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %dest)
65   %call = call i8* @strcat(i8* %dest, i8* %src)
66   call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %dest)
67   ret void
70 declare i8* @strncat(i8* %dest, i8* %src, i64 %n) nounwind
71 define void @test4(i8* %src) {
72 ; CHECK-LABEL: @test4(
73 ; CHECK-NEXT:    ret void
75   %B = alloca [16 x i8]
76   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
77   %call = call i8* @strncat(i8* %dest, i8* %src, i64 12)
78   ret void
81 define void @test5(i8* nocapture %src) {
82 ; CHECK-LABEL: @test5(
83 ; CHECK-NEXT:    ret void
85   %dest = alloca [100 x i8], align 16
86   %arraydecay = getelementptr inbounds [100 x i8], [100 x i8]* %dest, i64 0, i64 0
87   %call = call i8* @strcpy(i8* %arraydecay, i8* %src)
88   %arrayidx = getelementptr inbounds i8, i8* %call, i64 10
89   store i8 97, i8* %arrayidx, align 1
90   ret void
93 declare void @user(i8* %p)
94 define void @test6(i8* %src) {
95 ; CHECK-LABEL: @test6(
96 ; CHECK-NEXT:    [[B:%.*]] = alloca [16 x i8], align 1
97 ; CHECK-NEXT:    [[DEST:%.*]] = getelementptr inbounds [16 x i8], [16 x i8]* [[B]], i64 0, i64 0
98 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @strcpy(i8* [[DEST]], i8* [[SRC:%.*]])
99 ; CHECK-NEXT:    call void @user(i8* [[DEST]])
100 ; CHECK-NEXT:    ret void
102   %B = alloca [16 x i8]
103   %dest = getelementptr inbounds [16 x i8], [16 x i8]* %B, i64 0, i64 0
104   %call = call i8* @strcpy(i8* %dest, i8* %src)
105   call void @user(i8* %dest)
106   ret void
109 declare i32 @memcmp(i8*, i8*, i64)
111 define i32 @test_memcmp_const_size(i8* noalias %foo) {
112 ; CHECK-LABEL: @test_memcmp_const_size(
113 ; CHECK-NEXT:  entry:
114 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
115 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
116 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
117 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
118 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
119 ; CHECK-NEXT:    [[RES:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2)
120 ; CHECK-NEXT:    ret i32 [[RES]]
122 entry:
123   %stack = alloca [10 x i8]
124   %stack.ptr = bitcast [10 x i8]* %stack to i8*
125   store i8 49, i8* %stack.ptr, align 1
126   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
127   store i8 50, i8* %gep.1, align 1
128   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
129   store i8 51, i8* %gep.2, align 1
130   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
131   store i8 52, i8* %gep.3, align 1
132   %res = call i32 @memcmp(i8* nonnull dereferenceable(2) %foo, i8* nonnull dereferenceable(2) %stack.ptr, i64 2)
133   ret i32 %res
136 define i32 @test_memcmp_variable_size(i8* noalias %foo, i64 %n) {
137 ; CHECK-LABEL: @test_memcmp_variable_size(
138 ; CHECK-NEXT:  entry:
139 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
140 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
141 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
142 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
143 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
144 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
145 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
146 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
147 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
148 ; CHECK-NEXT:    [[RES:%.*]] = call i32 @memcmp(i8* nonnull [[FOO:%.*]], i8* nonnull [[STACK_PTR]], i64 [[N:%.*]])
149 ; CHECK-NEXT:    ret i32 [[RES]]
151 entry:
152   %stack = alloca [10 x i8]
153   %stack.ptr = bitcast [10 x i8]* %stack to i8*
154   store i8 49, i8* %stack.ptr, align 1
155   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
156   store i8 50, i8* %gep.1, align 1
157   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
158   store i8 51, i8* %gep.2, align 1
159   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
160   store i8 52, i8* %gep.3, align 1
161   %res = call i32 @memcmp(i8* nonnull %foo, i8* nonnull %stack.ptr, i64 %n)
162   ret i32 %res
165 declare i32 @bcmp(i8*, i8*, i64)
167 define i1 @test_bcmp_const_size(i8* noalias %foo) {
168 ; CHECK-LABEL: @test_bcmp_const_size(
169 ; CHECK-NEXT:  entry:
170 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
171 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
172 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
173 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
174 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
175 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @bcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2)
176 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[CALL]], 0
177 ; CHECK-NEXT:    ret i1 [[RES]]
179 entry:
180   %stack = alloca [10 x i8]
181   %stack.ptr = bitcast [10 x i8]* %stack to i8*
182   store i8 49, i8* %stack.ptr, align 1
183   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
184   store i8 50, i8* %gep.1, align 1
185   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
186   store i8 51, i8* %gep.2, align 1
187   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
188   store i8 52, i8* %gep.3, align 1
189   %call = call i32 @bcmp(i8* nonnull dereferenceable(2) %foo, i8* nonnull dereferenceable(2) %stack.ptr, i64 2)
190   %res = icmp eq i32 %call, 0
191   ret i1 %res
194 define i1 @test_bcmp_variable_size(i8* noalias %foo, i64 %n) {
195 ; CHECK-LABEL: @test_bcmp_variable_size(
196 ; CHECK-NEXT:  entry:
197 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
198 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
199 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
200 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
201 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
202 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
203 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
204 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
205 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
206 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @bcmp(i8* nonnull [[FOO:%.*]], i8* nonnull [[STACK_PTR]], i64 [[N:%.*]])
207 ; CHECK-NEXT:    [[RES:%.*]] = icmp eq i32 [[CALL]], 0
208 ; CHECK-NEXT:    ret i1 [[RES]]
210 entry:
211   %stack = alloca [10 x i8]
212   %stack.ptr = bitcast [10 x i8]* %stack to i8*
213   store i8 49, i8* %stack.ptr, align 1
214   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
215   store i8 50, i8* %gep.1, align 1
216   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
217   store i8 51, i8* %gep.2, align 1
218   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
219   store i8 52, i8* %gep.3, align 1
220   %call = call i32 @bcmp(i8* nonnull %foo, i8* nonnull %stack.ptr, i64 %n)
221   %res = icmp eq i32 %call, 0
222   ret i1 %res
225 declare i8* @memchr(i8*, i32, i64)
227 define i8* @test_memchr_const_size() {
228 ; CHECK-LABEL: @test_memchr_const_size(
229 ; CHECK-NEXT:  entry:
230 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
231 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
232 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
233 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
234 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
235 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 2)
236 ; CHECK-NEXT:    ret i8* [[CALL]]
238 entry:
239   %stack = alloca [10 x i8]
240   %stack.ptr = bitcast [10 x i8]* %stack to i8*
241   store i8 49, i8* %stack.ptr, align 1
242   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
243   store i8 50, i8* %gep.1, align 1
244   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
245   store i8 51, i8* %gep.2, align 1
246   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
247   store i8 52, i8* %gep.3, align 1
248   %call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 2)
249   ret i8* %call
252 define i8* @test_memchr_variable_size(i64 %n) {
253 ; CHECK-LABEL: @test_memchr_variable_size(
254 ; CHECK-NEXT:  entry:
255 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
256 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
257 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
258 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
259 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
260 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
261 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
262 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 4
263 ; CHECK-NEXT:    store i8 52, i8* [[GEP]], align 1
264 ; CHECK-NEXT:    [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
265 ; CHECK-NEXT:    ret i8* [[CALL]]
267 entry:
268   %stack = alloca [10 x i8]
269   %stack.ptr = bitcast [10 x i8]* %stack to i8*
270   store i8 49, i8* %stack.ptr, align 1
271   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
272   store i8 50, i8* %gep.1, align 1
273   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
274   store i8 51, i8* %gep.2, align 1
275   %gep = getelementptr i8, i8* %stack.ptr, i64 4
276   store i8 52, i8* %gep, align 1
277   %call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 %n)
278   ret i8* %call
281 declare i8* @memccpy(i8*, i8*, i32, i64)
283 define i8* @test_memccpy_const_size(i8* %foo) {
284 ; CHECK-LABEL: @test_memccpy_const_size(
285 ; CHECK-NEXT:  entry:
286 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
287 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
288 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
289 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
290 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
291 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 2)
292 ; CHECK-NEXT:    ret i8* [[RES]]
294 entry:
295   %stack = alloca [10 x i8]
296   %stack.ptr = bitcast [10 x i8]* %stack to i8*
297   store i8 49, i8* %stack.ptr, align 1
298   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
299   store i8 50, i8* %gep.1, align 1
300   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
301   store i8 51, i8* %gep.2, align 1
302   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
303   store i8 52, i8* %gep.3, align 1
304   %res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 2)
305   ret i8* %res
308 define i8* @test_memccpy_variable_size(i8* %foo, i64 %n) {
309 ; CHECK-LABEL: @test_memccpy_variable_size(
310 ; CHECK-NEXT:  entry:
311 ; CHECK-NEXT:    [[STACK:%.*]] = alloca [10 x i8], align 1
312 ; CHECK-NEXT:    [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
313 ; CHECK-NEXT:    store i8 49, i8* [[STACK_PTR]], align 1
314 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
315 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
316 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
317 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
318 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
319 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
320 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
321 ; CHECK-NEXT:    ret i8* [[RES]]
323 entry:
324   %stack = alloca [10 x i8]
325   %stack.ptr = bitcast [10 x i8]* %stack to i8*
326   store i8 49, i8* %stack.ptr, align 1
327   %gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
328   store i8 50, i8* %gep.1, align 1
329   %gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
330   store i8 51, i8* %gep.2, align 1
331   %gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
332   store i8 52, i8* %gep.3, align 1
333   %res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 %n)
334   ret i8* %res
337 ; Make sure memccpy does not kill any stores, because it is not known how many
338 ; bytes are written.
339 define i8* @test_memccpy_const_size_does_not_kill_stores(i8* noalias %dest, i8* noalias %foo) {
340 ; CHECK-LABEL: @test_memccpy_const_size_does_not_kill_stores(
341 ; CHECK-NEXT:  entry:
342 ; CHECK-NEXT:    store i8 49, i8* [[DEST:%.*]], align 1
343 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, i8* [[DEST]], i64 1
344 ; CHECK-NEXT:    store i8 50, i8* [[GEP_1]], align 1
345 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, i8* [[DEST]], i64 2
346 ; CHECK-NEXT:    store i8 51, i8* [[GEP_2]], align 1
347 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, i8* [[DEST]], i64 3
348 ; CHECK-NEXT:    store i8 52, i8* [[GEP_3]], align 1
349 ; CHECK-NEXT:    [[RES:%.*]] = call i8* @memccpy(i8* [[DEST]], i8* [[FOO:%.*]], i32 42, i64 2)
350 ; CHECK-NEXT:    ret i8* [[RES]]
352 entry:
353   store i8 49, i8* %dest, align 1
354   %gep.1 = getelementptr i8, i8* %dest, i64 1
355   store i8 50, i8* %gep.1, align 1
356   %gep.2 = getelementptr i8, i8* %dest, i64 2
357   store i8 51, i8* %gep.2, align 1
358   %gep.3 = getelementptr i8, i8* %dest, i64 3
359   store i8 52, i8* %gep.3, align 1
360   %res = call i8* @memccpy(i8* %dest, i8* %foo, i32 42, i64 2)
361   ret i8* %res
364 define void @dse_strcpy(i8* nocapture readonly %src) {
365 ; CHECK-LABEL: @dse_strcpy(
366 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
367 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
368 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
369 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
370 ; CHECK-NEXT:    ret void
372   %a = alloca [256 x i8], align 16
373   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
374   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
375   call i8* @strcpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src)
376   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
377   ret void
380 define void @dse_strncpy(i8* nocapture readonly %src) {
381 ; CHECK-LABEL: @dse_strncpy(
382 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
383 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
384 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
385 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
386 ; CHECK-NEXT:    ret void
388   %a = alloca [256 x i8], align 16
389   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
390   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
391   call i8* @strncpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6)
392   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
393   ret void
396 define void @dse_strcat(i8* nocapture readonly %src) {
397 ; CHECK-LABEL: @dse_strcat(
398 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
399 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
400 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
401 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
402 ; CHECK-NEXT:    ret void
404   %a = alloca [256 x i8], align 16
405   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
406   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
407   call i8* @strcat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src)
408   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
409   ret void
412 define void @dse_strncat(i8* nocapture readonly %src) {
413 ; CHECK-LABEL: @dse_strncat(
414 ; CHECK-NEXT:    [[A:%.*]] = alloca [256 x i8], align 16
415 ; CHECK-NEXT:    [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0
416 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]])
417 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]])
418 ; CHECK-NEXT:    ret void
420   %a = alloca [256 x i8], align 16
421   %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0
422   call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf)
423   call i8* @strncat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6)
424   call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf)
425   ret void
428 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
429 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)