xref: /llvm-project/llvm/test/Transforms/MemCpyOpt/memcpy.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=memcpyopt,dse -S -verify-memoryssa | FileCheck %s
3
4target 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"
5target triple = "i686-apple-darwin9"
6
7%0 = type { x86_fp80, x86_fp80 }
8%1 = type { i32, i32 }
9
10@C = external constant [0 x i8]
11
12declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) nocapture, ptr nocapture, i64, i1) nounwind
13declare void @llvm.memcpy.p0.p1.i64(ptr nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind
14declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind
15declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind
16declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
17declare void @llvm.memcpy.inline.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind
18declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
19
20; Check that one of the memcpy's are removed.
21;; FIXME: PR 8643 We should be able to eliminate the last memcpy here.
22define 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
31;
32entry:
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
40}
41
42declare void @ccoshl(ptr nocapture sret(%0), x86_fp80, x86_fp80) nounwind
43
44
45; The intermediate alloca and one of the memcpy's should be eliminated, the
46; other should be related with a memmove.
47define 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
51;
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
56
57}
58
59; The intermediate alloca and one of the memcpy's should be eliminated, the
60; other should be related with a memcpy.
61define 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
65;
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
70
71}
72
73; The intermediate alloca and one of the memcpy's should be eliminated, the
74; other should be related with a memcpy.
75define 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
79;
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
84
85}
86
87; Same as @test2_memcpy, but the remaining memcpy should remain non-inline even
88; if the one eliminated was inline.
89define 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
93;
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
98
99}
100
101; Same as @test2_memcpy, but the remaining memcpy should remain inline even
102; if the one eliminated was not inline.
103define 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
107;
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
112
113}
114
115; Same as @test2_memcpy, and the inline-ness should be preserved.
116define 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
120;
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
125
126}
127
128; Similar to test5_memcpy, but without noalias; check that memcpy.inline is not folded into memmove.
129define 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
135;
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
140}
141
142; When forwarding to memcpy(arg+1, arg+1), we don't need to create this memcpy.
143define 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
147;
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
154}
155
156; We have to retain this `memcpy(arg+2, arg+1)` forwarding.
157define 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
165;
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
172}
173
174@x = external global %0
175
176define 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
181;
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
186}
187
188
189; PR8644
190define 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
194;
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
199}
200
201; Make sure we don't remove the memcpy if the source address space doesn't match the byval argument
202define 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
208;
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
213}
214
215define 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
222;
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
228}
229
230define 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]]
237;
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
243}
244
245define 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
253;
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
257
258call:
259  call void @test4a(ptr align 1 byval(i8) %a1)
260  br label %exit
261
262exit:
263  ret void
264}
265
266declare void @test4a(ptr align 1 byval(i8))
267
268%struct.S = type { i128, [4 x i8]}
269
270@sS = external global %struct.S, align 16
271
272declare void @test5a(ptr align 16 byval(%struct.S)) nounwind ssp
273
274
275; rdar://8713376 - This memcpy can't be eliminated.
276define 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
285;
286entry:
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
293}
294
295;; Noop memcpy should be zapped.
296define void @test6(ptr %P) {
297; CHECK-LABEL: @test6(
298; CHECK-NEXT:    ret void
299;
300  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %P, ptr align 4 %P, i64 8, i1 false)
301  ret void
302}
303
304
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 }
308
309define 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]]
314;
315entry:
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
320}
321
322declare i32 @g(ptr align 8 byval(%struct.p))
323
324
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"
328
329define void @test8() {
330; CHECK-LABEL: @test8(
331; CHECK-NEXT:    ret void
332;
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
340}
341
342declare noalias ptr @malloc(i32) willreturn allockind("alloc,uninitialized") allocsize(0)
343
344; rdar://11341081
345%struct.big = type { [50 x i32] }
346
347define 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
357;
358entry:
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
367}
368
369define 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
377;
378entry:
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
385}
386
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'.
390
391%opaque = type opaque
392declare void @foo(ptr noalias nocapture)
393
394define 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 captures(none) [[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
402;
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
409}
410
411; don't create new addressspacecasts when we don't know they're safe for the target
412define 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
416;
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
421}
422
423declare void @f1(ptr nocapture sret(%struct.big))
424declare void @f2(ptr)
425
426declare void @f(ptr)
427declare void @f_byval(ptr byval(i32))
428declare void @f_full_readonly(ptr nocapture noalias readonly)
429
430define void @immut_param(ptr align 4 noalias %val) {
431; CHECK-LABEL: @immut_param(
432; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL:%.*]])
433; CHECK-NEXT:    ret void
434;
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
439}
440
441; Can't remove memcpy because dest may be captured.
442define 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
448;
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
453}
454
455; Can't remove memcpy because dest may be aliased.
456define 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 readonly align 4 captures(none) [[VAL1]])
462; CHECK-NEXT:    ret void
463;
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
469}
470
471; Can remove memcpy because alloca does not escape, so lack of noalias on the
472; argument doesn't matter.
473define void @immut_param_unescaped_alloca(ptr align 4 noalias %val) {
474; CHECK-LABEL: @immut_param_unescaped_alloca(
475; CHECK-NEXT:    call void @f(ptr readonly align 4 captures(none) [[VAL:%.*]])
476; CHECK-NEXT:    ret void
477;
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
482}
483
484; Can remove memcpy because the function is argmem: read, so there cannot be
485; a write to the escaped pointer.
486define 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 readonly align 4 captures(none) [[VAL:%.*]]) #[[ATTR6:[0-9]+]]
491; CHECK-NEXT:    ret void
492;
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
498}
499
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.
503define 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 align 4 captures(none) [[VAL1]]) #[[ATTR6]]
509; CHECK-NEXT:    ret void
510;
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
516}
517
518; Can't remove memcpy because dest may be written.
519define 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 align 4 captures(none) [[VAL1]])
524; CHECK-NEXT:    ret void
525;
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
530}
531
532define 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
536;
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
541}
542
543define 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 readonly captures(none) [[VAL:%.*]])
546; CHECK-NEXT:    ret void
547;
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
552}
553
554@gp = external constant [0 x i8]
555; Can't remove memcpy because dest is not unescaped alloca, so cpying is meaningfull.
556define 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 readonly align 4 captures(none) @gp)
560; CHECK-NEXT:    ret void
561;
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
565}
566
567; Can't remove memcpy for VLA because of unknown size and alignment.
568define 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 readonly align 4 captures(none) [[VAL1]])
573; CHECK-NEXT:    ret void
574;
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
579}
580
581; Can't remove memcpy for scalable vector, because of memcpy size sufficiency is unknown
582define 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 readonly align 4 captures(none) [[VAL1]])
587; CHECK-NEXT:    ret void
588;
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
593}
594
595; Can't remove memcpy because dst is modified between call and memcpy
596define 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 readonly align 4 captures(none) [[VAL1]])
601; CHECK-NEXT:    ret void
602;
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
608}
609
610; Can't remove memcpy because src is modified between call and memcpy
611define 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 readonly align 4 captures(none) [[VAL1]])
617; CHECK-NEXT:    ret void
618;
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
624}
625
626; Can't remove memcpy because memcpy is volatile
627define 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 readonly align 4 captures(none) [[VAL1]])
632; CHECK-NEXT:    ret void
633;
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
638}
639
640; Can't remove memcpy because address spaces are different.
641define 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 readonly align 4 captures(none) [[VAL1]])
646; CHECK-NEXT:    ret void
647;
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
652}
653
654define 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 readonly captures(none) [[VAL:%.*]])
657; CHECK-NEXT:    ret void
658;
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
663}
664
665; Can't remove memcpy if we remove, the bigger alignment couldn't replaced by smaller one.
666define 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 readonly captures(none) [[VAL1]])
671; CHECK-NEXT:    ret void
672;
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
677}
678
679define 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 readonly captures(none) [[VAL]])
684; CHECK-NEXT:    ret void
685;
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
692}
693
694; Can't remove memcpy, because if the %val directly passed to @f,
695; alignment of ptr to f's argument will be different.
696define 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 readonly captures(none) [[VAL3]])
703; CHECK-NEXT:    ret void
704;
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
711}
712
713; Can't remove memcpy, because alias might modify the src.
714define 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 readonly captures(none) [[VAL1]])
719; CHECK-NEXT:    ret void
720;
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
725}
726
727define 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
733;
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
740}
741
742; Can't remove memcpy, because alloca src is modified
743define 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
751;
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
759}
760
761; TODO: Remove memcpy
762define 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 readonly captures(none) [[VAL3]])
769; CHECK-NEXT:    ret void
770;
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
777}
778
779; Merge/drop noalias metadata when replacing parameter.
780define 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 readonly captures(none) [[PTR]])
784; CHECK-NEXT:    ret void
785;
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
791}
792
793define 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
798;
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
804}
805
806define void @byval_param_profile_metadata(ptr align 4 byval(i32) %ptr) {
807; CHECK-LABEL: @byval_param_profile_metadata(
808; CHECK-NEXT:    store i32 1, ptr [[PTR2:%.*]], align 4
809; CHECK-NEXT:    call void @f_byval(ptr byval(i32) align 4 [[PTR2]]), !prof [[PROF3:![0-9]+]], !memprof [[META4:![0-9]+]], !callsite [[META7:![0-9]+]]
810; CHECK-NEXT:    ret void
811;
812  %tmp = alloca i32, align 4
813  store i32 1, ptr %ptr
814  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)
815  call void @f_byval(ptr align 4 byval(i32) %tmp), !memprof !3, !callsite !6, !prof !7
816  ret void
817}
818
819define void @memcpy_memory_none(ptr %p, ptr %p2, i64 %size) {
820; CHECK-LABEL: @memcpy_memory_none(
821; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[SIZE:%.*]], i1 false) #[[ATTR7:[0-9]+]]
822; CHECK-NEXT:    ret void
823;
824  call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none)
825  ret void
826}
827
828declare void @do_something()
829declare void @capture(ptr)
830
831define void @memcpy_memcpy_escape_before(ptr noalias %P, ptr noalias %Q) {
832; CHECK-LABEL: @memcpy_memcpy_escape_before(
833; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [32 x i8], align 16
834; CHECK-NEXT:    call void @capture(ptr [[MEMTMP]])
835; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)
836; CHECK-NEXT:    call void @do_something()
837; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[MEMTMP]], i32 32, i1 false)
838; CHECK-NEXT:    ret void
839;
840  %memtmp = alloca [32 x i8], align 16
841  call void @capture(ptr %memtmp)
842  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
843  call void @do_something()
844  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
845  ret void
846}
847
848define void @memcpy_memcpy_escape_after1(ptr noalias %P, ptr noalias %Q) {
849; CHECK-LABEL: @memcpy_memcpy_escape_after1(
850; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [32 x i8], align 16
851; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)
852; CHECK-NEXT:    call void @do_something()
853; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P]], i32 32, i1 false)
854; CHECK-NEXT:    call void @capture(ptr [[MEMTMP]])
855; CHECK-NEXT:    ret void
856;
857  %memtmp = alloca [32 x i8], align 16
858  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
859  call void @do_something()
860  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
861  call void @capture(ptr %memtmp)
862  ret void
863}
864
865define void @memcpy_memcpy_escape_after2(ptr noalias %P, ptr noalias %Q) {
866; CHECK-LABEL: @memcpy_memcpy_escape_after2(
867; CHECK-NEXT:    call void @do_something()
868; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)
869; CHECK-NEXT:    call void @capture(ptr [[P]])
870; CHECK-NEXT:    ret void
871;
872  %memtmp = alloca [32 x i8], align 16
873  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)
874  call void @do_something()
875  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)
876  call void @capture(ptr %P)
877  ret void
878}
879
880define void @memcpy_byval_escape_after(ptr noalias %P) {
881; CHECK-LABEL: @memcpy_byval_escape_after(
882; CHECK-NEXT:    call void @do_something()
883; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P:%.*]])
884; CHECK-NEXT:    call void @capture(ptr [[P]])
885; CHECK-NEXT:    ret void
886;
887  %A = alloca [8 x i8]
888  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 %P, i64 8, i1 false)
889  call void @do_something()
890  call void @test4a(ptr align 1 byval(i8) %A)
891  call void @capture(ptr %P)
892  ret void
893}
894
895define void @memcpy_immut_escape_after(ptr align 4 noalias %val) {
896; CHECK-LABEL: @memcpy_immut_escape_after(
897; CHECK-NEXT:    call void @do_something()
898; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL:%.*]])
899; CHECK-NEXT:    call void @capture(ptr [[VAL]])
900; CHECK-NEXT:    ret void
901;
902  %val1 = alloca i8, align 4
903  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)
904  call void @do_something()
905  call void @f(ptr align 4 nocapture noalias readonly %val1)
906  call void @capture(ptr %val)
907  ret void
908}
909
910!0 = !{!0}
911!1 = !{!1, !0}
912!2 = !{!1}
913!3 = !{!4}
914!4 = !{!5, !"cold"}
915!5 = !{i64 123, i64 456}
916!6 = !{i64 123}
917!7 = !{!"branch_weights", i32 10}
918