Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / MemCpyOpt / stack-move.ll
blob6089c0a4d7cf5070eb13545513b536880d7e039a
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
4 %struct.Foo = type { i32, i32, i32 }
6 declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
7 declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
8 declare void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) noalias nocapture writeonly, ptr addrspace(1) noalias nocapture readonly, i64, i1 immarg)
9 declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
10 declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
12 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
13 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
14 declare void @llvm.lifetime.start.p1(i64, ptr addrspace(1) nocapture)
15 declare void @llvm.lifetime.end.p1(i64, ptr addrspace(1) nocapture)
16 declare void @llvm.lifetime.start.p2(i64, ptr addrspace(2) nocapture)
17 declare void @llvm.lifetime.end.p2(i64, ptr addrspace(2) nocapture)
19 declare i32 @use_nocapture(ptr nocapture)
20 declare i32 @use_maycapture(ptr noundef)
21 declare i32 @use_readonly(ptr readonly)
22 declare i32 @use_writeonly(ptr noundef) memory(write)
24 define 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 nocapture [[SRC]])
29 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
30 ; CHECK-NEXT:    ret void
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)
39   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
41   %2 = call i32 @use_nocapture(ptr nocapture %dest)
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
48 define 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
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
62   store i1 %src.val, ptr %dest, align 1
64   ret i32 0
67 define 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 nocapture [[SRC]])
72 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
73 ; CHECK-NEXT:    ret void
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)
82   call void @llvm.memmove.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
84   %2 = call i32 @use_nocapture(ptr nocapture %dest)
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
91 ; Tests that the optimization succeeds with a load/store pair.
92 define 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 nocapture [[SRC]])
97 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
98 ; CHECK-NEXT:    ret void
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)
107   %src.val = load i32, ptr %src
108   store i32 %src.val, ptr %dest
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
116 ; Test scalable vectors.
117 define 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 nocapture [[SRC]])
123 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
124 ; CHECK-NEXT:    ret void
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)
133   %src.val = load <vscale x 4 x i32>, ptr %src
134   store <vscale x 4 x i32> %src.val, ptr %dest
136   %2 = call i32 @use_nocapture(ptr nocapture %dest)
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
143 ; Tests that merging two allocas shouldn't be more poisonous, smaller aligned src is valid.
144 define 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 nocapture [[SRC]])
149 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
150 ; CHECK-NEXT:    ret void
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)
159   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
167 ; Tests that we correctly remove extra lifetime intrinsics when performing the
168 ; optimization.
169 define 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 nocapture [[SRC]])
174 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
175 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
176 ; CHECK-NEXT:    ret void
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)
185   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
198 ; Tests that we won't insert lifetime markers if they don't exist originally.
199 define 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 nocapture [[SRC]])
204 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
205 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
206 ; CHECK-NEXT:    ret void
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)
213   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
215   %2 = call i32 @use_nocapture(ptr nocapture %dest)
216   %3 = call i32 @use_nocapture(ptr nocapture %dest)
217   ret void
220 ; Tests that aliasing src or dest but no modification desn't prevent transformations.
221 define 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 nocapture [[SRC]])
227 ; CHECK-NEXT:    [[SRC_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0
228 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
229 ; CHECK-NEXT:    ret void
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)
239   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
248 ; Scope domain
249 !0 = !{!0}
250 ; Scope in that domain
251 !1 = !{!1, !0}
252 ; Scope list
253 !2 = !{!1}
255 !3 = !{!"Whatever"}
257 ; Tests that we remove scoped noalias metadata from a call.
258 define 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 nocapture [[SRC]]), !alias.scope !0
263 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
264 ; CHECK-NEXT:    ret void
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
273   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
281 ; Tests that we remove metadata on the merged alloca.
282 define 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 nocapture [[SRC]]), !alias.scope !0
287 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
288 ; CHECK-NEXT:    ret void
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
297   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
305 ; Tests that we remove scoped noalias metadata from a call.
306 ; And confirm that don't crash on noalias metadata on lifetime markers.
307 define 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 nocapture [[SRC]]), !alias.scope !0
312 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
313 ; CHECK-NEXT:    ret void
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
322   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
330 ; Tests that we can merge alloca if the dest and src has only refs except lifetime intrinsics.
331 define 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 nocapture [[SRC]])
336 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_readonly(ptr nocapture [[SRC]])
337 ; CHECK-NEXT:    ret void
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
345   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
354 ; Tests that we can merge alloca if the dest and src has only mods.
355 define 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 nocapture [[SRC]])
360 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_writeonly(ptr nocapture [[SRC]])
361 ; CHECK-NEXT:    ret void
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
369   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
378 define 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
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
395 ; For multi-bb patch, we will insert it for next immediate post dominator block.
396 define 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 nocapture [[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
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)
417   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
422 unw:
423   %lp = landingpad i32 cleanup
424   resume i32 0
425 suc:
426   ret void
429 define 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 nocapture [[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 nocapture [[SRC]])
440 ; CHECK-NEXT:    ret void
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
450 bb0:
451   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 4, i1 false)
452   br label %bb1
454 bb1:
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
461 define 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 nocapture [[SRC]])
467 ; CHECK-NEXT:    br label [[BB0:%.*]]
468 ; CHECK:       bb0:
469 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[SRC]])
470 ; CHECK-NEXT:    ret void
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)
479   %src.val = load i32, ptr %src
480   store i32 %src.val, ptr %dest
481   br label %bb0
483 bb0:
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
490 ; FIXME: merge allocas for bb-separated, but logically straight.
491 ; We might be handle those load/store MemCpyOpt totally
492 define 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 nocapture [[SRC]])
498 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[DEST]])
499 ; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
500 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[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 nocapture [[DEST]])
508 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[SRC]])
509 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[DEST]])
510 ; CHECK-NEXT:    ret void
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)
519   %src.val = load i32, ptr %src
520   br label %bb0
522 bb0:
523   store i32 %src.val, ptr %dest
524   br label %bb1
526 bb1:
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
533 define 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 nocapture noundef [[SRC]])
539 ; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]
540 ; CHECK:       bb0:
541 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
542 ; CHECK-NEXT:    br label [[BB2:%.*]]
543 ; CHECK:       bb1:
544 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
545 ; CHECK-NEXT:    br label [[BB2]]
546 ; CHECK:       bb2:
547 ; CHECK-NEXT:    ret void
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
558 bb0:
559   %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
560   br label %bb2
562 bb1:
563   %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
564   br label %bb2
566 bb2:
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
572 ; Test for BasicBlock and Instruction mixed dominator finding.
573 define 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 nocapture noundef [[SRC]])
586 ; CHECK-NEXT:    ret void
588   %src = alloca %struct.Foo, align 4
589   %dest = alloca %struct.Foo, align 4
590   br i1 %b, label %bb0, label %bb1
592 bb0:
593   store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
594   br label %bb2
596 bb1:
597   store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src
598   br label %bb2
600 bb2:
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)
605   ret void
609 ; Test for BasicBlock and Instruction mixed dominator finding.
610 define 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 nocapture [[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 nocapture noundef [[DEST]])
626 ; CHECK-NEXT:    ret void
627 ; CHECK:       unr:
628 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
629 ; CHECK-NEXT:    br label [[BB2]]
631   %src = alloca %struct.Foo, align 4
632   %dest = alloca %struct.Foo, align 4
633   br i1 %b, label %bb0, label %bb1
635 bb0:
636   store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src
637   br label %bb2
639 bb1:
640   store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src
641   br label %bb2
643 bb2:
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)
648   ret void
650 unr:
651   %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
652   br label %bb2
655 ; Test for BasicBlock and Instruction mixed post-dominator finding.
656 define 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 nocapture noundef [[SRC]])
664 ; CHECK-NEXT:    br label [[BB2:%.*]]
665 ; CHECK:       bb1:
666 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
667 ; CHECK-NEXT:    br label [[BB2]]
668 ; CHECK:       bb2:
669 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
670 ; CHECK-NEXT:    ret void
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
679 bb0:
680   %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
681   br label %bb2
683 bb1:
684   %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
685   br label %bb2
687 bb2:
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
692   uselistorder ptr %dest, {  2, 3, 0, 1, 4, 5 }
695 ; Test for inserting lifetime.end after the phi-node
696 define 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 nocapture noundef [[SRC]])
704 ; CHECK-NEXT:    br label [[BB2:%.*]]
705 ; CHECK:       bb1:
706 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[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
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
719 bb0:
720   %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)
721   br label %bb2
723 bb1:
724   %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
725   br label %bb2
727 bb2:
728   %i = phi i32 [ 42, %bb0 ], [ 41, %bb1 ]
729   ret void
733 ; Test for existing unreachable cycle
734 define 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 nocapture noundef [[SRC]])
740 ; CHECK-NEXT:    ret void
741 ; CHECK:       unr1:
742 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
743 ; CHECK-NEXT:    br label [[UNR2:%.*]]
744 ; CHECK:       unr2:
745 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
746 ; CHECK-NEXT:    br label [[UNR1:%.*]]
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
756 unr1:
757   %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)
758   br label %unr2
760 unr2:
761   %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
762   br label %unr1
766 define 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
783 entry:
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
792 loop_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
800 loop_exit:
801   ret void
804 define 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 nocapture noundef [[SRC]])
810 ; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[EXIT:%.*]]
811 ; CHECK:       exit:
812 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
813 ; CHECK-NEXT:    ret void
814 ; CHECK:       bb0:
815 ; CHECK-NEXT:    ret void
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
825 exit:
826   %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
827   ret void
829 bb0:
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
836 define 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 nocapture noundef [[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 nocapture noundef [[SRC]])
847 ; CHECK-NEXT:    br label [[BB2]]
848 ; CHECK:       bb2:
849 ; CHECK-NEXT:    ret void
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
859 bb0:
860   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
861   br label %bb2
863 bb1:
864   %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
865   br label %bb2
867 bb2:
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
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.
877 define 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 nocapture [[SRC]])
882 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[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 nocapture noundef [[SRC]])
889 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
890 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
891 ; CHECK-NEXT:    ret void
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
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.
911 define 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 nocapture [[SRC]])
916 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[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 nocapture noundef [[SRC]])
923 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
924 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
925 ; CHECK-NEXT:    ret void
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
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.
945 define 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 nocapture [[SRC]])
950 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nocapture [[DEST]])
951 ; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4
952 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[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 nocapture noundef [[DEST]])
956 ; CHECK-NEXT:    store i32 64, ptr [[SRC]], align 4
957 ; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[SRC]])
958 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[SRC]])
959 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nocapture [[DEST]])
960 ; CHECK-NEXT:    ret void
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
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.
980 define 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 nocapture [[SRC]])
986 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[SRC]])
993 ; CHECK-NEXT:    br label [[BB2:%.*]]
994 ; CHECK:       bb1:
995 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
996 ; CHECK-NEXT:    br label [[BB2]]
997 ; CHECK:       bb2:
998 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
999 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1000 ; CHECK-NEXT:    ret void
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
1011 bb0:
1012   %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
1013   br label %bb2
1015 bb1:
1016   %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1017   br label %bb2
1019 bb2:
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
1026 ; Optimization failures follow:
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.
1030 define 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 nocapture [[SRC]])
1035 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[DEST]])
1040 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1041 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1042 ; CHECK-NEXT:    ret void
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
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.
1059 define 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 nocapture [[SRC]])
1064 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[DEST]])
1070 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1071 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1072 ; CHECK-NEXT:    ret void
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
1088 ; Tests that dynamically-sized allocas are never merged.
1089 define 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 nocapture [[SRC]])
1095 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1100 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture [[SRC]])
1101 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture [[DEST]])
1102 ; CHECK-NEXT:    ret void
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)
1111   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1120 ; Tests that inalloca attributed allocas are never merged, to prevent stacksave/stackrestore handling.
1121 define 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 nocapture [[SRC]])
1126 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1131 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1132 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1133 ; CHECK-NEXT:    ret void
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)
1142   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1150 ; Tests that a memcpy with a dynamic size is never optimized.
1151 define 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 nocapture [[SRC]])
1157 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1162 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1163 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1164 ; CHECK-NEXT:    ret void
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)
1173   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 %size, i1 false)
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
1181 ; Tests that allocas with different sizes aren't merged together.
1182 define 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 nocapture [[SRC]])
1187 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1192 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 24, ptr nocapture [[SRC]])
1193 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1194 ; CHECK-NEXT:    ret void
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)
1203   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1211 ; Tests that allocas with mismatched address spaces aren't combined.
1212 define 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) nocapture [[SRC]])
1217 ; CHECK-NEXT:    call void @llvm.lifetime.start.p2(i64 12, ptr addrspace(2) nocapture [[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) nocapture [[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) nocapture [[SRC]])
1222 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr addrspace(2) nocapture [[DEST]])
1223 ; CHECK-NEXT:    call void @llvm.lifetime.end.p2(i64 12, ptr addrspace(2) nocapture [[DEST]])
1224 ; CHECK-NEXT:    ret void
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)
1233   call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 %dest, ptr addrspace(1) align 4 %src, i64 12, i1 false)
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
1241 ; Tests that volatile memcpys aren't removed.
1242 define 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 nocapture [[SRC]])
1247 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1252 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1253 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1254 ; CHECK-NEXT:    ret void
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)
1263   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 true)
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
1271 ; Tests that the optimization isn't performed when the destination is captured.
1272 define 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 nocapture [[SRC]])
1277 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[SRC]])
1283 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1284 ; CHECK-NEXT:    ret void
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
1292   %1 = call i32 @use_nocapture(ptr nocapture %src)
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
1301 ; Tests that the optimization isn't performed when the source is captured.
1302 define 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 nocapture [[SRC]])
1307 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[DEST]])
1312 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1313 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1314 ; CHECK-NEXT:    ret void
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)
1323   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
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.
1333 define 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 nocapture [[SRC]])
1338 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[DEST]])
1341 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr nocapture [[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 nocapture [[SRC]])
1344 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
1345 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1346 ; CHECK-NEXT:    ret void
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)
1356   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1364 ; Tests that failure because copy semantics will change if dest is replaced with src.
1365 define 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 nocapture [[SRC]])
1370 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[SRC]])
1376 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
1377 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1378 ; CHECK-NEXT:    ret void
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)
1388   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1396 define 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 nocapture [[SRC]])
1401 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[SRC]])
1408 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
1409 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1410 ; CHECK-NEXT:    ret void
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)
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
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
1430 ; Tests that the optimization isn't performed,
1431 ; when the source may have mod and dest may have ref after the full copy.
1432 define 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 nocapture [[SRC]])
1437 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[DEST]])
1442 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1443 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1444 ; CHECK-NEXT:    ret void
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
1452   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1461 ; Tests that the optimization isn't performed.
1462 ; Merging dest to src is no longer valid if conflicting Mod/Ref exist.
1463 define 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 nocapture [[SRC]])
1468 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[SRC]])
1473 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1474 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1475 ; CHECK-NEXT:    ret void
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
1483   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1492 ; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks
1493 define 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 nocapture [[SRC]])
1498 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[DEST]])
1505 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1506 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1507 ; CHECK-NEXT:    ret void
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)
1518   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1526 ; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks
1527 define 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 nocapture [[SRC]])
1532 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture [[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 nocapture [[SRC]])
1539 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1540 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1541 ; CHECK-NEXT:    ret void
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)
1550   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1560 ; Tests that the optimization isn't performed when the source and destination
1561 ; have mod ref conflict on bb2.
1562 define 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 nocapture [[SRC]])
1568 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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 nocapture noundef [[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 nocapture noundef [[SRC]])
1575 ; CHECK-NEXT:    br label [[BB2:%.*]]
1576 ; CHECK:       bb1:
1577 ; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
1578 ; CHECK-NEXT:    br label [[BB2]]
1579 ; CHECK:       bb2:
1580 ; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
1581 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1582 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1583 ; CHECK-NEXT:    ret void
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
1594 bb0:
1595   %2 = call i32 @use_nocapture(ptr noundef nocapture %src)
1596   br label %bb2
1598 bb1:
1599   %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)
1600   br label %bb2
1602 bb2:
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
1609 ; Tests that failure because after copy mod could be before copy on loop.
1610 define 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 nocapture [[SRC]])
1618 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr nocapture [[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
1631 entry:
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
1640 loop_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
1648 loop_exit:
1649   ret void
1652 ; Tests that failure because partial-sized lifetimes are counted as mod.
1653 define 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 nocapture [[SRC]])
1658 ; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 3, ptr nocapture [[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 nocapture [[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 nocapture [[SRC]])
1663 ; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr nocapture [[DEST]])
1664 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[SRC]])
1665 ; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr nocapture [[DEST]])
1666 ; CHECK-NEXT:    ret void
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)
1675   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)
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
1684 ; Do not merge or crash if the different block user comes first.
1685 define 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 nocapture noundef [[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 nocapture noundef [[SRC]])
1696 ; CHECK-NEXT:    [[T4:%.*]] = call i32 @use_nocapture(ptr nocapture noundef [[DEST]])
1697 ; CHECK-NEXT:    br label [[ELSE]]
1698 ; CHECK:       else:
1699 ; CHECK-NEXT:    ret void
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
1706 then:                                             ; 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
1713 else:                                             ; preds = %then, %entry
1714   ret void
1716   uselistorder ptr %dest, { 1, 2, 0 }