xref: /llvm-project/llvm/test/Transforms/MemCpyOpt/stack-move.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt < %s -passes=memcpyopt -verify-memoryssa -S | FileCheck %s
3
4%struct.Foo = type { i32, i32, i32 }
5
6declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
7declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
8declare void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) noalias nocapture writeonly, ptr addrspace(1) noalias nocapture readonly, i64, i1 immarg)
9declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
10declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
11
12declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
13declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
14declare void @llvm.lifetime.start.p1(i64, ptr addrspace(1) nocapture)
15declare void @llvm.lifetime.end.p1(i64, ptr addrspace(1) nocapture)
16declare void @llvm.lifetime.start.p2(i64, ptr addrspace(2) nocapture)
17declare void @llvm.lifetime.end.p2(i64, ptr addrspace(2) nocapture)
18
19declare i32 @use_nocapture(ptr nocapture)
20declare i32 @use_maycapture(ptr noundef)
21declare i32 @use_readonly(ptr readonly)
22declare i32 @use_writeonly(ptr noundef) memory(write)
23
24define void @basic_memcpy() {
25; CHECK-LABEL: define void @basic_memcpy() {
26; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
27; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
28; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
29; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
30; CHECK-NEXT:    ret void
31;
32  %src = alloca %struct.Foo, align 4
33  %dest = alloca %struct.Foo, align 4
34  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
35  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
36  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
37  %1 = call i32 @use_nocapture(ptr nocapture %src)
38
39  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
40
41  %2 = call i32 @use_nocapture(ptr nocapture %dest)
42
43  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
44  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
45  ret void
46}
47
48define i32 @use_not_dominated_by_src_alloca() {
49; CHECK-LABEL: define i32 @use_not_dominated_by_src_alloca() {
50; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, align 4
51; CHECK-NEXT:    [[DEST_GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 -1
52; CHECK-NEXT:    [[DEST_USE:%.*]] = load i8, ptr [[DEST_GEP]], align 1
53; CHECK-NEXT:    ret i32 0
54;
55  %dest = alloca i1, align 1
56  ; Replacing the use of dest with src causes no domination uses.
57  %dest.gep = getelementptr i64, ptr %dest, i64 -1
58  %dest.use = load i8, ptr %dest.gep, align 1
59  %src = alloca i8, align 4
60  %src.val = load i1, ptr %src, align 4
61
62  store i1 %src.val, ptr %dest, align 1
63
64  ret i32 0
65}
66
67define void @basic_memmove() {
68; CHECK-LABEL: define void @basic_memmove() {
69; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
70; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
71; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
72; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
73; CHECK-NEXT:    ret void
74;
75  %src = alloca %struct.Foo, align 4
76  %dest = alloca %struct.Foo, align 4
77  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
78  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
79  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
80  %1 = call i32 @use_nocapture(ptr nocapture %src)
81
82  call void @llvm.memmove.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
83
84  %2 = call i32 @use_nocapture(ptr nocapture %dest)
85
86  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
87  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
88  ret void
89}
90
91; Tests that the optimization succeeds with a load/store pair.
92define void @load_store() {
93; CHECK-LABEL: define void @load_store() {
94; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
95; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
96; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
97; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
98; CHECK-NEXT:    ret void
99;
100  %src = alloca i32, align 4
101  %dest = alloca i32, align 4
102  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src)
103  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest)
104  store i32 42, ptr %src
105  %1 = call i32 @use_nocapture(ptr nocapture %src)
106
107  %src.val = load i32, ptr %src
108  store i32 %src.val, ptr %dest
109
110  %2 = call i32 @use_nocapture(ptr nocapture %dest)
111  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src)
112  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest)
113  ret void
114}
115
116; Test scalable vectors.
117define void @load_store_scalable(<vscale x 4 x i32> %x) {
118; CHECK-LABEL: define void @load_store_scalable
119; CHECK-SAME: (<vscale x 4 x i32> [[X:%.*]]) {
120; CHECK-NEXT:    [[SRC:%.*]] = alloca <vscale x 4 x i32>, align 16
121; CHECK-NEXT:    store <vscale x 4 x i32> [[X]], ptr [[SRC]], align 16
122; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
123; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
124; CHECK-NEXT:    ret void
125;
126  %src = alloca <vscale x 4 x i32>
127  %dest = alloca <vscale x 4 x i32>
128  call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %src)
129  call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %dest)
130  store <vscale x 4 x i32> %x, ptr %src
131  %1 = call i32 @use_nocapture(ptr nocapture %src)
132
133  %src.val = load <vscale x 4 x i32>, ptr %src
134  store <vscale x 4 x i32> %src.val, ptr %dest
135
136  %2 = call i32 @use_nocapture(ptr nocapture %dest)
137
138  call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %src)
139  call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %dest)
140  ret void
141}
142
143; Tests that merging two allocas shouldn't be more poisonous, smaller aligned src is valid.
144define void @align_up() {
145; CHECK-LABEL: define void @align_up() {
146; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
147; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
148; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
149; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
150; CHECK-NEXT:    ret void
151;
152  %src = alloca %struct.Foo, align 4
153  %dest = alloca %struct.Foo, align 8
154  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
155  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
156  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
157  %1 = call i32 @use_nocapture(ptr nocapture %src)
158
159  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
160
161  %2 = call i32 @use_nocapture(ptr nocapture %dest)
162  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
163  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
164  ret void
165}
166
167; Tests that we correctly remove extra lifetime intrinsics when performing the
168; optimization.
169define void @remove_extra_lifetime_intrinsics() {
170; CHECK-LABEL: define void @remove_extra_lifetime_intrinsics() {
171; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
172; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
173; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
174; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
175; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
176; CHECK-NEXT:    ret void
177;
178  %src = alloca %struct.Foo, align 4
179  %dest = alloca %struct.Foo, align 4
180  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
181  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
182  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
183  %1 = call i32 @use_nocapture(ptr nocapture %src)
184
185  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
186
187  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
188  %2 = call i32 @use_nocapture(ptr nocapture %dest)
189  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
190  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
191  %3 = call i32 @use_nocapture(ptr nocapture %dest)
192  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
193  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
194  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
195  ret void
196}
197
198; Tests that we won't insert lifetime markers if they don't exist originally.
199define void @no_lifetime() {
200; CHECK-LABEL: define void @no_lifetime() {
201; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
202; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
203; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
204; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
205; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
206; CHECK-NEXT:    ret void
207;
208  %src = alloca %struct.Foo, align 4
209  %dest = alloca %struct.Foo, align 4
210  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
211  %1 = call i32 @use_nocapture(ptr nocapture %src)
212
213  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
214
215  %2 = call i32 @use_nocapture(ptr nocapture %dest)
216  %3 = call i32 @use_nocapture(ptr nocapture %dest)
217  ret void
218}
219
220; Tests that aliasing src or dest but no modification desn't prevent transformations.
221define void @alias_no_mod() {
222; CHECK-LABEL: define void @alias_no_mod() {
223; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
224; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0
225; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
226; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
227; CHECK-NEXT:    [[SRC_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0
228; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
229; CHECK-NEXT:    ret void
230;
231  %src = alloca %struct.Foo, align 4
232  %dest = alloca %struct.Foo, align 4
233  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
234  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
235  %dest.alias = getelementptr %struct.Foo, ptr %dest, i32 0, i32 0
236  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
237  %1 = call i32 @use_nocapture(ptr nocapture %src)
238
239  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
240
241  %src.alias = getelementptr %struct.Foo, ptr %src, i32 0, i32 0
242  %2 = call i32 @use_nocapture(ptr nocapture %dest)
243  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
244  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
245  ret void
246}
247
248; Scope domain
249!0 = !{!0}
250; Scope in that domain
251!1 = !{!1, !0}
252; Scope list
253!2 = !{!1}
254
255!3 = !{!"Whatever"}
256
257; Tests that we remove scoped noalias metadata from a call.
258define void @remove_scoped_noalias() {
259; CHECK-LABEL: define void @remove_scoped_noalias() {
260; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
261; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
262; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0:![0-9]+]]
263; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
264; CHECK-NEXT:    ret void
265;
266  %src = alloca %struct.Foo, align 4
267  %dest = alloca %struct.Foo, align 4
268  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
269  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
270  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
271  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2
272
273  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
274
275  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
276  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2
277  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
278  ret void
279}
280
281; Tests that we remove metadata on the merged alloca.
282define void @remove_alloca_metadata() {
283; CHECK-LABEL: define void @remove_alloca_metadata() {
284; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
285; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
286; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0]]
287; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
288; CHECK-NEXT:    ret void
289;
290  %src = alloca %struct.Foo, align 4, !annotation !3
291  %dest = alloca %struct.Foo, align 4
292  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
293  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
294  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
295  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2
296
297  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
298
299  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2
300  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
301  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
302  ret void
303}
304
305; Tests that we remove scoped noalias metadata from a call.
306; And confirm that don't crash on noalias metadata on lifetime markers.
307define void @noalias_on_lifetime() {
308; CHECK-LABEL: define void @noalias_on_lifetime() {
309; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
310; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
311; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0]]
312; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
313; CHECK-NEXT:    ret void
314;
315  %src = alloca %struct.Foo, align 4
316  %dest = alloca %struct.Foo, align 4
317  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
318  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
319  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
320  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2
321
322  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
323
324  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src), !alias.scope !2
325  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2
326  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest), !noalias !2
327  ret void
328}
329
330; Tests that we can merge alloca if the dest and src has only refs except lifetime intrinsics.
331define void @src_ref_dest_ref_after_copy() {
332; CHECK-LABEL: define void @src_ref_dest_ref_after_copy() {
333; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
334; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
335; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]])
336; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]])
337; CHECK-NEXT:    ret void
338;
339  %src = alloca %struct.Foo, align 4
340  %dest = alloca %struct.Foo, align 4
341  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
342  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
343  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
344
345  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
346
347  %1 = call i32 @use_readonly(ptr nocapture %src)
348  %2 = call i32 @use_readonly(ptr nocapture %dest)
349  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
350  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
351  ret void
352}
353
354; Tests that we can merge alloca if the dest and src has only mods.
355define void @src_mod_dest_mod_after_copy() {
356; CHECK-LABEL: define void @src_mod_dest_mod_after_copy() {
357; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
358; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
359; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]])
360; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]])
361; CHECK-NEXT:    ret void
362;
363  %src = alloca %struct.Foo, align 4
364  %dest = alloca %struct.Foo, align 4
365  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
366  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
367  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
368
369  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
370
371  %1 = call i32 @use_writeonly(ptr nocapture %src)
372  %2 = call i32 @use_writeonly(ptr nocapture %dest)
373  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
374  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
375  ret void
376}
377
378define void @avoid_memory_use_last_user_crash() {
379; CHECK-LABEL: define void @avoid_memory_use_last_user_crash() {
380; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
381; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
382; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[SRC]], align 4
383; CHECK-NEXT:    ret void
384;
385  %src = alloca %struct.Foo, align 4
386  %dest = alloca %struct.Foo, align 4
387  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
388  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
389  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
390  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
391  %v = load i32, ptr %dest
392  ret void
393}
394
395; For multi-bb patch, we will insert it for next immediate post dominator block.
396define void @terminator_lastuse() personality i32 0 {
397; CHECK-LABEL: define void @terminator_lastuse() personality i32 0 {
398; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
399; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
400; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
401; CHECK-NEXT:    [[RV:%.*]] = invoke i32 @use_nocapture(ptr [[SRC]])
402; CHECK-NEXT:            to label [[SUC:%.*]] unwind label [[UNW:%.*]]
403; CHECK:       unw:
404; CHECK-NEXT:    [[LP:%.*]] = landingpad i32
405; CHECK-NEXT:            cleanup
406; CHECK-NEXT:    resume i32 0
407; CHECK:       suc:
408; CHECK-NEXT:    ret void
409;
410  %src = alloca %struct.Foo, align 4
411  %dest = alloca %struct.Foo, align 4
412  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
413  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
414  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
415  %1 = call i32 @use_nocapture(ptr nocapture %src)
416
417  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
418
419  call void @llvm.lifetime.end.p0(i64 12, ptr %src)
420  %rv = invoke i32 @use_nocapture(ptr %dest)
421  to label %suc unwind label %unw
422unw:
423  %lp = landingpad i32 cleanup
424  resume i32 0
425suc:
426  ret void
427}
428
429define void @multi_bb_memcpy(i1 %b) {
430; CHECK-LABEL: define void @multi_bb_memcpy
431; CHECK-SAME: (i1 [[B:%.*]]) {
432; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
433; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
434; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
435; CHECK-NEXT:    br label [[BB0:%.*]]
436; CHECK:       bb0:
437; CHECK-NEXT:    br label [[BB1:%.*]]
438; CHECK:       bb1:
439; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
440; CHECK-NEXT:    ret void
441;
442  %src = alloca i32, align 4
443  %dest = alloca i32, align 4
444  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src)
445  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest)
446  store i32 42, ptr %src
447  %1 = call i32 @use_nocapture(ptr nocapture %src)
448  br label %bb0
449
450bb0:
451  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 4, i1 false)
452  br label %bb1
453
454bb1:
455  %2 = call i32 @use_nocapture(ptr nocapture %dest)
456  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src)
457  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest)
458  ret void
459}
460
461define void @multi_bb_load_store(i1 %b) {
462; CHECK-LABEL: define void @multi_bb_load_store
463; CHECK-SAME: (i1 [[B:%.*]]) {
464; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
465; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
466; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
467; CHECK-NEXT:    br label [[BB0:%.*]]
468; CHECK:       bb0:
469; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
470; CHECK-NEXT:    ret void
471;
472  %src = alloca i32, align 4
473  %dest = alloca i32, align 4
474  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src)
475  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest)
476  store i32 42, ptr %src
477  %1 = call i32 @use_nocapture(ptr nocapture %src)
478
479  %src.val = load i32, ptr %src
480  store i32 %src.val, ptr %dest
481  br label %bb0
482
483bb0:
484  %2 = call i32 @use_nocapture(ptr nocapture %dest)
485  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src)
486  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest)
487  ret void
488}
489
490; FIXME: merge allocas for bb-separated, but logically straight.
491; We might be handle those load/store MemCpyOpt totally
492define void @multi_bb_separated_load_store(i1 %b) {
493; CHECK-LABEL: define void @multi_bb_separated_load_store
494; CHECK-SAME: (i1 [[B:%.*]]) {
495; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
496; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4
497; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[SRC]])
498; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[DEST]])
499; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
500; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
501; CHECK-NEXT:    [[SRC_VAL:%.*]] = load i32, ptr [[SRC]], align 4
502; CHECK-NEXT:    br label [[BB0:%.*]]
503; CHECK:       bb0:
504; CHECK-NEXT:    store i32 [[SRC_VAL]], ptr [[DEST]], align 4
505; CHECK-NEXT:    br label [[BB1:%.*]]
506; CHECK:       bb1:
507; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
508; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[SRC]])
509; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[DEST]])
510; CHECK-NEXT:    ret void
511;
512  %src = alloca i32, align 4
513  %dest = alloca i32, align 4
514  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src)
515  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest)
516  store i32 42, ptr %src
517  %1 = call i32 @use_nocapture(ptr nocapture %src)
518
519  %src.val = load i32, ptr %src
520  br label %bb0
521
522bb0:
523  store i32 %src.val, ptr %dest
524  br label %bb1
525
526bb1:
527  %2 = call i32 @use_nocapture(ptr nocapture %dest)
528  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src)
529  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest)
530  ret void
531}
532
533define void @multi_bb_simple_br(i1 %b) {
534; CHECK-LABEL: define void @multi_bb_simple_br
535; CHECK-SAME: (i1 [[B:%.*]]) {
536; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
537; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
538; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
539; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
540; CHECK:       bb0:
541; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
542; CHECK-NEXT:    br label [[BB2:%.*]]
543; CHECK:       bb1:
544; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
545; CHECK-NEXT:    br label [[BB2]]
546; CHECK:       bb2:
547; CHECK-NEXT:    ret void
548;
549  %src = alloca %struct.Foo, align 4
550  %dest = alloca %struct.Foo, align 4
551  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
552  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
553  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
554  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
555  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
556  br i1 %b, label %bb0, label %bb1
557
558bb0:
559  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
560  br label %bb2
561
562bb1:
563  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
564  br label %bb2
565
566bb2:
567  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
568  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
569  ret void
570}
571
572; Test for BasicBlock and Instruction mixed dominator finding.
573define void @multi_bb_dom_test0(i1 %b) {
574; CHECK-LABEL: define void @multi_bb_dom_test0
575; CHECK-SAME: (i1 [[B:%.*]]) {
576; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
577; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
578; CHECK:       bb0:
579; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
580; CHECK-NEXT:    br label [[BB2:%.*]]
581; CHECK:       bb1:
582; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4
583; CHECK-NEXT:    br label [[BB2]]
584; CHECK:       bb2:
585; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
586; CHECK-NEXT:    ret void
587;
588  %src = alloca %struct.Foo, align 4
589  %dest = alloca %struct.Foo, align 4
590  br i1 %b, label %bb0, label %bb1
591
592bb0:
593  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
594  br label %bb2
595
596bb1:
597  store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src
598  br label %bb2
599
600bb2:
601  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
602  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
603  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
604
605  ret void
606
607}
608
609; Test for BasicBlock and Instruction mixed dominator finding.
610define void @multi_bb_dom_test1(i1 %b) {
611; CHECK-LABEL: define void @multi_bb_dom_test1
612; CHECK-SAME: (i1 [[B:%.*]]) {
613; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
614; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
615; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
616; CHECK:       bb0:
617; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
618; CHECK-NEXT:    br label [[BB2:%.*]]
619; CHECK:       bb1:
620; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4
621; CHECK-NEXT:    br label [[BB2]]
622; CHECK:       bb2:
623; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
624; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
625; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
626; CHECK-NEXT:    ret void
627; CHECK:       unr:
628; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
629; CHECK-NEXT:    br label [[BB2]]
630;
631  %src = alloca %struct.Foo, align 4
632  %dest = alloca %struct.Foo, align 4
633  br i1 %b, label %bb0, label %bb1
634
635bb0:
636  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
637  br label %bb2
638
639bb1:
640  store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src
641  br label %bb2
642
643bb2:
644  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
645  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1
646  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
647
648  ret void
649
650unr:
651  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
652  br label %bb2
653}
654
655; Test for BasicBlock and Instruction mixed post-dominator finding.
656define void @multi_bb_pdom_test0(i1 %b) {
657; CHECK-LABEL: define void @multi_bb_pdom_test0
658; CHECK-SAME: (i1 [[B:%.*]]) {
659; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
660; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
661; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
662; CHECK:       bb0:
663; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
664; CHECK-NEXT:    br label [[BB2:%.*]]
665; CHECK:       bb1:
666; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
667; CHECK-NEXT:    br label [[BB2]]
668; CHECK:       bb2:
669; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
670; CHECK-NEXT:    ret void
671;
672  %src = alloca %struct.Foo, align 4
673  %dest = alloca %struct.Foo, align 4
674  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
675  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
676  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1
677  br i1 %b, label %bb0, label %bb1
678
679bb0:
680  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
681  br label %bb2
682
683bb1:
684  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
685  br label %bb2
686
687bb2:
688  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
689  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
690  ret void
691
692  uselistorder ptr %dest, {  2, 3, 0, 1, 4, 5 }
693}
694
695; Test for inserting lifetime.end after the phi-node
696define void @multi_bb_pdom_test1(i1 %b) {
697; CHECK-LABEL: define void @multi_bb_pdom_test1
698; CHECK-SAME: (i1 [[B:%.*]]) {
699; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
700; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
701; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
702; CHECK:       bb0:
703; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
704; CHECK-NEXT:    br label [[BB2:%.*]]
705; CHECK:       bb1:
706; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
707; CHECK-NEXT:    br label [[BB2]]
708; CHECK:       bb2:
709; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 42, [[BB0]] ], [ 41, [[BB1]] ]
710; CHECK-NEXT:    ret void
711;
712  %src = alloca %struct.Foo, align 4
713  %dest = alloca %struct.Foo, align 4
714  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
715  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
716  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1
717  br i1 %b, label %bb0, label %bb1
718
719bb0:
720  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
721  br label %bb2
722
723bb1:
724  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
725  br label %bb2
726
727bb2:
728  %i = phi i32 [ 42, %bb0 ], [ 41, %bb1 ]
729  ret void
730
731}
732
733; Test for existing unreachable cycle
734define void @multi_bb_pdom_test2(i1 %b) {
735; CHECK-LABEL: define void @multi_bb_pdom_test2
736; CHECK-SAME: (i1 [[B:%.*]]) {
737; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
738; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
739; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
740; CHECK-NEXT:    ret void
741; CHECK:       unr1:
742; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
743; CHECK-NEXT:    br label [[UNR2:%.*]]
744; CHECK:       unr2:
745; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
746; CHECK-NEXT:    br label [[UNR1:%.*]]
747;
748  %src = alloca %struct.Foo, align 4
749  %dest = alloca %struct.Foo, align 4
750  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
751  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
752  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1
753  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
754  ret void
755
756unr1:
757  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
758  br label %unr2
759
760unr2:
761  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
762  br label %unr1
763
764}
765
766define void @multi_bb_loop(i32 %n) {
767; CHECK-LABEL: define void @multi_bb_loop
768; CHECK-SAME: (i32 [[N:%.*]]) {
769; CHECK-NEXT:  entry:
770; CHECK-NEXT:    [[NLT1:%.*]] = icmp slt i32 [[N]], 1
771; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
772; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4
773; CHECK-NEXT:    br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]]
774; CHECK:       loop_body:
775; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ]
776; CHECK-NEXT:    [[NEW_I]] = add i32 [[I]], 1
777; CHECK-NEXT:    store i32 [[NEW_I]], ptr [[SRC]], align 4
778; CHECK-NEXT:    [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]]
779; CHECK-NEXT:    br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]]
780; CHECK:       loop_exit:
781; CHECK-NEXT:    ret void
782;
783entry:
784  %nlt1 = icmp slt i32 %n, 1
785  %src = alloca %struct.Foo, align 8
786  %dest = alloca %struct.Foo, align 8
787  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
788  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
789  store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src
790  br i1 %nlt1, label %loop_exit, label %loop_body
791
792loop_body:
793  %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ]
794  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false)
795  %new_i = add i32 %i, 1
796  store i32 %new_i, ptr %src
797  %igtn = icmp sgt i32 %new_i, %n
798  br i1 %igtn, label %loop_exit, label %loop_body
799
800loop_exit:
801  ret void
802}
803
804define void @multi_bb_unreachable_modref(i1 %b0) {
805; CHECK-LABEL: define void @multi_bb_unreachable_modref
806; CHECK-SAME: (i1 [[B0:%.*]]) {
807; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
808; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
809; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
810; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[EXIT:%.*]]
811; CHECK:       exit:
812; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
813; CHECK-NEXT:    ret void
814; CHECK:       bb0:
815; CHECK-NEXT:    ret void
816;
817  %src = alloca %struct.Foo, align 4
818  %dest = alloca %struct.Foo, align 4
819  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
820  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
821  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
822  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
823  br i1 %b0, label %bb0, label %exit
824
825exit:
826  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
827  ret void
828
829bb0:
830  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
831  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
832  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
833  ret void
834}
835
836define void @multi_bb_non_dominated(i1 %b0, i1 %b1) {
837; CHECK-LABEL: define void @multi_bb_non_dominated
838; CHECK-SAME: (i1 [[B0:%.*]], i1 [[B1:%.*]]) {
839; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
840; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
841; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
842; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[BB1:%.*]]
843; CHECK:       bb0:
844; CHECK-NEXT:    br label [[BB2:%.*]]
845; CHECK:       bb1:
846; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
847; CHECK-NEXT:    br label [[BB2]]
848; CHECK:       bb2:
849; CHECK-NEXT:    ret void
850;
851  %src = alloca %struct.Foo, align 4
852  %dest = alloca %struct.Foo, align 4
853  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
854  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
855  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
856  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
857  br i1 %b0, label %bb0, label %bb1
858
859bb0:
860  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
861  br label %bb2
862
863bb1:
864  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
865  br label %bb2
866
867bb2:
868  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
869  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
870  ret void
871}
872
873; TODO: to merge following `is_def` cases, we need to do liveness analysis
874; or something that distinguish the full-size-Mod as a Def.
875; Tests that a memcpy that completely overwrites a stack value is a definition
876; for the purposes of liveness analysis.
877define void @memcpy_is_def() {
878; CHECK-LABEL: define void @memcpy_is_def() {
879; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
880; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
881; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
882; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
883; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
884; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
885; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
886; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
887; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[SRC]], ptr align 4 [[DEST]], i64 12, i1 false)
888; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
889; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
890; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
891; CHECK-NEXT:    ret void
892;
893  %src = alloca %struct.Foo, align 4
894  %dest = alloca %struct.Foo, align 4
895  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
896  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
897  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
898  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
899  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
900  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
901  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %src, ptr align 4 %dest, i64 12, i1 false)
902  %3 = call i32 @use_nocapture(ptr noundef nocapture %src)
903  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
904  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
905  ret void
906}
907
908; TODO: merge allocas
909; Tests that a memset that completely overwrites a stack value is a definition
910; for the purposes of liveness analysis.
911define void @memset_is_def() {
912; CHECK-LABEL: define void @memset_is_def() {
913; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
914; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
915; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
916; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
917; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
918; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
919; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
920; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
921; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[SRC]], i8 42, i64 12, i1 false)
922; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
923; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
924; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
925; CHECK-NEXT:    ret void
926;
927  %src = alloca %struct.Foo, align 4
928  %dest = alloca %struct.Foo, align 4
929  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
930  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
931  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
932  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
933  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
934  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
935  call void @llvm.memset.p0.i64(ptr align 4 %src, i8 42, i64 12, i1 false)
936  %3 = call i32 @use_nocapture(ptr noundef nocapture %src)
937  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
938  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
939  ret void
940}
941
942; TODO: merge allocas
943; Tests that a store that completely overwrites a stack value is a definition
944; for the purposes of liveness analysis.
945define void @store_is_def() {
946; CHECK-LABEL: define void @store_is_def() {
947; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4
948; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4
949; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[SRC]])
950; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[DEST]])
951; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
952; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
953; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4
954; CHECK-NEXT:    store i32 [[TMP2]], ptr [[DEST]], align 4
955; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
956; CHECK-NEXT:    store i32 64, ptr [[SRC]], align 4
957; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
958; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[SRC]])
959; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[DEST]])
960; CHECK-NEXT:    ret void
961;
962  %src = alloca i32, align 4
963  %dest = alloca i32, align 4
964  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src)
965  call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest)
966  store i32 42, ptr %src
967  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
968  %2 = load i32, ptr %src
969  store i32 %2, ptr %dest
970  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
971  store i32 64, ptr %src
972  %4 = call i32 @use_nocapture(ptr noundef nocapture %src)
973  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src)
974  call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest)
975  ret void
976}
977
978; TODO: merge src and dest, because any execution path doesn't cause conflicts.
979; Tests that exists modref for both src/dest, but it never conflict on the execution.
980define void @multi_bb_dataflow(i1 %b) {
981; CHECK-LABEL: define void @multi_bb_dataflow
982; CHECK-SAME: (i1 [[B:%.*]]) {
983; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
984; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
985; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
986; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
987; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
988; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
989; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
990; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
991; CHECK:       bb0:
992; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
993; CHECK-NEXT:    br label [[BB2:%.*]]
994; CHECK:       bb1:
995; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
996; CHECK-NEXT:    br label [[BB2]]
997; CHECK:       bb2:
998; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
999; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1000; CHECK-NEXT:    ret void
1001;
1002  %src = alloca %struct.Foo, align 4
1003  %dest = alloca %struct.Foo, align 4
1004  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1005  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1006  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1007  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
1008  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1009  br i1 %b, label %bb0, label %bb1
1010
1011bb0:
1012  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
1013  br label %bb2
1014
1015bb1:
1016  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1017  br label %bb2
1018
1019bb2:
1020  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1021  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1022  ret void
1023}
1024
1025
1026; Optimization failures follow:
1027
1028; Tests that a memcpy that doesn't completely overwrite a stack value is a use
1029; for the purposes of liveness analysis, not a definition.
1030define void @incomplete_memcpy() {
1031; CHECK-LABEL: define void @incomplete_memcpy() {
1032; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1033; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1034; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1035; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1036; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1037; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1038; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 11, i1 false)
1039; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
1040; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1041; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1042; CHECK-NEXT:    ret void
1043;
1044  %src = alloca %struct.Foo, align 4
1045  %dest = alloca %struct.Foo, align 4
1046  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1047  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1048  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1049  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
1050  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 11, i1 false)
1051  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1052  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1053  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1054  ret void
1055}
1056
1057; Tests that a store that doesn't completely overwrite a stack value is a use
1058; for the purposes of liveness analysis, not a definition.
1059define void @incomplete_store() {
1060; CHECK-LABEL: define void @incomplete_store() {
1061; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1062; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1063; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1064; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1065; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1066; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1067; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4
1068; CHECK-NEXT:    store i32 [[TMP2]], ptr [[DEST]], align 4
1069; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
1070; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1071; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1072; CHECK-NEXT:    ret void
1073;
1074  %src = alloca %struct.Foo, align 4
1075  %dest = alloca %struct.Foo, align 4
1076  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1077  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1078  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1079  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
1080  %2 = load i32, ptr %src
1081  store i32 %2, ptr %dest
1082  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1083  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1084  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1085  ret void
1086}
1087
1088; Tests that dynamically-sized allocas are never merged.
1089define void @dynamically_sized_alloca(i64 %i) {
1090; CHECK-LABEL: define void @dynamically_sized_alloca
1091; CHECK-SAME: (i64 [[I:%.*]]) {
1092; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 [[I]], align 4
1093; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 [[I]], align 4
1094; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr captures(none) [[SRC]])
1095; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr captures(none) [[DEST]])
1096; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1097; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1098; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1099; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1100; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr captures(none) [[SRC]])
1101; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr captures(none) [[DEST]])
1102; CHECK-NEXT:    ret void
1103;
1104  %src = alloca i8, i64 %i, align 4
1105  %dest = alloca i8, i64 %i, align 4
1106  call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %src)
1107  call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %dest)
1108  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1109  %1 = call i32 @use_nocapture(ptr nocapture %src)
1110
1111  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1112
1113  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1114  call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %src)
1115  call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %dest)
1116  ret void
1117}
1118
1119
1120; Tests that inalloca attributed allocas are never merged, to prevent stacksave/stackrestore handling.
1121define void @inalloca() {
1122; CHECK-LABEL: define void @inalloca() {
1123; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1124; CHECK-NEXT:    [[DEST:%.*]] = alloca inalloca [[STRUCT_FOO]], align 4
1125; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1126; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1127; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1128; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1129; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1130; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1131; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1132; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1133; CHECK-NEXT:    ret void
1134;
1135  %src = alloca %struct.Foo, align 4
1136  %dest = alloca inalloca %struct.Foo, align 4
1137  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1138  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1139  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1140  %1 = call i32 @use_nocapture(ptr nocapture %src)
1141
1142  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1143
1144  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1145  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1146  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1147  ret void
1148}
1149
1150; Tests that a memcpy with a dynamic size is never optimized.
1151define void @dynamically_sized_memcpy(i64 %size) {
1152; CHECK-LABEL: define void @dynamically_sized_memcpy
1153; CHECK-SAME: (i64 [[SIZE:%.*]]) {
1154; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1155; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1156; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1157; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1158; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1159; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1160; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 [[SIZE]], i1 false)
1161; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1162; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1163; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1164; CHECK-NEXT:    ret void
1165;
1166  %src = alloca %struct.Foo, align 4
1167  %dest = alloca %struct.Foo, align 4
1168  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1169  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1170  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1171  %1 = call i32 @use_nocapture(ptr nocapture %src)
1172
1173  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 %size, i1 false)
1174
1175  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1176  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1177  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1178  ret void
1179}
1180
1181; Tests that allocas with different sizes aren't merged together.
1182define void @mismatched_alloca_size() {
1183; CHECK-LABEL: define void @mismatched_alloca_size() {
1184; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 24, align 4
1185; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 12, align 4
1186; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 24, ptr captures(none) [[SRC]])
1187; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1188; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1189; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1190; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1191; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1192; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 24, ptr captures(none) [[SRC]])
1193; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1194; CHECK-NEXT:    ret void
1195;
1196  %src = alloca i8, i64 24, align 4
1197  %dest = alloca i8, i64 12, align 4
1198  call void @llvm.lifetime.start.p0(i64 24, ptr nocapture %src)
1199  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1200  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1201  %1 = call i32 @use_nocapture(ptr nocapture %src)
1202
1203  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1204
1205  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1206  call void @llvm.lifetime.end.p0(i64 24, ptr nocapture %src)
1207  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1208  ret void
1209}
1210
1211; Tests that allocas with mismatched address spaces aren't combined.
1212define void @mismatched_alloca_addrspace() {
1213; CHECK-LABEL: define void @mismatched_alloca_addrspace() {
1214; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 24, align 4, addrspace(1)
1215; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 12, align 4, addrspace(2)
1216; CHECK-NEXT:    call void @llvm.lifetime.start.p1(i64 24, ptr addrspace(1) captures(none) [[SRC]])
1217; CHECK-NEXT:    call void @llvm.lifetime.start.p2(i64 12, ptr addrspace(2) captures(none) [[DEST]])
1218; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr addrspace(1) [[SRC]], align 4
1219; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr addrspace(1) captures(none) [[SRC]])
1220; CHECK-NEXT:    call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 [[DEST]], ptr addrspace(1) align 4 [[SRC]], i64 12, i1 false)
1221; CHECK-NEXT:    call void @llvm.lifetime.end.p1(i64 24, ptr addrspace(1) captures(none) [[SRC]])
1222; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr addrspace(2) captures(none) [[DEST]])
1223; CHECK-NEXT:    call void @llvm.lifetime.end.p2(i64 12, ptr addrspace(2) captures(none) [[DEST]])
1224; CHECK-NEXT:    ret void
1225;
1226  %src = alloca i8, i64 24, align 4, addrspace(1)
1227  %dest = alloca i8, i64 12, align 4, addrspace(2)
1228  call void @llvm.lifetime.start.p1(i64 24, ptr addrspace(1) nocapture %src)
1229  call void @llvm.lifetime.start.p2(i64 12, ptr addrspace(2) nocapture %dest)
1230  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr addrspace(1) %src
1231  %1 = call i32 @use_nocapture(ptr addrspace(1) nocapture %src)
1232
1233  call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 %dest, ptr addrspace(1) align 4 %src, i64 12, i1 false)
1234
1235  call void @llvm.lifetime.end.p1(i64 24, ptr addrspace(1) nocapture %src)
1236  %2 = call i32 @use_nocapture(ptr addrspace(2) nocapture %dest)
1237  call void @llvm.lifetime.end.p2(i64 12, ptr addrspace(2) nocapture %dest)
1238  ret void
1239}
1240
1241; Tests that volatile memcpys aren't removed.
1242define void @volatile_memcpy() {
1243; CHECK-LABEL: define void @volatile_memcpy() {
1244; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1245; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1246; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1247; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1248; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1249; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1250; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 true)
1251; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1252; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1253; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1254; CHECK-NEXT:    ret void
1255;
1256  %src = alloca %struct.Foo, align 4
1257  %dest = alloca %struct.Foo, align 4
1258  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1259  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1260  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1261  %1 = call i32 @use_nocapture(ptr nocapture %src)
1262
1263  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 true)
1264
1265  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1266  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1267  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1268  ret void
1269}
1270
1271; Tests that the optimization isn't performed when the destination is captured.
1272define void @dest_captured() {
1273; CHECK-LABEL: define void @dest_captured() {
1274; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1275; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1276; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1277; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1278; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1279; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1280; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1281; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_maycapture(ptr [[DEST]])
1282; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1283; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1284; CHECK-NEXT:    ret void
1285;
1286  %src = alloca %struct.Foo, align 4
1287  %dest = alloca %struct.Foo, align 4
1288  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1289  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1290  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1291
1292  %1 = call i32 @use_nocapture(ptr nocapture %src)
1293
1294  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1295  %2 = call i32 @use_maycapture(ptr %dest)
1296  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1297  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1298  ret void
1299}
1300
1301; Tests that the optimization isn't performed when the source is captured.
1302define void @src_captured() {
1303; CHECK-LABEL: define void @src_captured() {
1304; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1305; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1306; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1307; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1308; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1309; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_maycapture(ptr [[SRC]])
1310; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1311; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1312; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1313; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1314; CHECK-NEXT:    ret void
1315;
1316  %src = alloca %struct.Foo, align 4
1317  %dest = alloca %struct.Foo, align 4
1318  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1319  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1320  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1321  %1 = call i32 @use_maycapture(ptr %src)
1322
1323  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1324
1325  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1326  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1327  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1328  ret void
1329}
1330
1331; Tests that failure if any modref exists before the copy,
1332; Exactly ref seems safe because no mod say ref would be always undefined, but to make simple and conservative.
1333define void @mod_ref_before_copy() {
1334; CHECK-LABEL: define void @mod_ref_before_copy() {
1335; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1336; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1337; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1338; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1339; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1340; CHECK-NEXT:    [[R:%.*]] = call i32 @use_readonly(ptr captures(none) [[DEST]])
1341; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1342; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1343; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1344; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1345; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1346; CHECK-NEXT:    ret void
1347;
1348  %src = alloca %struct.Foo, align 4
1349  %dest = alloca %struct.Foo, align 4
1350  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1351  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1352  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1353  %r = call i32 @use_readonly(ptr nocapture %dest)
1354  %1 = call i32 @use_nocapture(ptr nocapture %src)
1355
1356  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1357
1358  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1359  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1360  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1361  ret void
1362}
1363
1364; Tests that failure because copy semantics will change if dest is replaced with src.
1365define void @mod_dest_before_copy() {
1366; CHECK-LABEL: define void @mod_dest_before_copy() {
1367; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1368; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1369; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1370; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1371; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1372; CHECK-NEXT:    store i32 13, ptr [[DEST]], align 4
1373; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1374; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1375; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1376; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1377; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1378; CHECK-NEXT:    ret void
1379;
1380  %src = alloca %struct.Foo, align 4
1381  %dest = alloca %struct.Foo, align 4
1382  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1383  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1384  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1385  store i32 13, ptr %dest
1386  %1 = call i32 @use_nocapture(ptr nocapture %src)
1387
1388  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1389
1390  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1391  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1392  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1393  ret void
1394}
1395
1396define void @mod_src_before_store_after_load() {
1397; CHECK-LABEL: define void @mod_src_before_store_after_load() {
1398; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1399; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1400; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1401; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1402; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1403; CHECK-NEXT:    store i32 13, ptr [[DEST]], align 4
1404; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1405; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1406; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 4
1407; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1408; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1409; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1410; CHECK-NEXT:    ret void
1411;
1412  %src = alloca %struct.Foo, align 4
1413  %dest = alloca %struct.Foo, align 4
1414  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1415  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1416  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1417  store i32 13, ptr %dest
1418  %1 = call i32 @use_nocapture(ptr nocapture %src)
1419
1420  %src.val = load %struct.Foo, ptr %src
1421  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src
1422  store %struct.Foo %src.val, ptr %dest
1423
1424  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1425  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1426  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1427  ret void
1428}
1429
1430; Tests that the optimization isn't performed,
1431; when the source may have mod and dest may have ref after the full copy.
1432define void @src_mod_dest_ref_after_copy() {
1433; CHECK-LABEL: define void @src_mod_dest_ref_after_copy() {
1434; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1435; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1436; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1437; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1438; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1439; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1440; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 4
1441; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1442; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1443; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1444; CHECK-NEXT:    ret void
1445;
1446  %src = alloca %struct.Foo, align 4
1447  %dest = alloca %struct.Foo, align 4
1448  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1449  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1450  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1451
1452  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1453
1454  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src
1455  %1 = call i32 @use_nocapture(ptr nocapture %dest)
1456  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1457  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1458  ret void
1459}
1460
1461; Tests that the optimization isn't performed.
1462; Merging dest to src is no longer valid if conflicting Mod/Ref exist.
1463define void @src_ref_dest_mod_after_copy() {
1464; CHECK-LABEL: define void @src_ref_dest_mod_after_copy() {
1465; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1466; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1467; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1468; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1469; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1470; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1471; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[DEST]], align 4
1472; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1473; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1474; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1475; CHECK-NEXT:    ret void
1476;
1477  %src = alloca %struct.Foo, align 4
1478  %dest = alloca %struct.Foo, align 4
1479  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1480  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1481  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1482
1483  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1484
1485  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %dest
1486  %1 = call i32 @use_nocapture(ptr nocapture %src)
1487  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1488  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1489  ret void
1490}
1491
1492; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks
1493define void @dest_alias_mod_before_copy() {
1494; CHECK-LABEL: define void @dest_alias_mod_before_copy() {
1495; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1496; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1497; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1498; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1499; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1500; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 1
1501; CHECK-NEXT:    store i32 13, ptr [[DEST_ALIAS]], align 4
1502; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1503; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1504; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1505; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1506; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1507; CHECK-NEXT:    ret void
1508;
1509  %src = alloca %struct.Foo, align 4
1510  %dest = alloca %struct.Foo, align 4
1511  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1512  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1513  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1514  %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 1
1515  store i32 13, ptr %dest.alias
1516  %1 = call i32 @use_nocapture(ptr nocapture %src)
1517
1518  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1519
1520  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1521  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1522  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1523  ret void
1524}
1525
1526; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks
1527define void @alias_src_ref_dest_mod_after_copy() {
1528; CHECK-LABEL: define void @alias_src_ref_dest_mod_after_copy() {
1529; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1530; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1531; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1532; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1533; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1534; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1535; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1536; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 1
1537; CHECK-NEXT:    store i32 13, ptr [[DEST_ALIAS]], align 4
1538; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1539; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1540; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1541; CHECK-NEXT:    ret void
1542;
1543  %src = alloca %struct.Foo, align 4
1544  %dest = alloca %struct.Foo, align 4
1545  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1546  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1547  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1548  %1 = call i32 @use_nocapture(ptr nocapture %src)
1549
1550  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1551
1552  %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 1
1553  store i32 13, ptr %dest.alias
1554  %2 = call i32 @use_nocapture(ptr nocapture %src)
1555  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1556  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1557  ret void
1558}
1559
1560; Tests that the optimization isn't performed when the source and destination
1561; have mod ref conflict on bb2.
1562define void @multi_bb_dataflow_conflict(i1 %b) {
1563; CHECK-LABEL: define void @multi_bb_dataflow_conflict
1564; CHECK-SAME: (i1 [[B:%.*]]) {
1565; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1566; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1567; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1568; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1569; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1570; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1571; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1572; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
1573; CHECK:       bb0:
1574; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1575; CHECK-NEXT:    br label [[BB2:%.*]]
1576; CHECK:       bb1:
1577; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
1578; CHECK-NEXT:    br label [[BB2]]
1579; CHECK:       bb2:
1580; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
1581; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1582; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1583; CHECK-NEXT:    ret void
1584;
1585  %src = alloca %struct.Foo, align 4
1586  %dest = alloca %struct.Foo, align 4
1587  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1588  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1589  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1590  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)
1591  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1592  br i1 %b, label %bb0, label %bb1
1593
1594bb0:
1595  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
1596  br label %bb2
1597
1598bb1:
1599  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1600  br label %bb2
1601
1602bb2:
1603  %4 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1604  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1605  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1606  ret void
1607}
1608
1609; Tests that failure because after copy mod could be before copy on loop.
1610define void @multi_bb_loop_dest_mod_before_copy(i32 %n) {
1611; CHECK-LABEL: define void @multi_bb_loop_dest_mod_before_copy
1612; CHECK-SAME: (i32 [[N:%.*]]) {
1613; CHECK-NEXT:  entry:
1614; CHECK-NEXT:    [[NLT1:%.*]] = icmp slt i32 [[N]], 1
1615; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
1616; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 8
1617; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1618; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]])
1619; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4
1620; CHECK-NEXT:    br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]]
1621; CHECK:       loop_body:
1622; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ]
1623; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DEST]], ptr align 8 [[SRC]], i64 12, i1 false)
1624; CHECK-NEXT:    [[NEW_I]] = add i32 [[I]], 1
1625; CHECK-NEXT:    store i32 [[NEW_I]], ptr [[DEST]], align 4
1626; CHECK-NEXT:    [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]]
1627; CHECK-NEXT:    br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]]
1628; CHECK:       loop_exit:
1629; CHECK-NEXT:    ret void
1630;
1631entry:
1632  %nlt1 = icmp slt i32 %n, 1
1633  %src = alloca %struct.Foo, align 8
1634  %dest = alloca %struct.Foo, align 8
1635  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1636  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest)
1637  store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src
1638  br i1 %nlt1, label %loop_exit, label %loop_body
1639
1640loop_body:
1641  %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ]
1642  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false)
1643  %new_i = add i32 %i, 1
1644  store i32 %new_i, ptr %dest
1645  %igtn = icmp sgt i32 %new_i, %n
1646  br i1 %igtn, label %loop_exit, label %loop_body
1647
1648loop_exit:
1649  ret void
1650}
1651
1652; Tests that failure because partial-sized lifetimes are counted as mod.
1653define void @partial_lifetime() {
1654; CHECK-LABEL: define void @partial_lifetime() {
1655; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4
1656; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4
1657; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]])
1658; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 3, ptr captures(none) [[DEST]])
1659; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4
1660; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])
1661; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)
1662; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 3, ptr captures(none) [[SRC]])
1663; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])
1664; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]])
1665; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]])
1666; CHECK-NEXT:    ret void
1667;
1668  %src = alloca %struct.Foo, align 4
1669  %dest = alloca %struct.Foo, align 4
1670  call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src)
1671  call void @llvm.lifetime.start.p0(i64 3, ptr nocapture %dest)
1672  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
1673  %1 = call i32 @use_nocapture(ptr nocapture %src)
1674
1675  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
1676
1677  call void @llvm.lifetime.end.p0(i64 3, ptr nocapture %src)
1678  %2 = call i32 @use_nocapture(ptr nocapture %dest)
1679  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src)
1680  call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest)
1681  ret void
1682}
1683
1684; Do not merge or crash if the different block user comes first.
1685define void @crash_store63851(i1 %b) {
1686; CHECK-LABEL: define void @crash_store63851
1687; CHECK-SAME: (i1 [[B:%.*]]) {
1688; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8
1689; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO]], align 8
1690; CHECK-NEXT:    store i32 0, ptr [[DEST]], align 4
1691; CHECK-NEXT:    br i1 [[B]], label [[THEN:%.*]], label [[ELSE:%.*]]
1692; CHECK:       then:
1693; CHECK-NEXT:    [[T:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1694; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[DEST]], ptr [[SRC]], i64 12, i1 false)
1695; CHECK-NEXT:    [[T3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])
1696; CHECK-NEXT:    [[T4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])
1697; CHECK-NEXT:    br label [[ELSE]]
1698; CHECK:       else:
1699; CHECK-NEXT:    ret void
1700;
1701  %dest = alloca %struct.Foo, align 8
1702  %src = alloca %struct.Foo, align 8
1703  store i32 0, ptr %dest, align 4
1704  br i1 %b, label %then, label %else
1705
1706then:                                             ; preds = %entry
1707  %t = call i32 @use_nocapture(ptr nocapture noundef %src)
1708  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 12, i1 false)
1709  %t3 = call i32 @use_nocapture(ptr nocapture noundef %src)
1710  %t4 = call i32 @use_nocapture(ptr nocapture noundef %dest)
1711  br label %else
1712
1713else:                                             ; preds = %then, %entry
1714  ret void
1715
1716  uselistorder ptr %dest, { 1, 2, 0 }
1717}
1718