1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=memcpyopt,dse -S -verify-memoryssa | FileCheck %s
4 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
5 target triple = "i686-apple-darwin9"
7 %0 = type { x86_fp80, x86_fp80 }
10 @C = external constant [0 x i8]
12 declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) nocapture, ptr nocapture, i64, i1) nounwind
13 declare void @llvm.memcpy.p0.p1.i64(ptr nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind
14 declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind
15 declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind
16 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
17 declare void @llvm.memcpy.inline.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind
18 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
20 ; Check that one of the memcpy's are removed.
21 ;; FIXME: PR 8643 We should be able to eliminate the last memcpy here.
22 define void @test1(ptr sret(%0) %agg.result, x86_fp80 %z.0, x86_fp80 %z.1) nounwind {
23 ; CHECK-LABEL: @test1(
25 ; CHECK-NEXT: [[TMP2:%.*]] = alloca [[TMP0:%.*]], align 16
26 ; CHECK-NEXT: [[MEMTMP:%.*]] = alloca [[TMP0]], align 16
27 ; CHECK-NEXT: [[TMP5:%.*]] = fsub x86_fp80 0xK80000000000000000000, [[Z_1:%.*]]
28 ; CHECK-NEXT: call void @ccoshl(ptr sret([[TMP0]]) [[TMP2]], x86_fp80 [[TMP5]], x86_fp80 [[Z_0:%.*]]) #[[ATTR2:[0-9]+]]
29 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[AGG_RESULT:%.*]], ptr align 16 [[TMP2]], i32 32, i1 false)
30 ; CHECK-NEXT: ret void
34 %memtmp = alloca %0, align 16
35 %tmp5 = fsub x86_fp80 0xK80000000000000000000, %z.1
36 call void @ccoshl(ptr sret(%0) %memtmp, x86_fp80 %tmp5, x86_fp80 %z.0) nounwind
37 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %tmp2, ptr align 16 %memtmp, i32 32, i1 false)
38 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 16 %tmp2, i32 32, i1 false)
42 declare void @ccoshl(ptr nocapture sret(%0), x86_fp80, x86_fp80) nounwind
45 ; The intermediate alloca and one of the memcpy's should be eliminated, the
46 ; other should be related with a memmove.
47 define void @test2(ptr %P, ptr %Q) nounwind {
48 ; CHECK-LABEL: @test2(
49 ; CHECK-NEXT: call void @llvm.memmove.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
50 ; CHECK-NEXT: ret void
52 %memtmp = alloca %0, align 16
53 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
54 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
59 ; The intermediate alloca and one of the memcpy's should be eliminated, the
60 ; other should be related with a memcpy.
61 define void @test2_constant(ptr %Q) nounwind {
62 ; CHECK-LABEL: @test2_constant(
63 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 @C, i32 32, i1 false)
64 ; CHECK-NEXT: ret void
66 %memtmp = alloca %0, align 16
67 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 @C, i32 32, i1 false)
68 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
73 ; The intermediate alloca and one of the memcpy's should be eliminated, the
74 ; other should be related with a memcpy.
75 define void @test2_memcpy(ptr noalias %P, ptr noalias %Q) nounwind {
76 ; CHECK-LABEL: @test2_memcpy(
77 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
78 ; CHECK-NEXT: ret void
80 %memtmp = alloca %0, align 16
81 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
82 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
87 ; Same as @test2_memcpy, but the remaining memcpy should remain non-inline even
88 ; if the one eliminated was inline.
89 define void @test3_memcpy(ptr noalias %P, ptr noalias %Q) nounwind {
90 ; CHECK-LABEL: @test3_memcpy(
91 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
92 ; CHECK-NEXT: ret void
94 %memtmp = alloca %0, align 16
95 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
96 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
101 ; Same as @test2_memcpy, but the remaining memcpy should remain inline even
102 ; if the one eliminated was not inline.
103 define void @test4_memcpy(ptr noalias %P, ptr noalias %Q) nounwind {
104 ; CHECK-LABEL: @test4_memcpy(
105 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
106 ; CHECK-NEXT: ret void
108 %memtmp = alloca %0, align 16
109 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
110 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
115 ; Same as @test2_memcpy, and the inline-ness should be preserved.
116 define void @test5_memcpy(ptr noalias %P, ptr noalias %Q) nounwind {
117 ; CHECK-LABEL: @test5_memcpy(
118 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
119 ; CHECK-NEXT: ret void
121 %memtmp = alloca %0, align 16
122 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
123 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
128 ; Similar to test5_memcpy, but without noalias; check that memcpy.inline is not folded into memmove.
129 define void @test6_memcpy(ptr %src, ptr %dest) nounwind {
130 ; CHECK-LABEL: @test6_memcpy(
131 ; CHECK-NEXT: [[TMP:%.*]] = alloca [16 x i8], align 1
132 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SRC:%.*]], i32 16, i1 false)
133 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[DEST:%.*]], ptr align 1 [[TMP]], i32 16, i1 false)
134 ; CHECK-NEXT: ret void
136 %tmp = alloca [16 x i8], align 1
137 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)
138 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)
142 ; When forwarding to memcpy(arg+1, arg+1), we don't need to create this memcpy.
143 define void @test6_memcpy_forward_back(ptr %arg) nounwind {
144 ; CHECK-LABEL: @test6_memcpy_forward_back(
145 ; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
146 ; CHECK-NEXT: ret void
148 %tmp = alloca [16 x i8], align 1
149 %src = getelementptr inbounds i8, ptr %arg, i64 1
150 %dest = getelementptr inbounds i8, ptr %arg, i64 1
151 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)
152 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)
156 ; We have to retain this `memcpy(arg+2, arg+1)` forwarding.
157 define void @test6_memcpy_forward_not_back(ptr %arg) nounwind {
158 ; CHECK-LABEL: @test6_memcpy_forward_not_back(
159 ; CHECK-NEXT: [[TMP:%.*]] = alloca [16 x i8], align 1
160 ; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1
161 ; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2
162 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SRC]], i32 16, i1 false)
163 ; CHECK-NEXT: call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[DEST]], ptr align 1 [[TMP]], i32 16, i1 false)
164 ; CHECK-NEXT: ret void
166 %tmp = alloca [16 x i8], align 1
167 %src = getelementptr inbounds i8, ptr %arg, i64 1
168 %dest = getelementptr inbounds i8, ptr %arg, i64 2
169 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)
170 call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)
174 @x = external global %0
176 define void @test3(ptr noalias writable sret(%0) %agg.result) nounwind {
177 ; CHECK-LABEL: @test3(
178 ; CHECK-NEXT: [[X_0:%.*]] = alloca [[TMP0:%.*]], align 16
179 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[AGG_RESULT:%.*]], ptr align 16 @x, i32 32, i1 false)
180 ; CHECK-NEXT: ret void
183 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x.0, ptr align 16 @x, i32 32, i1 false)
184 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 16 %x.0, i32 32, i1 false)
190 define void @test4(ptr %P) {
191 ; CHECK-LABEL: @test4(
192 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P:%.*]])
193 ; CHECK-NEXT: ret void
196 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 %P, i64 8, i1 false)
197 call void @test4a(ptr align 1 byval(i8) %A)
201 ; Make sure we don't remove the memcpy if the source address space doesn't match the byval argument
202 define void @test4_addrspace(ptr addrspace(1) %P) {
203 ; CHECK-LABEL: @test4_addrspace(
204 ; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
205 ; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr align 4 [[A1]], ptr addrspace(1) align 4 [[P:%.*]], i64 8, i1 false)
206 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[A1]])
207 ; CHECK-NEXT: ret void
210 call void @llvm.memcpy.p0.p1.i64(ptr align 4 %a1, ptr addrspace(1) align 4 %P, i64 8, i1 false)
211 call void @test4a(ptr align 1 byval(i8) %a1)
215 define void @test4_write_between(ptr %P) {
216 ; CHECK-LABEL: @test4_write_between(
217 ; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
218 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A1]], ptr align 4 [[P:%.*]], i64 8, i1 false)
219 ; CHECK-NEXT: store i8 0, ptr [[A1]], align 1
220 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[A1]])
221 ; CHECK-NEXT: ret void
224 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)
226 call void @test4a(ptr align 1 byval(i8) %a1)
230 define i8 @test4_read_between(ptr %P) {
231 ; CHECK-LABEL: @test4_read_between(
232 ; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8
233 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A1]], ptr align 4 [[P:%.*]], i64 8, i1 false)
234 ; CHECK-NEXT: [[X:%.*]] = load i8, ptr [[A1]], align 1
235 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P]])
236 ; CHECK-NEXT: ret i8 [[X]]
239 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)
240 %x = load i8, ptr %a1
241 call void @test4a(ptr align 1 byval(i8) %a1)
245 define void @test4_non_local(ptr %P, i1 %c) {
246 ; CHECK-LABEL: @test4_non_local(
247 ; CHECK-NEXT: br i1 [[C:%.*]], label [[CALL:%.*]], label [[EXIT:%.*]]
249 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P:%.*]])
250 ; CHECK-NEXT: br label [[EXIT]]
252 ; CHECK-NEXT: ret void
255 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)
256 br i1 %c, label %call, label %exit
259 call void @test4a(ptr align 1 byval(i8) %a1)
266 declare void @test4a(ptr align 1 byval(i8))
268 %struct.S = type { i128, [4 x i8]}
270 @sS = external global %struct.S, align 16
272 declare void @test5a(ptr align 16 byval(%struct.S)) nounwind ssp
275 ; rdar://8713376 - This memcpy can't be eliminated.
276 define i32 @test5(i32 %x) nounwind ssp {
277 ; CHECK-LABEL: @test5(
279 ; CHECK-NEXT: [[Y:%.*]] = alloca [[STRUCT_S:%.*]], align 16
280 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[Y]], ptr align 16 @sS, i64 32, i1 false)
281 ; CHECK-NEXT: [[A:%.*]] = getelementptr [[STRUCT_S]], ptr [[Y]], i64 0, i32 1, i64 0
282 ; CHECK-NEXT: store i8 4, ptr [[A]], align 1
283 ; CHECK-NEXT: call void @test5a(ptr byval([[STRUCT_S]]) align 16 [[Y]])
284 ; CHECK-NEXT: ret i32 0
287 %y = alloca %struct.S, align 16
288 call void @llvm.memcpy.p0.p0.i64(ptr align 16 %y, ptr align 16 @sS, i64 32, i1 false)
289 %a = getelementptr %struct.S, ptr %y, i64 0, i32 1, i64 0
291 call void @test5a(ptr align 16 byval(%struct.S) %y)
295 ;; Noop memcpy should be zapped.
296 define void @test6(ptr %P) {
297 ; CHECK-LABEL: @test6(
298 ; CHECK-NEXT: ret void
300 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %P, ptr align 4 %P, i64 8, i1 false)
305 ; PR9794 - Should forward memcpy into byval argument even though the memcpy
306 ; isn't itself 8 byte aligned.
307 %struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }
309 define i32 @test7(ptr nocapture align 8 byval(%struct.p) %q) nounwind ssp {
310 ; CHECK-LABEL: @test7(
312 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @g(ptr byval([[STRUCT_P:%.*]]) align 8 [[Q:%.*]]) #[[ATTR2]]
313 ; CHECK-NEXT: ret i32 [[CALL]]
316 %agg.tmp = alloca %struct.p, align 4
317 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %q, i64 48, i1 false)
318 %call = call i32 @g(ptr align 8 byval(%struct.p) %agg.tmp) nounwind
322 declare i32 @g(ptr align 8 byval(%struct.p))
325 ; PR11142 - When looking for a memcpy-memcpy dependency, don't get stuck on
326 ; instructions between the memcpy's that only affect the destination pointer.
327 @test8.str = internal constant [7 x i8] c"ABCDEF\00"
329 define void @test8() {
330 ; CHECK-LABEL: @test8(
331 ; CHECK-NEXT: ret void
333 %A = tail call ptr @malloc(i32 10)
334 %B = getelementptr inbounds i8, ptr %A, i64 2
335 tail call void @llvm.memcpy.p0.p0.i32(ptr %B, ptr @test8.str, i32 7, i1 false)
336 %C = tail call ptr @malloc(i32 10)
337 %D = getelementptr inbounds i8, ptr %C, i64 2
338 tail call void @llvm.memcpy.p0.p0.i32(ptr %D, ptr %B, i32 7, i1 false)
342 declare noalias ptr @malloc(i32) willreturn allockind("alloc,uninitialized") allocsize(0)
345 %struct.big = type { [50 x i32] }
347 define void @test9_addrspacecast() nounwind ssp uwtable {
348 ; CHECK-LABEL: @test9_addrspacecast(
350 ; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4
351 ; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4
352 ; CHECK-NEXT: call void @f1(ptr sret([[STRUCT_BIG]]) [[B]])
353 ; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[B]] to ptr addrspace(1)
354 ; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[TMP]] to ptr addrspace(1)
355 ; CHECK-NEXT: call void @f2(ptr [[B]])
356 ; CHECK-NEXT: ret void
359 %b = alloca %struct.big, align 4
360 %tmp = alloca %struct.big, align 4
361 call void @f1(ptr sret(%struct.big) %tmp)
362 %0 = addrspacecast ptr %b to ptr addrspace(1)
363 %1 = addrspacecast ptr %tmp to ptr addrspace(1)
364 call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 4 %0, ptr addrspace(1) align 4 %1, i64 200, i1 false)
365 call void @f2(ptr %b)
369 define void @test9() nounwind ssp uwtable {
370 ; CHECK-LABEL: @test9(
372 ; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4
373 ; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4
374 ; CHECK-NEXT: call void @f1(ptr sret([[STRUCT_BIG]]) [[B]])
375 ; CHECK-NEXT: call void @f2(ptr [[B]])
376 ; CHECK-NEXT: ret void
379 %b = alloca %struct.big, align 4
380 %tmp = alloca %struct.big, align 4
381 call void @f1(ptr sret(%struct.big) %tmp)
382 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %b, ptr align 4 %tmp, i64 200, i1 false)
383 call void @f2(ptr %b)
388 ; Test10 triggered assertion when the compiler try to get the size of the
389 ; opaque type of *x, where the x is the formal argument with attribute 'sret'.
391 %opaque = type opaque
392 declare void @foo(ptr noalias nocapture)
394 define void @test10(ptr noalias nocapture sret(%opaque) %x, i32 %y) {
395 ; CHECK-LABEL: @test10(
396 ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
397 ; CHECK-NEXT: store i32 [[Y:%.*]], ptr [[A]], align 4
398 ; CHECK-NEXT: call void @foo(ptr noalias nocapture [[A]])
399 ; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[A]], align 4
400 ; CHECK-NEXT: store i32 [[C]], ptr [[X:%.*]], align 4
401 ; CHECK-NEXT: ret void
403 %a = alloca i32, align 4
405 call void @foo(ptr noalias nocapture %a)
406 %c = load i32, ptr %a
411 ; don't create new addressspacecasts when we don't know they're safe for the target
412 define void @test11(ptr addrspace(1) nocapture dereferenceable(80) %P) {
413 ; CHECK-LABEL: @test11(
414 ; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 4 [[P:%.*]], i8 0, i64 80, i1 false)
415 ; CHECK-NEXT: ret void
417 %A = alloca [20 x i32], align 4
418 call void @llvm.memset.p0.i64(ptr align 4 %A, i8 0, i64 80, i1 false)
419 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 %P, ptr align 4 %A, i64 80, i1 false)
423 declare void @f1(ptr nocapture sret(%struct.big))
424 declare void @f2(ptr)
427 declare void @f_byval(ptr byval(i32))
428 declare void @f_full_readonly(ptr nocapture noalias readonly)
430 define void @immut_param(ptr align 4 noalias %val) {
431 ; CHECK-LABEL: @immut_param(
432 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL:%.*]])
433 ; CHECK-NEXT: ret void
435 %val1 = alloca i8, align 4
436 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
437 call void @f(ptr align 4 nocapture noalias readonly %val1)
441 ; Can't remove memcpy because dest may be captured.
442 define void @immut_param_maycapture(ptr align 4 noalias %val) {
443 ; CHECK-LABEL: @immut_param_maycapture(
444 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
445 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
446 ; CHECK-NEXT: call void @f(ptr noalias readonly align 4 [[VAL1]])
447 ; CHECK-NEXT: ret void
449 %val1 = alloca i8, align 4
450 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
451 call void @f(ptr align 4 noalias readonly %val1)
455 ; Can't remove memcpy because dest may be aliased.
456 define void @immut_param_mayalias(ptr align 4 noalias %val) {
457 ; CHECK-LABEL: @immut_param_mayalias(
458 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
459 ; CHECK-NEXT: call void @f(ptr [[VAL1]])
460 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
461 ; CHECK-NEXT: call void @f(ptr nocapture readonly align 4 [[VAL1]])
462 ; CHECK-NEXT: ret void
464 %val1 = alloca i8, align 4
465 call void @f(ptr %val1) ; escape
466 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
467 call void @f(ptr align 4 nocapture readonly %val1)
471 ; Can remove memcpy because alloca does not escape, so lack of noalias on the
472 ; argument doesn't matter.
473 define void @immut_param_unescaped_alloca(ptr align 4 noalias %val) {
474 ; CHECK-LABEL: @immut_param_unescaped_alloca(
475 ; CHECK-NEXT: call void @f(ptr nocapture readonly align 4 [[VAL:%.*]])
476 ; CHECK-NEXT: ret void
478 %val1 = alloca i8, align 4
479 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
480 call void @f(ptr align 4 nocapture readonly %val1)
484 ; Can remove memcpy because the function is argmem: read, so there cannot be
485 ; a write to the escaped pointer.
486 define void @immut_param_memory_argmem_read(ptr align 4 noalias %val) {
487 ; CHECK-LABEL: @immut_param_memory_argmem_read(
488 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
489 ; CHECK-NEXT: call void @f(ptr [[VAL1]])
490 ; CHECK-NEXT: call void @f(ptr nocapture readonly align 4 [[VAL:%.*]]) #[[ATTR6:[0-9]+]]
491 ; CHECK-NEXT: ret void
493 %val1 = alloca i8, align 4
494 call void @f(ptr %val1) ; escape
495 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
496 call void @f(ptr align 4 nocapture readonly %val1) memory(argmem: read)
500 ; Can remove memcpy because the function is argmem: read, so there cannot be
501 ; a write to the escaped pointer. The readonly on the argument is redundant in
503 define void @immut_param_memory_argmem_read_no_readonly(ptr align 4 noalias %val) {
504 ; CHECK-LABEL: @immut_param_memory_argmem_read_no_readonly(
505 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
506 ; CHECK-NEXT: call void @f(ptr [[VAL1]])
507 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
508 ; CHECK-NEXT: call void @f(ptr nocapture align 4 [[VAL1]]) #[[ATTR6]]
509 ; CHECK-NEXT: ret void
511 %val1 = alloca i8, align 4
512 call void @f(ptr %val1) ; escape
513 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
514 call void @f(ptr align 4 nocapture %val1) memory(argmem: read)
518 ; Can't remove memcpy because dest may be written.
519 define void @immut_param_maywrite(ptr align 4 noalias %val) {
520 ; CHECK-LABEL: @immut_param_maywrite(
521 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
522 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
523 ; CHECK-NEXT: call void @f(ptr noalias nocapture align 4 [[VAL1]])
524 ; CHECK-NEXT: ret void
526 %val1 = alloca i8, align 4
527 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
528 call void @f(ptr align 4 nocapture noalias %val1)
532 define void @immut_param_readonly(ptr align 4 noalias %val) {
533 ; CHECK-LABEL: @immut_param_readonly(
534 ; CHECK-NEXT: call void @f_full_readonly(ptr align 4 [[VAL:%.*]])
535 ; CHECK-NEXT: ret void
537 %val1 = alloca i8, align 4
538 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
539 call void @f_full_readonly(ptr align 4 %val1)
543 define void @immut_param_no_align(ptr align 4 noalias %val) {
544 ; CHECK-LABEL: @immut_param_no_align(
545 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL:%.*]])
546 ; CHECK-NEXT: ret void
548 %val1 = alloca i8, align 4
549 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
550 call void @f(ptr nocapture noalias readonly %val1)
554 @gp = external constant [0 x i8]
555 ; Can't remove memcpy because dest is not unescaped alloca, so cpying is meaningfull.
556 define void @immut_param_global(ptr align 4 noalias %val) {
557 ; CHECK-LABEL: @immut_param_global(
558 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 @gp, ptr align 4 [[VAL:%.*]], i64 1, i1 false)
559 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 @gp)
560 ; CHECK-NEXT: ret void
562 call void @llvm.memcpy.p0.p0.i64(ptr align 4 @gp, ptr align 4 %val, i64 1, i1 false)
563 call void @f(ptr nocapture align 4 noalias readonly @gp)
567 ; Can't remove memcpy for VLA because of unknown size and alignment.
568 define void @immut_param_vla(ptr align 4 noalias %val, i64 %n) {
569 ; CHECK-LABEL: @immut_param_vla(
570 ; CHECK-NEXT: [[VAL1:%.*]] = alloca ptr, i64 [[N:%.*]], align 4
571 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
572 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
573 ; CHECK-NEXT: ret void
575 %val1 = alloca ptr, i64 %n
576 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
577 call void @f(ptr nocapture align 4 noalias readonly %val1)
581 ; Can't remove memcpy for scalable vector, because of memcpy size sufficiency is unknown
582 define void @immut_param_scalable_vector(ptr align 4 noalias %val) {
583 ; CHECK-LABEL: @immut_param_scalable_vector(
584 ; CHECK-NEXT: [[VAL1:%.*]] = alloca <vscale x 2 x i32>, align 8
585 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 2, i1 false)
586 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
587 ; CHECK-NEXT: ret void
589 %val1 = alloca <vscale x 2 x i32>
590 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 2, i1 false)
591 call void @f(ptr nocapture align 4 noalias readonly %val1)
595 ; Can't remove memcpy because dst is modified between call and memcpy
596 define void @immut_param_modified_dst(ptr align 4 noalias %val) {
597 ; CHECK-LABEL: @immut_param_modified_dst(
598 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
599 ; CHECK-NEXT: store i32 13, ptr [[VAL1]], align 4
600 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
601 ; CHECK-NEXT: ret void
603 %val1 = alloca i8, align 4
604 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
605 store i32 13, ptr %val1
606 call void @f(ptr nocapture align 4 noalias readonly %val1)
610 ; Can't remove memcpy because src is modified between call and memcpy
611 define void @immut_param_modified_src(ptr align 4 noalias %val) {
612 ; CHECK-LABEL: @immut_param_modified_src(
613 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
614 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
615 ; CHECK-NEXT: store i32 13, ptr [[VAL]], align 4
616 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
617 ; CHECK-NEXT: ret void
619 %val1 = alloca i8, align 4
620 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
621 store i32 13, ptr %val
622 call void @f(ptr nocapture align 4 noalias readonly %val1)
626 ; Can't remove memcpy because memcpy is volatile
627 define void @immut_param_volatile(ptr align 4 noalias %val) {
628 ; CHECK-LABEL: @immut_param_volatile(
629 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
630 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 true)
631 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
632 ; CHECK-NEXT: ret void
634 %val1 = alloca i8, align 4
635 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 true)
636 call void @f(ptr nocapture align 4 noalias readonly %val1)
640 ; Can't remove memcpy because address spaces are different.
641 define void @immut_param_different_addrespace(ptr addrspace(1) align 4 noalias %val) {
642 ; CHECK-LABEL: @immut_param_different_addrespace(
643 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
644 ; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr align 4 [[VAL1]], ptr addrspace(1) align 4 [[VAL:%.*]], i64 1, i1 false)
645 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL1]])
646 ; CHECK-NEXT: ret void
648 %val1 = alloca i8, align 4
649 call void @llvm.memcpy.p0.p1.i64(ptr align 4 %val1, ptr addrspace(1) align 4 %val, i64 1, i1 false)
650 call void @f(ptr nocapture align 4 noalias readonly %val1)
654 define void @immut_param_bigger_align(ptr align 16 noalias %val) {
655 ; CHECK-LABEL: @immut_param_bigger_align(
656 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL:%.*]])
657 ; CHECK-NEXT: ret void
659 %val1 = alloca i8, align 4
660 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr %val, i64 1, i1 false)
661 call void @f(ptr nocapture noalias readonly %val1)
665 ; Can't remove memcpy if we remove, the bigger alignment couldn't replaced by smaller one.
666 define void @immut_param_smaller_align(ptr align 4 noalias %val) {
667 ; CHECK-LABEL: @immut_param_smaller_align(
668 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 16
669 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[VAL1]], ptr [[VAL:%.*]], i64 1, i1 false)
670 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL1]])
671 ; CHECK-NEXT: ret void
673 %val1 = alloca i8, align 16
674 call void @llvm.memcpy.p0.p0.i64(ptr align 16 %val1, ptr %val, i64 1, i1 false)
675 call void @f(ptr nocapture noalias readonly %val1)
679 define void @immut_param_enforced_alignment() {
680 ; CHECK-LABEL: @immut_param_enforced_alignment(
681 ; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4
682 ; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4
683 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL]])
684 ; CHECK-NEXT: ret void
686 %val = alloca i8, align 1
687 store i32 42, ptr %val
688 %val1 = alloca i8, align 4
689 call void @llvm.memcpy.p0.p0.i64(ptr %val1, ptr %val, i64 1, i1 false)
690 call void @f(ptr nocapture noalias readonly %val1)
694 ; Can't remove memcpy, because if the %val directly passed to @f,
695 ; alignment of ptr to f's argument will be different.
696 define void @immut_invalid_align_branched(i1 %c, ptr noalias %val) {
697 ; CHECK-LABEL: @immut_invalid_align_branched(
698 ; CHECK-NEXT: [[VAL1:%.*]] = alloca [4 x i8], align 4
699 ; CHECK-NEXT: [[VAL2:%.*]] = alloca [16 x i8], align 16
700 ; CHECK-NEXT: [[VAL3:%.*]] = select i1 [[C:%.*]], ptr [[VAL1]], ptr [[VAL2]]
701 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL3]], ptr align 4 [[VAL:%.*]], i64 4, i1 false)
702 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL3]])
703 ; CHECK-NEXT: ret void
705 %val1 = alloca [4 x i8], align 4
706 %val2 = alloca [16 x i8], align 16
707 %val3 = select i1 %c, ptr %val1, ptr %val2
708 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val3, ptr align 4 %val, i64 4, i1 false)
709 call void @f(ptr nocapture noalias readonly %val3)
713 ; Can't remove memcpy, because alias might modify the src.
714 define void @immut_but_alias_src(ptr %val) {
715 ; CHECK-LABEL: @immut_but_alias_src(
716 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
717 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)
718 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL1]])
719 ; CHECK-NEXT: ret void
721 %val1 = alloca i8, align 4
722 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
723 call void @f(ptr nocapture noalias readonly %val1)
727 define void @immut_unescaped_alloca() {
728 ; CHECK-LABEL: @immut_unescaped_alloca(
729 ; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4
730 ; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4
731 ; CHECK-NEXT: call void @f_full_readonly(ptr [[VAL]])
732 ; CHECK-NEXT: ret void
734 %val = alloca i8, align 4
735 store i32 42, ptr %val
736 %val1 = alloca i8, align 4
737 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
738 call void @f_full_readonly(ptr %val1)
742 ; Can't remove memcpy, because alloca src is modified
743 define void @immut_unescaped_alloca_modified() {
744 ; CHECK-LABEL: @immut_unescaped_alloca_modified(
745 ; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4
746 ; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4
747 ; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4
748 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL]], i64 1, i1 false)
749 ; CHECK-NEXT: call void @f_full_readonly(ptr [[VAL1]])
750 ; CHECK-NEXT: ret void
752 %val = alloca i8, align 4
753 store i32 42, ptr %val
754 %val1 = alloca i8, align 4
755 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
756 store i32 13, ptr %val
757 call void @f_full_readonly(ptr %val1)
761 ; TODO: Remove memcpy
762 define void @immut_valid_align_branched(i1 %c, ptr noalias align 4 %val) {
763 ; CHECK-LABEL: @immut_valid_align_branched(
764 ; CHECK-NEXT: [[VAL1:%.*]] = alloca [4 x i8], align 4
765 ; CHECK-NEXT: [[VAL2:%.*]] = alloca [16 x i8], align 4
766 ; CHECK-NEXT: [[VAL3:%.*]] = select i1 [[C:%.*]], ptr [[VAL1]], ptr [[VAL2]]
767 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL3]], ptr align 4 [[VAL:%.*]], i64 4, i1 false)
768 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[VAL3]])
769 ; CHECK-NEXT: ret void
771 %val1 = alloca [4 x i8], align 4
772 %val2 = alloca [16 x i8], align 4
773 %val3 = select i1 %c, ptr %val1, ptr %val2
774 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val3, ptr align 4 %val, i64 4, i1 false)
775 call void @f(ptr nocapture noalias readonly %val3)
779 ; Merge/drop noalias metadata when replacing parameter.
780 define void @immut_param_noalias_metadata(ptr align 4 byval(i32) %ptr) {
781 ; CHECK-LABEL: @immut_param_noalias_metadata(
782 ; CHECK-NEXT: store i32 1, ptr [[PTR:%.*]], align 4, !noalias [[META0:![0-9]+]]
783 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly [[PTR]])
784 ; CHECK-NEXT: ret void
786 %tmp = alloca i32, align 4
787 store i32 1, ptr %ptr, !noalias !2
788 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)
789 call void @f(ptr nocapture noalias readonly %tmp), !alias.scope !2
793 define void @byval_param_noalias_metadata(ptr align 4 byval(i32) %ptr) {
794 ; CHECK-LABEL: @byval_param_noalias_metadata(
795 ; CHECK-NEXT: store i32 1, ptr [[PTR:%.*]], align 4, !noalias [[META0]]
796 ; CHECK-NEXT: call void @f_byval(ptr byval(i32) align 4 [[PTR]])
797 ; CHECK-NEXT: ret void
799 %tmp = alloca i32, align 4
800 store i32 1, ptr %ptr, !noalias !2
801 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)
802 call void @f_byval(ptr align 4 byval(i32) %tmp), !alias.scope !2
806 define void @memcpy_memory_none(ptr %p, ptr %p2, i64 %size) {
807 ; CHECK-LABEL: @memcpy_memory_none(
808 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[SIZE:%.*]], i1 false) #[[ATTR7:[0-9]+]]
809 ; CHECK-NEXT: ret void
811 call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none)
815 declare void @do_something()
816 declare void @capture(ptr)
818 define void @memcpy_memcpy_escape_before(ptr noalias %P, ptr noalias %Q) {
819 ; CHECK-LABEL: @memcpy_memcpy_escape_before(
820 ; CHECK-NEXT: [[MEMTMP:%.*]] = alloca [32 x i8], align 16
821 ; CHECK-NEXT: call void @capture(ptr [[MEMTMP]])
822 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)
823 ; CHECK-NEXT: call void @do_something()
824 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[MEMTMP]], i32 32, i1 false)
825 ; CHECK-NEXT: ret void
827 %memtmp = alloca [32 x i8], align 16
828 call void @capture(ptr %memtmp)
829 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
830 call void @do_something()
831 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
835 define void @memcpy_memcpy_escape_after1(ptr noalias %P, ptr noalias %Q) {
836 ; CHECK-LABEL: @memcpy_memcpy_escape_after1(
837 ; CHECK-NEXT: [[MEMTMP:%.*]] = alloca [32 x i8], align 16
838 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)
839 ; CHECK-NEXT: call void @do_something()
840 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P]], i32 32, i1 false)
841 ; CHECK-NEXT: call void @capture(ptr [[MEMTMP]])
842 ; CHECK-NEXT: ret void
844 %memtmp = alloca [32 x i8], align 16
845 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
846 call void @do_something()
847 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
848 call void @capture(ptr %memtmp)
852 define void @memcpy_memcpy_escape_after2(ptr noalias %P, ptr noalias %Q) {
853 ; CHECK-LABEL: @memcpy_memcpy_escape_after2(
854 ; CHECK-NEXT: call void @do_something()
855 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
856 ; CHECK-NEXT: call void @capture(ptr [[P]])
857 ; CHECK-NEXT: ret void
859 %memtmp = alloca [32 x i8], align 16
860 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
861 call void @do_something()
862 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
863 call void @capture(ptr %P)
867 define void @memcpy_byval_escape_after(ptr noalias %P) {
868 ; CHECK-LABEL: @memcpy_byval_escape_after(
869 ; CHECK-NEXT: call void @do_something()
870 ; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P:%.*]])
871 ; CHECK-NEXT: call void @capture(ptr [[P]])
872 ; CHECK-NEXT: ret void
875 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 %P, i64 8, i1 false)
876 call void @do_something()
877 call void @test4a(ptr align 1 byval(i8) %A)
878 call void @capture(ptr %P)
882 define void @memcpy_immut_escape_after(ptr align 4 noalias %val) {
883 ; CHECK-LABEL: @memcpy_immut_escape_after(
884 ; CHECK-NEXT: call void @do_something()
885 ; CHECK-NEXT: call void @f(ptr noalias nocapture readonly align 4 [[VAL:%.*]])
886 ; CHECK-NEXT: call void @capture(ptr [[VAL]])
887 ; CHECK-NEXT: ret void
889 %val1 = alloca i8, align 4
890 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
891 call void @do_something()
892 call void @f(ptr align 4 nocapture noalias readonly %val1)
893 call void @capture(ptr %val)