[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / Transforms / MemCpyOpt / memcpy.ll
blob39b90adc74ef3830f5b1780dd55a0d00da304642
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 }
8 %1 = type { i32, i32 }
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(
24 ; CHECK-NEXT:  entry:
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
32 entry:
33   %tmp2 = alloca %0
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)
39   ret void
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)
55   ret void
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)
69   ret void
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)
83   ret void
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)
97   ret void
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)
111   ret void
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)
124   ret void
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)
139   ret void
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)
153   ret void
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)
171   ret void
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
182   %x.0 = alloca %0
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)
185   ret void
189 ; PR8644
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
195   %A = alloca %1
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)
198   ret void
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
209   %a1 = alloca %1
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)
212   ret void
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
223   %a1 = alloca %1
224   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)
225   store i8 0, ptr %a1
226   call void @test4a(ptr align 1 byval(i8) %a1)
227   ret void
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]]
238   %a1 = alloca %1
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)
242   ret i8 %x
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:%.*]]
248 ; CHECK:       call:
249 ; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P:%.*]])
250 ; CHECK-NEXT:    br label [[EXIT]]
251 ; CHECK:       exit:
252 ; CHECK-NEXT:    ret void
254   %a1 = alloca %1
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
258 call:
259   call void @test4a(ptr align 1 byval(i8) %a1)
260   br label %exit
262 exit:
263   ret void
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(
278 ; CHECK-NEXT:  entry:
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
286 entry:
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
290   store i8 4, ptr %a
291   call void @test5a(ptr align 16 byval(%struct.S) %y)
292   ret i32 0
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)
301   ret void
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(
311 ; CHECK-NEXT:  entry:
312 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @g(ptr byval([[STRUCT_P:%.*]]) align 8 [[Q:%.*]]) #[[ATTR2]]
313 ; CHECK-NEXT:    ret i32 [[CALL]]
315 entry:
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
319   ret i32 %call
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)
339   ret void
342 declare noalias ptr @malloc(i32) willreturn allockind("alloc,uninitialized") allocsize(0)
344 ; rdar://11341081
345 %struct.big = type { [50 x i32] }
347 define void @test9_addrspacecast() nounwind ssp uwtable {
348 ; CHECK-LABEL: @test9_addrspacecast(
349 ; CHECK-NEXT:  entry:
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
358 entry:
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)
366   ret void
369 define void @test9() nounwind ssp uwtable {
370 ; CHECK-LABEL: @test9(
371 ; CHECK-NEXT:  entry:
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
378 entry:
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)
384   ret void
387 ; rdar://14073661.
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
404   store i32 %y, ptr %a
405   call void @foo(ptr noalias nocapture %a)
406   %c = load i32, ptr %a
407   store i32 %c, ptr %x
408   ret void
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)
420   ret void
423 declare void @f1(ptr nocapture sret(%struct.big))
424 declare void @f2(ptr)
426 declare void @f(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)
438   ret void
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)
452   ret void
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)
468   ret void
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)
481   ret void
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)
497   ret void
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
502 ; this case.
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)
515   ret void
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)
529   ret void
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)
540   ret void
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)
551   ret void
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)
564   ret void
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)
578   ret void
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)
592   ret void
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)
607   ret void
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)
623   ret void
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)
637   ret void
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)
651   ret void
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)
662   ret void
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)
676   ret void
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)
691   ret void
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)
710   ret void
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)
724   ret void
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)
739   ret void
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)
758   ret void
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)
776   ret void
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
790   ret void
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
803   ret void
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)
812   ret void
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)
832   ret void
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)
849   ret void
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)
864   ret void
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
874   %A = alloca [8 x i8]
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)
879   ret void
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)
894   ret void
897 !0 = !{!0}
898 !1 = !{!1, !0}
899 !2 = !{!1}