139321564Skhei4; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 290ecb9d5Skhei4; RUN: opt < %s -passes=memcpyopt -verify-memoryssa -S | FileCheck %s 339321564Skhei4 439321564Skhei4%struct.Foo = type { i32, i32, i32 } 539321564Skhei4 639321564Skhei4declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) 739321564Skhei4declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) 839321564Skhei4declare void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) noalias nocapture writeonly, ptr addrspace(1) noalias nocapture readonly, i64, i1 immarg) 939321564Skhei4declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg) 10e0911b98Skhei4declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) 1139321564Skhei4 1239321564Skhei4declare void @llvm.lifetime.start.p0(i64, ptr nocapture) 1339321564Skhei4declare void @llvm.lifetime.end.p0(i64, ptr nocapture) 1439321564Skhei4declare void @llvm.lifetime.start.p1(i64, ptr addrspace(1) nocapture) 1539321564Skhei4declare void @llvm.lifetime.end.p1(i64, ptr addrspace(1) nocapture) 1639321564Skhei4declare void @llvm.lifetime.start.p2(i64, ptr addrspace(2) nocapture) 1739321564Skhei4declare void @llvm.lifetime.end.p2(i64, ptr addrspace(2) nocapture) 1839321564Skhei4 1939321564Skhei4declare i32 @use_nocapture(ptr nocapture) 2039321564Skhei4declare i32 @use_maycapture(ptr noundef) 2139321564Skhei4declare i32 @use_readonly(ptr readonly) 2239321564Skhei4declare i32 @use_writeonly(ptr noundef) memory(write) 2339321564Skhei4 2439321564Skhei4define void @basic_memcpy() { 2539321564Skhei4; CHECK-LABEL: define void @basic_memcpy() { 2639321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 2739321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 28*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 29*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 3039321564Skhei4; CHECK-NEXT: ret void 3139321564Skhei4; 3239321564Skhei4 %src = alloca %struct.Foo, align 4 3339321564Skhei4 %dest = alloca %struct.Foo, align 4 3439321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 3539321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 3639321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 3739321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 3839321564Skhei4 3939321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 4039321564Skhei4 4139321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 4239321564Skhei4 4339321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 4439321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 4539321564Skhei4 ret void 4639321564Skhei4} 4739321564Skhei4 482a207128SKohei Asanodefine i32 @use_not_dominated_by_src_alloca() { 492a207128SKohei Asano; CHECK-LABEL: define i32 @use_not_dominated_by_src_alloca() { 502a207128SKohei Asano; CHECK-NEXT: [[SRC:%.*]] = alloca i8, align 4 512a207128SKohei Asano; CHECK-NEXT: [[DEST_GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 -1 522a207128SKohei Asano; CHECK-NEXT: [[DEST_USE:%.*]] = load i8, ptr [[DEST_GEP]], align 1 532a207128SKohei Asano; CHECK-NEXT: ret i32 0 542a207128SKohei Asano; 552a207128SKohei Asano %dest = alloca i1, align 1 562a207128SKohei Asano ; Replacing the use of dest with src causes no domination uses. 572a207128SKohei Asano %dest.gep = getelementptr i64, ptr %dest, i64 -1 582a207128SKohei Asano %dest.use = load i8, ptr %dest.gep, align 1 592a207128SKohei Asano %src = alloca i8, align 4 602a207128SKohei Asano %src.val = load i1, ptr %src, align 4 612a207128SKohei Asano 622a207128SKohei Asano store i1 %src.val, ptr %dest, align 1 632a207128SKohei Asano 642a207128SKohei Asano ret i32 0 652a207128SKohei Asano} 662a207128SKohei Asano 6739321564Skhei4define void @basic_memmove() { 6839321564Skhei4; CHECK-LABEL: define void @basic_memmove() { 6939321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 7039321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 71*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 72*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 7339321564Skhei4; CHECK-NEXT: ret void 7439321564Skhei4; 7539321564Skhei4 %src = alloca %struct.Foo, align 4 7639321564Skhei4 %dest = alloca %struct.Foo, align 4 7739321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 7839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 7939321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 8039321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 8139321564Skhei4 8239321564Skhei4 call void @llvm.memmove.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 8339321564Skhei4 8439321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 8539321564Skhei4 8639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 8739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 8839321564Skhei4 ret void 8939321564Skhei4} 9039321564Skhei4 9139321564Skhei4; Tests that the optimization succeeds with a load/store pair. 9239321564Skhei4define void @load_store() { 9339321564Skhei4; CHECK-LABEL: define void @load_store() { 9439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i32, align 4 9539321564Skhei4; CHECK-NEXT: store i32 42, ptr [[SRC]], align 4 96*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 97*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 9839321564Skhei4; CHECK-NEXT: ret void 9939321564Skhei4; 10039321564Skhei4 %src = alloca i32, align 4 10139321564Skhei4 %dest = alloca i32, align 4 10239321564Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src) 10339321564Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest) 10439321564Skhei4 store i32 42, ptr %src 10539321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 10639321564Skhei4 10739321564Skhei4 %src.val = load i32, ptr %src 10839321564Skhei4 store i32 %src.val, ptr %dest 10939321564Skhei4 11039321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 11139321564Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src) 11239321564Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest) 11339321564Skhei4 ret void 11439321564Skhei4} 11539321564Skhei4 116689ace53SCraig Topper; Test scalable vectors. 117689ace53SCraig Topperdefine void @load_store_scalable(<vscale x 4 x i32> %x) { 118689ace53SCraig Topper; CHECK-LABEL: define void @load_store_scalable 119689ace53SCraig Topper; CHECK-SAME: (<vscale x 4 x i32> [[X:%.*]]) { 120689ace53SCraig Topper; CHECK-NEXT: [[SRC:%.*]] = alloca <vscale x 4 x i32>, align 16 121689ace53SCraig Topper; CHECK-NEXT: store <vscale x 4 x i32> [[X]], ptr [[SRC]], align 16 122*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 123*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 124689ace53SCraig Topper; CHECK-NEXT: ret void 125689ace53SCraig Topper; 126689ace53SCraig Topper %src = alloca <vscale x 4 x i32> 127689ace53SCraig Topper %dest = alloca <vscale x 4 x i32> 128689ace53SCraig Topper call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %src) 129689ace53SCraig Topper call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %dest) 130689ace53SCraig Topper store <vscale x 4 x i32> %x, ptr %src 131689ace53SCraig Topper %1 = call i32 @use_nocapture(ptr nocapture %src) 132689ace53SCraig Topper 133689ace53SCraig Topper %src.val = load <vscale x 4 x i32>, ptr %src 134689ace53SCraig Topper store <vscale x 4 x i32> %src.val, ptr %dest 135689ace53SCraig Topper 136689ace53SCraig Topper %2 = call i32 @use_nocapture(ptr nocapture %dest) 137689ace53SCraig Topper 138689ace53SCraig Topper call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %src) 139689ace53SCraig Topper call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %dest) 140689ace53SCraig Topper ret void 141689ace53SCraig Topper} 142689ace53SCraig Topper 14339321564Skhei4; Tests that merging two allocas shouldn't be more poisonous, smaller aligned src is valid. 14439321564Skhei4define void @align_up() { 14539321564Skhei4; CHECK-LABEL: define void @align_up() { 146ca68a7f9Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 14739321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 148*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 149*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 15039321564Skhei4; CHECK-NEXT: ret void 15139321564Skhei4; 15239321564Skhei4 %src = alloca %struct.Foo, align 4 15339321564Skhei4 %dest = alloca %struct.Foo, align 8 15439321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 15539321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 15639321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 15739321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 15839321564Skhei4 15939321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 16039321564Skhei4 16139321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 16239321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 16339321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 16439321564Skhei4 ret void 16539321564Skhei4} 16639321564Skhei4 16739321564Skhei4; Tests that we correctly remove extra lifetime intrinsics when performing the 16839321564Skhei4; optimization. 16939321564Skhei4define void @remove_extra_lifetime_intrinsics() { 17039321564Skhei4; CHECK-LABEL: define void @remove_extra_lifetime_intrinsics() { 17139321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 17239321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 173*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 174*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 175*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 17639321564Skhei4; CHECK-NEXT: ret void 17739321564Skhei4; 17839321564Skhei4 %src = alloca %struct.Foo, align 4 17939321564Skhei4 %dest = alloca %struct.Foo, align 4 18039321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 18139321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 18239321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 18339321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 18439321564Skhei4 18539321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 18639321564Skhei4 18739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 18839321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 18939321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 19039321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 19139321564Skhei4 %3 = call i32 @use_nocapture(ptr nocapture %dest) 19239321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 19339321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 19439321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 19539321564Skhei4 ret void 19639321564Skhei4} 19739321564Skhei4 19839321564Skhei4; Tests that we won't insert lifetime markers if they don't exist originally. 19939321564Skhei4define void @no_lifetime() { 20039321564Skhei4; CHECK-LABEL: define void @no_lifetime() { 20139321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 20239321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 203*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 204*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 205*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 20639321564Skhei4; CHECK-NEXT: ret void 20739321564Skhei4; 20839321564Skhei4 %src = alloca %struct.Foo, align 4 20939321564Skhei4 %dest = alloca %struct.Foo, align 4 21039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 21139321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 21239321564Skhei4 21339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 21439321564Skhei4 21539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 21639321564Skhei4 %3 = call i32 @use_nocapture(ptr nocapture %dest) 21739321564Skhei4 ret void 21839321564Skhei4} 21939321564Skhei4 22039321564Skhei4; Tests that aliasing src or dest but no modification desn't prevent transformations. 22139321564Skhei4define void @alias_no_mod() { 22239321564Skhei4; CHECK-LABEL: define void @alias_no_mod() { 22339321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 224ca68a7f9Skhei4; CHECK-NEXT: [[DEST_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0 22539321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 226*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 22739321564Skhei4; CHECK-NEXT: [[SRC_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0 228*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 22939321564Skhei4; CHECK-NEXT: ret void 23039321564Skhei4; 23139321564Skhei4 %src = alloca %struct.Foo, align 4 23239321564Skhei4 %dest = alloca %struct.Foo, align 4 23339321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 23439321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 23539321564Skhei4 %dest.alias = getelementptr %struct.Foo, ptr %dest, i32 0, i32 0 23639321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 23739321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 23839321564Skhei4 23939321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 24039321564Skhei4 24139321564Skhei4 %src.alias = getelementptr %struct.Foo, ptr %src, i32 0, i32 0 24239321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 24339321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 24439321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 24539321564Skhei4 ret void 24639321564Skhei4} 24739321564Skhei4 24839321564Skhei4; Scope domain 24939321564Skhei4!0 = !{!0} 25039321564Skhei4; Scope in that domain 25139321564Skhei4!1 = !{!1, !0} 25239321564Skhei4; Scope list 25339321564Skhei4!2 = !{!1} 25439321564Skhei4 25539321564Skhei4!3 = !{!"Whatever"} 25639321564Skhei4 25739321564Skhei4; Tests that we remove scoped noalias metadata from a call. 25839321564Skhei4define void @remove_scoped_noalias() { 25939321564Skhei4; CHECK-LABEL: define void @remove_scoped_noalias() { 26039321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 26139321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 262*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0:![0-9]+]] 263*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 26439321564Skhei4; CHECK-NEXT: ret void 26539321564Skhei4; 26639321564Skhei4 %src = alloca %struct.Foo, align 4 26739321564Skhei4 %dest = alloca %struct.Foo, align 4 26839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 26939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 27039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 27139321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2 27239321564Skhei4 27339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 27439321564Skhei4 27539321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 27639321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2 27739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 27839321564Skhei4 ret void 27939321564Skhei4} 28039321564Skhei4 28139321564Skhei4; Tests that we remove metadata on the merged alloca. 28239321564Skhei4define void @remove_alloca_metadata() { 28339321564Skhei4; CHECK-LABEL: define void @remove_alloca_metadata() { 284ca68a7f9Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 28539321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 286*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0]] 287*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 28839321564Skhei4; CHECK-NEXT: ret void 28939321564Skhei4; 29039321564Skhei4 %src = alloca %struct.Foo, align 4, !annotation !3 29139321564Skhei4 %dest = alloca %struct.Foo, align 4 29239321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 29339321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 29439321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 29539321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2 29639321564Skhei4 29739321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 29839321564Skhei4 29939321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2 30039321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 30139321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 30239321564Skhei4 ret void 30339321564Skhei4} 30439321564Skhei4 305d878916cSkhei4; Tests that we remove scoped noalias metadata from a call. 306d878916cSkhei4; And confirm that don't crash on noalias metadata on lifetime markers. 307d878916cSkhei4define void @noalias_on_lifetime() { 308d878916cSkhei4; CHECK-LABEL: define void @noalias_on_lifetime() { 309d878916cSkhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 310d878916cSkhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 311*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]), !alias.scope [[META0]] 312*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 313d878916cSkhei4; CHECK-NEXT: ret void 314d878916cSkhei4; 315d878916cSkhei4 %src = alloca %struct.Foo, align 4 316d878916cSkhei4 %dest = alloca %struct.Foo, align 4 317d878916cSkhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 318d878916cSkhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 319d878916cSkhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 320d878916cSkhei4 %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2 321d878916cSkhei4 322d878916cSkhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 323d878916cSkhei4 324d878916cSkhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src), !alias.scope !2 325d878916cSkhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2 326d878916cSkhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest), !noalias !2 327d878916cSkhei4 ret void 328d878916cSkhei4} 329d878916cSkhei4 33039321564Skhei4; Tests that we can merge alloca if the dest and src has only refs except lifetime intrinsics. 33139321564Skhei4define void @src_ref_dest_ref_after_copy() { 33239321564Skhei4; CHECK-LABEL: define void @src_ref_dest_ref_after_copy() { 33339321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 33439321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 335*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]]) 336*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]]) 33739321564Skhei4; CHECK-NEXT: ret void 33839321564Skhei4; 33939321564Skhei4 %src = alloca %struct.Foo, align 4 34039321564Skhei4 %dest = alloca %struct.Foo, align 4 34139321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 34239321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 34339321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 34439321564Skhei4 34539321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 34639321564Skhei4 34739321564Skhei4 %1 = call i32 @use_readonly(ptr nocapture %src) 34839321564Skhei4 %2 = call i32 @use_readonly(ptr nocapture %dest) 34939321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 35039321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 35139321564Skhei4 ret void 35239321564Skhei4} 35339321564Skhei4 35439321564Skhei4; Tests that we can merge alloca if the dest and src has only mods. 35539321564Skhei4define void @src_mod_dest_mod_after_copy() { 35639321564Skhei4; CHECK-LABEL: define void @src_mod_dest_mod_after_copy() { 35739321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 35839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 359*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]]) 360*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]]) 36139321564Skhei4; CHECK-NEXT: ret void 36239321564Skhei4; 36339321564Skhei4 %src = alloca %struct.Foo, align 4 36439321564Skhei4 %dest = alloca %struct.Foo, align 4 36539321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 36639321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 36739321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 36839321564Skhei4 36939321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 37039321564Skhei4 37139321564Skhei4 %1 = call i32 @use_writeonly(ptr nocapture %src) 37239321564Skhei4 %2 = call i32 @use_writeonly(ptr nocapture %dest) 37339321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 37439321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 37539321564Skhei4 ret void 37639321564Skhei4} 37739321564Skhei4 3780b4f8c9fSkhei4define void @avoid_memory_use_last_user_crash() { 3790b4f8c9fSkhei4; CHECK-LABEL: define void @avoid_memory_use_last_user_crash() { 3800b4f8c9fSkhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 3810b4f8c9fSkhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 382ca68a7f9Skhei4; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[SRC]], align 4 3830b4f8c9fSkhei4; CHECK-NEXT: ret void 3840b4f8c9fSkhei4; 3850b4f8c9fSkhei4 %src = alloca %struct.Foo, align 4 3860b4f8c9fSkhei4 %dest = alloca %struct.Foo, align 4 3870b4f8c9fSkhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 3880b4f8c9fSkhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 3890b4f8c9fSkhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 3900b4f8c9fSkhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 3910b4f8c9fSkhei4 %v = load i32, ptr %dest 3920b4f8c9fSkhei4 ret void 3930b4f8c9fSkhei4} 3940b4f8c9fSkhei4 395bdc9a6b1Skhei4; For multi-bb patch, we will insert it for next immediate post dominator block. 396bdc9a6b1Skhei4define void @terminator_lastuse() personality i32 0 { 397bdc9a6b1Skhei4; CHECK-LABEL: define void @terminator_lastuse() personality i32 0 { 398bdc9a6b1Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 399bdc9a6b1Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 400*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 401ca68a7f9Skhei4; CHECK-NEXT: [[RV:%.*]] = invoke i32 @use_nocapture(ptr [[SRC]]) 402bdc9a6b1Skhei4; CHECK-NEXT: to label [[SUC:%.*]] unwind label [[UNW:%.*]] 403bdc9a6b1Skhei4; CHECK: unw: 404bdc9a6b1Skhei4; CHECK-NEXT: [[LP:%.*]] = landingpad i32 405bdc9a6b1Skhei4; CHECK-NEXT: cleanup 406bdc9a6b1Skhei4; CHECK-NEXT: resume i32 0 407bdc9a6b1Skhei4; CHECK: suc: 408bdc9a6b1Skhei4; CHECK-NEXT: ret void 409bdc9a6b1Skhei4; 410bdc9a6b1Skhei4 %src = alloca %struct.Foo, align 4 411bdc9a6b1Skhei4 %dest = alloca %struct.Foo, align 4 412bdc9a6b1Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 413bdc9a6b1Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 414bdc9a6b1Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 415bdc9a6b1Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 416bdc9a6b1Skhei4 417bdc9a6b1Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 418bdc9a6b1Skhei4 419bdc9a6b1Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr %src) 420bdc9a6b1Skhei4 %rv = invoke i32 @use_nocapture(ptr %dest) 421bdc9a6b1Skhei4 to label %suc unwind label %unw 422bdc9a6b1Skhei4unw: 423bdc9a6b1Skhei4 %lp = landingpad i32 cleanup 424bdc9a6b1Skhei4 resume i32 0 425bdc9a6b1Skhei4suc: 426bdc9a6b1Skhei4 ret void 427bdc9a6b1Skhei4} 428bdc9a6b1Skhei4 429a92e1971Skhei4define void @multi_bb_memcpy(i1 %b) { 430a92e1971Skhei4; CHECK-LABEL: define void @multi_bb_memcpy 431a92e1971Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 432a92e1971Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i32, align 4 433a92e1971Skhei4; CHECK-NEXT: store i32 42, ptr [[SRC]], align 4 434*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 435a92e1971Skhei4; CHECK-NEXT: br label [[BB0:%.*]] 436a92e1971Skhei4; CHECK: bb0: 437a92e1971Skhei4; CHECK-NEXT: br label [[BB1:%.*]] 438a92e1971Skhei4; CHECK: bb1: 439*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 440a92e1971Skhei4; CHECK-NEXT: ret void 441a92e1971Skhei4; 442a92e1971Skhei4 %src = alloca i32, align 4 443a92e1971Skhei4 %dest = alloca i32, align 4 444a92e1971Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src) 445a92e1971Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest) 446a92e1971Skhei4 store i32 42, ptr %src 447a92e1971Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 448a92e1971Skhei4 br label %bb0 449a92e1971Skhei4 450a92e1971Skhei4bb0: 451a92e1971Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 4, i1 false) 452a92e1971Skhei4 br label %bb1 453a92e1971Skhei4 454a92e1971Skhei4bb1: 455a92e1971Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 456a92e1971Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src) 457a92e1971Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest) 458a92e1971Skhei4 ret void 459a92e1971Skhei4} 460a92e1971Skhei4 461a92e1971Skhei4define void @multi_bb_load_store(i1 %b) { 462a92e1971Skhei4; CHECK-LABEL: define void @multi_bb_load_store 463a92e1971Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 464a92e1971Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i32, align 4 465a92e1971Skhei4; CHECK-NEXT: store i32 42, ptr [[SRC]], align 4 466*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 467e0911b98Skhei4; CHECK-NEXT: br label [[BB0:%.*]] 468e0911b98Skhei4; CHECK: bb0: 469*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 470e0911b98Skhei4; CHECK-NEXT: ret void 471e0911b98Skhei4; 472e0911b98Skhei4 %src = alloca i32, align 4 473e0911b98Skhei4 %dest = alloca i32, align 4 474e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src) 475e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest) 476e0911b98Skhei4 store i32 42, ptr %src 477e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 478e0911b98Skhei4 479e0911b98Skhei4 %src.val = load i32, ptr %src 480e0911b98Skhei4 store i32 %src.val, ptr %dest 481e0911b98Skhei4 br label %bb0 482e0911b98Skhei4 483e0911b98Skhei4bb0: 484e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 485e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src) 486e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest) 487e0911b98Skhei4 ret void 488e0911b98Skhei4} 489e0911b98Skhei4 490e0911b98Skhei4; FIXME: merge allocas for bb-separated, but logically straight. 491e0911b98Skhei4; We might be handle those load/store MemCpyOpt totally 492e0911b98Skhei4define void @multi_bb_separated_load_store(i1 %b) { 493e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_separated_load_store 494e0911b98Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 495e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i32, align 4 496e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca i32, align 4 497*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[SRC]]) 498*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[DEST]]) 499e0911b98Skhei4; CHECK-NEXT: store i32 42, ptr [[SRC]], align 4 500*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 501e0911b98Skhei4; CHECK-NEXT: [[SRC_VAL:%.*]] = load i32, ptr [[SRC]], align 4 502a92e1971Skhei4; CHECK-NEXT: br label [[BB0:%.*]] 503a92e1971Skhei4; CHECK: bb0: 504a92e1971Skhei4; CHECK-NEXT: store i32 [[SRC_VAL]], ptr [[DEST]], align 4 505a92e1971Skhei4; CHECK-NEXT: br label [[BB1:%.*]] 506a92e1971Skhei4; CHECK: bb1: 507*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 508*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[SRC]]) 509*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[DEST]]) 510a92e1971Skhei4; CHECK-NEXT: ret void 511a92e1971Skhei4; 512a92e1971Skhei4 %src = alloca i32, align 4 513a92e1971Skhei4 %dest = alloca i32, align 4 514a92e1971Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src) 515a92e1971Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest) 516a92e1971Skhei4 store i32 42, ptr %src 517a92e1971Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 518a92e1971Skhei4 519a92e1971Skhei4 %src.val = load i32, ptr %src 520a92e1971Skhei4 br label %bb0 521a92e1971Skhei4 522a92e1971Skhei4bb0: 523a92e1971Skhei4 store i32 %src.val, ptr %dest 524a92e1971Skhei4 br label %bb1 525a92e1971Skhei4 526a92e1971Skhei4bb1: 527a92e1971Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 528a92e1971Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src) 529a92e1971Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest) 530a92e1971Skhei4 ret void 531a92e1971Skhei4} 532a92e1971Skhei4 533a92e1971Skhei4define void @multi_bb_simple_br(i1 %b) { 534a92e1971Skhei4; CHECK-LABEL: define void @multi_bb_simple_br 53539321564Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 53639321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 53739321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 538*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 53939321564Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 54039321564Skhei4; CHECK: bb0: 541*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 54239321564Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 54339321564Skhei4; CHECK: bb1: 544*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 54539321564Skhei4; CHECK-NEXT: br label [[BB2]] 54639321564Skhei4; CHECK: bb2: 54739321564Skhei4; CHECK-NEXT: ret void 54839321564Skhei4; 54939321564Skhei4 %src = alloca %struct.Foo, align 4 55039321564Skhei4 %dest = alloca %struct.Foo, align 4 55139321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 55239321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 55339321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 55439321564Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 55539321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 55639321564Skhei4 br i1 %b, label %bb0, label %bb1 55739321564Skhei4 55839321564Skhei4bb0: 55939321564Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 56039321564Skhei4 br label %bb2 56139321564Skhei4 56239321564Skhei4bb1: 56339321564Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 56439321564Skhei4 br label %bb2 56539321564Skhei4 56639321564Skhei4bb2: 56739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 56839321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 56939321564Skhei4 ret void 57039321564Skhei4} 57139321564Skhei4 572fe285ae0Skhei4; Test for BasicBlock and Instruction mixed dominator finding. 573fe285ae0Skhei4define void @multi_bb_dom_test0(i1 %b) { 574fe285ae0Skhei4; CHECK-LABEL: define void @multi_bb_dom_test0 575fe285ae0Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 576fe285ae0Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 577fe285ae0Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 578fe285ae0Skhei4; CHECK: bb0: 579fe285ae0Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 580fe285ae0Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 581fe285ae0Skhei4; CHECK: bb1: 582fe285ae0Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4 583fe285ae0Skhei4; CHECK-NEXT: br label [[BB2]] 584fe285ae0Skhei4; CHECK: bb2: 585*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 586fe285ae0Skhei4; CHECK-NEXT: ret void 587fe285ae0Skhei4; 588fe285ae0Skhei4 %src = alloca %struct.Foo, align 4 589fe285ae0Skhei4 %dest = alloca %struct.Foo, align 4 590fe285ae0Skhei4 br i1 %b, label %bb0, label %bb1 591fe285ae0Skhei4 592fe285ae0Skhei4bb0: 593fe285ae0Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 594fe285ae0Skhei4 br label %bb2 595fe285ae0Skhei4 596fe285ae0Skhei4bb1: 597fe285ae0Skhei4 store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src 598fe285ae0Skhei4 br label %bb2 599fe285ae0Skhei4 600fe285ae0Skhei4bb2: 601fe285ae0Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 602c652987dSkhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 603fe285ae0Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %dest) 604fe285ae0Skhei4 605fe285ae0Skhei4 ret void 606fe285ae0Skhei4 607fe285ae0Skhei4} 608fe285ae0Skhei4 60998d1b0ebSkhei4; Test for BasicBlock and Instruction mixed dominator finding. 61098d1b0ebSkhei4define void @multi_bb_dom_test1(i1 %b) { 61198d1b0ebSkhei4; CHECK-LABEL: define void @multi_bb_dom_test1 61298d1b0ebSkhei4; CHECK-SAME: (i1 [[B:%.*]]) { 61398d1b0ebSkhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 61498d1b0ebSkhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 61598d1b0ebSkhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 61698d1b0ebSkhei4; CHECK: bb0: 61798d1b0ebSkhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 61898d1b0ebSkhei4; CHECK-NEXT: br label [[BB2:%.*]] 61998d1b0ebSkhei4; CHECK: bb1: 62098d1b0ebSkhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4 62198d1b0ebSkhei4; CHECK-NEXT: br label [[BB2]] 62298d1b0ebSkhei4; CHECK: bb2: 623*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 62498d1b0ebSkhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 625*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 62698d1b0ebSkhei4; CHECK-NEXT: ret void 62798d1b0ebSkhei4; CHECK: unr: 628*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 62998d1b0ebSkhei4; CHECK-NEXT: br label [[BB2]] 63098d1b0ebSkhei4; 63198d1b0ebSkhei4 %src = alloca %struct.Foo, align 4 63298d1b0ebSkhei4 %dest = alloca %struct.Foo, align 4 63398d1b0ebSkhei4 br i1 %b, label %bb0, label %bb1 63498d1b0ebSkhei4 63598d1b0ebSkhei4bb0: 63698d1b0ebSkhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 63798d1b0ebSkhei4 br label %bb2 63898d1b0ebSkhei4 63998d1b0ebSkhei4bb1: 64098d1b0ebSkhei4 store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src 64198d1b0ebSkhei4 br label %bb2 64298d1b0ebSkhei4 64398d1b0ebSkhei4bb2: 64498d1b0ebSkhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 64598d1b0ebSkhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1 64698d1b0ebSkhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %dest) 64798d1b0ebSkhei4 64898d1b0ebSkhei4 ret void 64998d1b0ebSkhei4 65098d1b0ebSkhei4unr: 65198d1b0ebSkhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 65298d1b0ebSkhei4 br label %bb2 65398d1b0ebSkhei4} 65498d1b0ebSkhei4 655e0911b98Skhei4; Test for BasicBlock and Instruction mixed post-dominator finding. 656e0911b98Skhei4define void @multi_bb_pdom_test0(i1 %b) { 657e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_pdom_test0 658e0911b98Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 659e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 660e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 661e0911b98Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 662e0911b98Skhei4; CHECK: bb0: 663*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 664e0911b98Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 665e0911b98Skhei4; CHECK: bb1: 666*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 667e0911b98Skhei4; CHECK-NEXT: br label [[BB2]] 668e0911b98Skhei4; CHECK: bb2: 669*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 670e0911b98Skhei4; CHECK-NEXT: ret void 671e0911b98Skhei4; 672e0911b98Skhei4 %src = alloca %struct.Foo, align 4 673e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 674e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 675e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 676e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1 677e0911b98Skhei4 br i1 %b, label %bb0, label %bb1 678e0911b98Skhei4 679e0911b98Skhei4bb0: 680e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %dest) 681e0911b98Skhei4 br label %bb2 682e0911b98Skhei4 683e0911b98Skhei4bb1: 684e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 685e0911b98Skhei4 br label %bb2 686e0911b98Skhei4 687e0911b98Skhei4bb2: 688e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 689e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 690e0911b98Skhei4 ret void 691e0911b98Skhei4 692e0911b98Skhei4 uselistorder ptr %dest, { 2, 3, 0, 1, 4, 5 } 693e0911b98Skhei4} 694e0911b98Skhei4 695e0911b98Skhei4; Test for inserting lifetime.end after the phi-node 696e0911b98Skhei4define void @multi_bb_pdom_test1(i1 %b) { 697e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_pdom_test1 698e0911b98Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 699e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 700e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 701e0911b98Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 702e0911b98Skhei4; CHECK: bb0: 703*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 704e0911b98Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 705e0911b98Skhei4; CHECK: bb1: 706*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 707e0911b98Skhei4; CHECK-NEXT: br label [[BB2]] 708e0911b98Skhei4; CHECK: bb2: 709e0911b98Skhei4; CHECK-NEXT: [[I:%.*]] = phi i32 [ 42, [[BB0]] ], [ 41, [[BB1]] ] 710e0911b98Skhei4; CHECK-NEXT: ret void 711e0911b98Skhei4; 712e0911b98Skhei4 %src = alloca %struct.Foo, align 4 713e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 714e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 715e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 716e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1 717e0911b98Skhei4 br i1 %b, label %bb0, label %bb1 718e0911b98Skhei4 719e0911b98Skhei4bb0: 720e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %dest) 721e0911b98Skhei4 br label %bb2 722e0911b98Skhei4 723e0911b98Skhei4bb1: 724e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 725e0911b98Skhei4 br label %bb2 726e0911b98Skhei4 727e0911b98Skhei4bb2: 728e0911b98Skhei4 %i = phi i32 [ 42, %bb0 ], [ 41, %bb1 ] 729e0911b98Skhei4 ret void 730e0911b98Skhei4 731e0911b98Skhei4} 732e0911b98Skhei4 7335a9a7f53Skhei4; Test for existing unreachable cycle 7345a9a7f53Skhei4define void @multi_bb_pdom_test2(i1 %b) { 7355a9a7f53Skhei4; CHECK-LABEL: define void @multi_bb_pdom_test2 7365a9a7f53Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 7375a9a7f53Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 7385a9a7f53Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 739*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 7405a9a7f53Skhei4; CHECK-NEXT: ret void 7415a9a7f53Skhei4; CHECK: unr1: 742*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 7435a9a7f53Skhei4; CHECK-NEXT: br label [[UNR2:%.*]] 7445a9a7f53Skhei4; CHECK: unr2: 745*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 7465a9a7f53Skhei4; CHECK-NEXT: br label [[UNR1:%.*]] 7475a9a7f53Skhei4; 7485a9a7f53Skhei4 %src = alloca %struct.Foo, align 4 7495a9a7f53Skhei4 %dest = alloca %struct.Foo, align 4 7505a9a7f53Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 7515a9a7f53Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 7525a9a7f53Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1 7535a9a7f53Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %dest) 7545a9a7f53Skhei4 ret void 7555a9a7f53Skhei4 7565a9a7f53Skhei4unr1: 7575a9a7f53Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 7585a9a7f53Skhei4 br label %unr2 7595a9a7f53Skhei4 7605a9a7f53Skhei4unr2: 7615a9a7f53Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 7625a9a7f53Skhei4 br label %unr1 7635a9a7f53Skhei4 7645a9a7f53Skhei4} 7655a9a7f53Skhei4 766e0911b98Skhei4define void @multi_bb_loop(i32 %n) { 767e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_loop 76839321564Skhei4; CHECK-SAME: (i32 [[N:%.*]]) { 76939321564Skhei4; CHECK-NEXT: entry: 77039321564Skhei4; CHECK-NEXT: [[NLT1:%.*]] = icmp slt i32 [[N]], 1 77139321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 77239321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4 77339321564Skhei4; CHECK-NEXT: br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]] 77439321564Skhei4; CHECK: loop_body: 77539321564Skhei4; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ] 77639321564Skhei4; CHECK-NEXT: [[NEW_I]] = add i32 [[I]], 1 777e0911b98Skhei4; CHECK-NEXT: store i32 [[NEW_I]], ptr [[SRC]], align 4 77839321564Skhei4; CHECK-NEXT: [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]] 77939321564Skhei4; CHECK-NEXT: br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]] 78039321564Skhei4; CHECK: loop_exit: 781e0911b98Skhei4; CHECK-NEXT: ret void 78239321564Skhei4; 78339321564Skhei4entry: 78439321564Skhei4 %nlt1 = icmp slt i32 %n, 1 78539321564Skhei4 %src = alloca %struct.Foo, align 8 78639321564Skhei4 %dest = alloca %struct.Foo, align 8 78739321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 78839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 78939321564Skhei4 store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src 79039321564Skhei4 br i1 %nlt1, label %loop_exit, label %loop_body 79139321564Skhei4 79239321564Skhei4loop_body: 79339321564Skhei4 %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ] 79439321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false) 79539321564Skhei4 %new_i = add i32 %i, 1 796e0911b98Skhei4 store i32 %new_i, ptr %src 79739321564Skhei4 %igtn = icmp sgt i32 %new_i, %n 79839321564Skhei4 br i1 %igtn, label %loop_exit, label %loop_body 79939321564Skhei4 80039321564Skhei4loop_exit: 801e0911b98Skhei4 ret void 802e0911b98Skhei4} 803e0911b98Skhei4 804e0911b98Skhei4define void @multi_bb_unreachable_modref(i1 %b0) { 805e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_unreachable_modref 806e0911b98Skhei4; CHECK-SAME: (i1 [[B0:%.*]]) { 807e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 808e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 809*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 810e0911b98Skhei4; CHECK-NEXT: br i1 [[B0]], label [[BB0:%.*]], label [[EXIT:%.*]] 811e0911b98Skhei4; CHECK: exit: 812*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 813e0911b98Skhei4; CHECK-NEXT: ret void 814e0911b98Skhei4; CHECK: bb0: 815e0911b98Skhei4; CHECK-NEXT: ret void 816e0911b98Skhei4; 817e0911b98Skhei4 %src = alloca %struct.Foo, align 4 818e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 819e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 820e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 821e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 822e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 823e0911b98Skhei4 br i1 %b0, label %bb0, label %exit 824e0911b98Skhei4 825e0911b98Skhei4exit: 826e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %src) 827e0911b98Skhei4 ret void 828e0911b98Skhei4 829e0911b98Skhei4bb0: 830e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 831e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 832e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 833e0911b98Skhei4 ret void 834e0911b98Skhei4} 835e0911b98Skhei4 836e0911b98Skhei4define void @multi_bb_non_dominated(i1 %b0, i1 %b1) { 837e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_non_dominated 838e0911b98Skhei4; CHECK-SAME: (i1 [[B0:%.*]], i1 [[B1:%.*]]) { 839e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 840e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 841*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 842e0911b98Skhei4; CHECK-NEXT: br i1 [[B0]], label [[BB0:%.*]], label [[BB1:%.*]] 843e0911b98Skhei4; CHECK: bb0: 844e0911b98Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 845e0911b98Skhei4; CHECK: bb1: 846*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 847e0911b98Skhei4; CHECK-NEXT: br label [[BB2]] 848e0911b98Skhei4; CHECK: bb2: 849e0911b98Skhei4; CHECK-NEXT: ret void 850e0911b98Skhei4; 851e0911b98Skhei4 %src = alloca %struct.Foo, align 4 852e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 853e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 854e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 855e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 856e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 857e0911b98Skhei4 br i1 %b0, label %bb0, label %bb1 858e0911b98Skhei4 859e0911b98Skhei4bb0: 860e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 861e0911b98Skhei4 br label %bb2 862e0911b98Skhei4 863e0911b98Skhei4bb1: 864e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %src) 865e0911b98Skhei4 br label %bb2 866e0911b98Skhei4 867e0911b98Skhei4bb2: 868e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 869e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 870e0911b98Skhei4 ret void 871e0911b98Skhei4} 872e0911b98Skhei4 873e0911b98Skhei4; TODO: to merge following `is_def` cases, we need to do liveness analysis 874e0911b98Skhei4; or something that distinguish the full-size-Mod as a Def. 875e0911b98Skhei4; Tests that a memcpy that completely overwrites a stack value is a definition 876e0911b98Skhei4; for the purposes of liveness analysis. 877e0911b98Skhei4define void @memcpy_is_def() { 878e0911b98Skhei4; CHECK-LABEL: define void @memcpy_is_def() { 879e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 880e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 881*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 882*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 883e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 884*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 885e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 886*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 887e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[SRC]], ptr align 4 [[DEST]], i64 12, i1 false) 888*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 889*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 890*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 891e0911b98Skhei4; CHECK-NEXT: ret void 892e0911b98Skhei4; 893e0911b98Skhei4 %src = alloca %struct.Foo, align 4 894e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 895e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 896e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 897e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 898e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 899e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 900e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 901e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %src, ptr align 4 %dest, i64 12, i1 false) 902e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %src) 903e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 904e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 905e0911b98Skhei4 ret void 906e0911b98Skhei4} 907e0911b98Skhei4 908e0911b98Skhei4; TODO: merge allocas 909e0911b98Skhei4; Tests that a memset that completely overwrites a stack value is a definition 910e0911b98Skhei4; for the purposes of liveness analysis. 911e0911b98Skhei4define void @memset_is_def() { 912e0911b98Skhei4; CHECK-LABEL: define void @memset_is_def() { 913e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 914e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 915*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 916*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 917e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 918*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 919e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 920*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 921e0911b98Skhei4; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[SRC]], i8 42, i64 12, i1 false) 922*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 923*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 924*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 925e0911b98Skhei4; CHECK-NEXT: ret void 926e0911b98Skhei4; 927e0911b98Skhei4 %src = alloca %struct.Foo, align 4 928e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 929e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 930e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 931e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 932e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 933e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 934e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 935e0911b98Skhei4 call void @llvm.memset.p0.i64(ptr align 4 %src, i8 42, i64 12, i1 false) 936e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %src) 937e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 938e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 939e0911b98Skhei4 ret void 940e0911b98Skhei4} 941e0911b98Skhei4 942e0911b98Skhei4; TODO: merge allocas 943e0911b98Skhei4; Tests that a store that completely overwrites a stack value is a definition 944e0911b98Skhei4; for the purposes of liveness analysis. 945e0911b98Skhei4define void @store_is_def() { 946e0911b98Skhei4; CHECK-LABEL: define void @store_is_def() { 947e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i32, align 4 948e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca i32, align 4 949*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[SRC]]) 950*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr captures(none) [[DEST]]) 951e0911b98Skhei4; CHECK-NEXT: store i32 42, ptr [[SRC]], align 4 952*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 953e0911b98Skhei4; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4 954e0911b98Skhei4; CHECK-NEXT: store i32 [[TMP2]], ptr [[DEST]], align 4 955*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 956e0911b98Skhei4; CHECK-NEXT: store i32 64, ptr [[SRC]], align 4 957*29441e4fSNikita Popov; CHECK-NEXT: [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 958*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[SRC]]) 959*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr captures(none) [[DEST]]) 960e0911b98Skhei4; CHECK-NEXT: ret void 961e0911b98Skhei4; 962e0911b98Skhei4 %src = alloca i32, align 4 963e0911b98Skhei4 %dest = alloca i32, align 4 964e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %src) 965e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 4, ptr nocapture %dest) 966e0911b98Skhei4 store i32 42, ptr %src 967e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 968e0911b98Skhei4 %2 = load i32, ptr %src 969e0911b98Skhei4 store i32 %2, ptr %dest 970e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 971e0911b98Skhei4 store i32 64, ptr %src 972e0911b98Skhei4 %4 = call i32 @use_nocapture(ptr noundef nocapture %src) 973e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %src) 974e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 4, ptr nocapture %dest) 975e0911b98Skhei4 ret void 97639321564Skhei4} 97739321564Skhei4 978c4d37c35Skhei4; TODO: merge src and dest, because any execution path doesn't cause conflicts. 979c4d37c35Skhei4; Tests that exists modref for both src/dest, but it never conflict on the execution. 980c4d37c35Skhei4define void @multi_bb_dataflow(i1 %b) { 981c4d37c35Skhei4; CHECK-LABEL: define void @multi_bb_dataflow 982c4d37c35Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 983c4d37c35Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 984c4d37c35Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 985*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 986*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 987c4d37c35Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 988*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 989c4d37c35Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 990c4d37c35Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 991c4d37c35Skhei4; CHECK: bb0: 992*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 993c4d37c35Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 994c4d37c35Skhei4; CHECK: bb1: 995*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 996c4d37c35Skhei4; CHECK-NEXT: br label [[BB2]] 997c4d37c35Skhei4; CHECK: bb2: 998*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 999*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 1000c4d37c35Skhei4; CHECK-NEXT: ret void 1001c4d37c35Skhei4; 1002c4d37c35Skhei4 %src = alloca %struct.Foo, align 4 1003c4d37c35Skhei4 %dest = alloca %struct.Foo, align 4 1004c4d37c35Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 1005c4d37c35Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 1006c4d37c35Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 1007c4d37c35Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 1008c4d37c35Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 1009c4d37c35Skhei4 br i1 %b, label %bb0, label %bb1 1010c4d37c35Skhei4 1011c4d37c35Skhei4bb0: 1012c4d37c35Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %src) 1013c4d37c35Skhei4 br label %bb2 1014c4d37c35Skhei4 1015c4d37c35Skhei4bb1: 1016c4d37c35Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 1017c4d37c35Skhei4 br label %bb2 1018c4d37c35Skhei4 1019c4d37c35Skhei4bb2: 1020c4d37c35Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 1021c4d37c35Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 1022c4d37c35Skhei4 ret void 1023c4d37c35Skhei4} 1024c4d37c35Skhei4 1025c4d37c35Skhei4 102639321564Skhei4; Optimization failures follow: 102739321564Skhei4 1028e0911b98Skhei4; Tests that a memcpy that doesn't completely overwrite a stack value is a use 1029e0911b98Skhei4; for the purposes of liveness analysis, not a definition. 1030e0911b98Skhei4define void @incomplete_memcpy() { 1031e0911b98Skhei4; CHECK-LABEL: define void @incomplete_memcpy() { 1032e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 1033e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1034*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1035*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 1036e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1037*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1038e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 11, i1 false) 1039*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 1040*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1041*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 1042e0911b98Skhei4; CHECK-NEXT: ret void 1043e0911b98Skhei4; 1044e0911b98Skhei4 %src = alloca %struct.Foo, align 4 1045e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 1046e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 1047e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 1048e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 1049e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 1050e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 11, i1 false) 1051e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %dest) 1052e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 1053e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 1054e0911b98Skhei4 ret void 1055e0911b98Skhei4} 1056e0911b98Skhei4 1057e0911b98Skhei4; Tests that a store that doesn't completely overwrite a stack value is a use 1058e0911b98Skhei4; for the purposes of liveness analysis, not a definition. 1059e0911b98Skhei4define void @incomplete_store() { 1060e0911b98Skhei4; CHECK-LABEL: define void @incomplete_store() { 1061e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 1062e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1063*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1064*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 1065e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1066*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1067e0911b98Skhei4; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4 1068e0911b98Skhei4; CHECK-NEXT: store i32 [[TMP2]], ptr [[DEST]], align 4 1069*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 1070*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1071*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 1072e0911b98Skhei4; CHECK-NEXT: ret void 1073e0911b98Skhei4; 1074e0911b98Skhei4 %src = alloca %struct.Foo, align 4 1075e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 1076e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 1077e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 1078e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 1079e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 1080e0911b98Skhei4 %2 = load i32, ptr %src 1081e0911b98Skhei4 store i32 %2, ptr %dest 1082e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 1083e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 1084e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 1085e0911b98Skhei4 ret void 1086e0911b98Skhei4} 1087e0911b98Skhei4 108839321564Skhei4; Tests that dynamically-sized allocas are never merged. 108939321564Skhei4define void @dynamically_sized_alloca(i64 %i) { 109039321564Skhei4; CHECK-LABEL: define void @dynamically_sized_alloca 109139321564Skhei4; CHECK-SAME: (i64 [[I:%.*]]) { 109239321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 [[I]], align 4 109339321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 [[I]], align 4 1094*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr captures(none) [[SRC]]) 1095*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr captures(none) [[DEST]]) 109639321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1097*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 109839321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1099*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1100*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr captures(none) [[SRC]]) 1101*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr captures(none) [[DEST]]) 110239321564Skhei4; CHECK-NEXT: ret void 110339321564Skhei4; 110439321564Skhei4 %src = alloca i8, i64 %i, align 4 110539321564Skhei4 %dest = alloca i8, i64 %i, align 4 110639321564Skhei4 call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %src) 110739321564Skhei4 call void @llvm.lifetime.start.p0(i64 -1, ptr nocapture %dest) 110839321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 110939321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 111039321564Skhei4 111139321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 111239321564Skhei4 111339321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 111439321564Skhei4 call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %src) 111539321564Skhei4 call void @llvm.lifetime.end.p0(i64 -1, ptr nocapture %dest) 111639321564Skhei4 ret void 111739321564Skhei4} 111839321564Skhei4 111939321564Skhei4 112039321564Skhei4; Tests that inalloca attributed allocas are never merged, to prevent stacksave/stackrestore handling. 112139321564Skhei4define void @inalloca() { 112239321564Skhei4; CHECK-LABEL: define void @inalloca() { 112339321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 112439321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca inalloca [[STRUCT_FOO]], align 4 1125*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1126*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 112739321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1128*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 112939321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1130*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1131*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1132*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 113339321564Skhei4; CHECK-NEXT: ret void 113439321564Skhei4; 113539321564Skhei4 %src = alloca %struct.Foo, align 4 113639321564Skhei4 %dest = alloca inalloca %struct.Foo, align 4 113739321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 113839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 113939321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 114039321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 114139321564Skhei4 114239321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 114339321564Skhei4 114439321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 114539321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 114639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 114739321564Skhei4 ret void 114839321564Skhei4} 114939321564Skhei4 115039321564Skhei4; Tests that a memcpy with a dynamic size is never optimized. 115139321564Skhei4define void @dynamically_sized_memcpy(i64 %size) { 115239321564Skhei4; CHECK-LABEL: define void @dynamically_sized_memcpy 115339321564Skhei4; CHECK-SAME: (i64 [[SIZE:%.*]]) { 115439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 115539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1156*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1157*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 115839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1159*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 116039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 [[SIZE]], i1 false) 1161*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1162*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 1163*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 116439321564Skhei4; CHECK-NEXT: ret void 116539321564Skhei4; 116639321564Skhei4 %src = alloca %struct.Foo, align 4 116739321564Skhei4 %dest = alloca %struct.Foo, align 4 116839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 116939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 117039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 117139321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 117239321564Skhei4 117339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 %size, i1 false) 117439321564Skhei4 117539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 117639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 117739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 117839321564Skhei4 ret void 117939321564Skhei4} 118039321564Skhei4 118139321564Skhei4; Tests that allocas with different sizes aren't merged together. 118239321564Skhei4define void @mismatched_alloca_size() { 118339321564Skhei4; CHECK-LABEL: define void @mismatched_alloca_size() { 118439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 24, align 4 118539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 12, align 4 1186*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr captures(none) [[SRC]]) 1187*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 118839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1189*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 119039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1191*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1192*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr captures(none) [[SRC]]) 1193*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 119439321564Skhei4; CHECK-NEXT: ret void 119539321564Skhei4; 119639321564Skhei4 %src = alloca i8, i64 24, align 4 119739321564Skhei4 %dest = alloca i8, i64 12, align 4 119839321564Skhei4 call void @llvm.lifetime.start.p0(i64 24, ptr nocapture %src) 119939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 120039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 120139321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 120239321564Skhei4 120339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 120439321564Skhei4 120539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 120639321564Skhei4 call void @llvm.lifetime.end.p0(i64 24, ptr nocapture %src) 120739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 120839321564Skhei4 ret void 120939321564Skhei4} 121039321564Skhei4 121139321564Skhei4; Tests that allocas with mismatched address spaces aren't combined. 121239321564Skhei4define void @mismatched_alloca_addrspace() { 121339321564Skhei4; CHECK-LABEL: define void @mismatched_alloca_addrspace() { 121439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca i8, i64 24, align 4, addrspace(1) 121539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca i8, i64 12, align 4, addrspace(2) 1216*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p1(i64 24, ptr addrspace(1) captures(none) [[SRC]]) 1217*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p2(i64 12, ptr addrspace(2) captures(none) [[DEST]]) 121839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr addrspace(1) [[SRC]], align 4 1219*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr addrspace(1) captures(none) [[SRC]]) 122039321564Skhei4; 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*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p1(i64 24, ptr addrspace(1) captures(none) [[SRC]]) 1222*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr addrspace(2) captures(none) [[DEST]]) 1223*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p2(i64 12, ptr addrspace(2) captures(none) [[DEST]]) 122439321564Skhei4; CHECK-NEXT: ret void 122539321564Skhei4; 122639321564Skhei4 %src = alloca i8, i64 24, align 4, addrspace(1) 122739321564Skhei4 %dest = alloca i8, i64 12, align 4, addrspace(2) 122839321564Skhei4 call void @llvm.lifetime.start.p1(i64 24, ptr addrspace(1) nocapture %src) 122939321564Skhei4 call void @llvm.lifetime.start.p2(i64 12, ptr addrspace(2) nocapture %dest) 123039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr addrspace(1) %src 123139321564Skhei4 %1 = call i32 @use_nocapture(ptr addrspace(1) nocapture %src) 123239321564Skhei4 123339321564Skhei4 call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 %dest, ptr addrspace(1) align 4 %src, i64 12, i1 false) 123439321564Skhei4 123539321564Skhei4 call void @llvm.lifetime.end.p1(i64 24, ptr addrspace(1) nocapture %src) 123639321564Skhei4 %2 = call i32 @use_nocapture(ptr addrspace(2) nocapture %dest) 123739321564Skhei4 call void @llvm.lifetime.end.p2(i64 12, ptr addrspace(2) nocapture %dest) 123839321564Skhei4 ret void 123939321564Skhei4} 124039321564Skhei4 124139321564Skhei4; Tests that volatile memcpys aren't removed. 124239321564Skhei4define void @volatile_memcpy() { 124339321564Skhei4; CHECK-LABEL: define void @volatile_memcpy() { 124439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 124539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1246*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1247*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 124839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1249*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 125039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 true) 1251*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1252*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1253*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 125439321564Skhei4; CHECK-NEXT: ret void 125539321564Skhei4; 125639321564Skhei4 %src = alloca %struct.Foo, align 4 125739321564Skhei4 %dest = alloca %struct.Foo, align 4 125839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 125939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 126039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 126139321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 126239321564Skhei4 126339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 true) 126439321564Skhei4 126539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 126639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 126739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 126839321564Skhei4 ret void 126939321564Skhei4} 127039321564Skhei4 127139321564Skhei4; Tests that the optimization isn't performed when the destination is captured. 127239321564Skhei4define void @dest_captured() { 127339321564Skhei4; CHECK-LABEL: define void @dest_captured() { 127439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 127539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1276*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1277*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 127839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1279*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 128039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 128139321564Skhei4; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_maycapture(ptr [[DEST]]) 1282*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1283*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 128439321564Skhei4; CHECK-NEXT: ret void 128539321564Skhei4; 128639321564Skhei4 %src = alloca %struct.Foo, align 4 128739321564Skhei4 %dest = alloca %struct.Foo, align 4 128839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 128939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 129039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 129139321564Skhei4 129239321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 129339321564Skhei4 129439321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 129539321564Skhei4 %2 = call i32 @use_maycapture(ptr %dest) 129639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 129739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 129839321564Skhei4 ret void 129939321564Skhei4} 130039321564Skhei4 130139321564Skhei4; Tests that the optimization isn't performed when the source is captured. 130239321564Skhei4define void @src_captured() { 130339321564Skhei4; CHECK-LABEL: define void @src_captured() { 130439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 130539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1306*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1307*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 130839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 130939321564Skhei4; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_maycapture(ptr [[SRC]]) 131039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1311*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1312*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1313*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 131439321564Skhei4; CHECK-NEXT: ret void 131539321564Skhei4; 131639321564Skhei4 %src = alloca %struct.Foo, align 4 131739321564Skhei4 %dest = alloca %struct.Foo, align 4 131839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 131939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 132039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 132139321564Skhei4 %1 = call i32 @use_maycapture(ptr %src) 132239321564Skhei4 132339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 132439321564Skhei4 132539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 132639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 132739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 132839321564Skhei4 ret void 132939321564Skhei4} 133039321564Skhei4 133139321564Skhei4; Tests that failure if any modref exists before the copy, 133239321564Skhei4; Exactly ref seems safe because no mod say ref would be always undefined, but to make simple and conservative. 133339321564Skhei4define void @mod_ref_before_copy() { 133439321564Skhei4; CHECK-LABEL: define void @mod_ref_before_copy() { 133539321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 133639321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1337*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1338*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 133939321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1340*29441e4fSNikita Popov; CHECK-NEXT: [[R:%.*]] = call i32 @use_readonly(ptr captures(none) [[DEST]]) 1341*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 134239321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1343*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1344*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1345*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 134639321564Skhei4; CHECK-NEXT: ret void 134739321564Skhei4; 134839321564Skhei4 %src = alloca %struct.Foo, align 4 134939321564Skhei4 %dest = alloca %struct.Foo, align 4 135039321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 135139321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 135239321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 135339321564Skhei4 %r = call i32 @use_readonly(ptr nocapture %dest) 135439321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 135539321564Skhei4 135639321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 135739321564Skhei4 135839321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 135939321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 136039321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 136139321564Skhei4 ret void 136239321564Skhei4} 136339321564Skhei4 136439321564Skhei4; Tests that failure because copy semantics will change if dest is replaced with src. 136539321564Skhei4define void @mod_dest_before_copy() { 136639321564Skhei4; CHECK-LABEL: define void @mod_dest_before_copy() { 136739321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 136839321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1369*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1370*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 137139321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 137239321564Skhei4; CHECK-NEXT: store i32 13, ptr [[DEST]], align 4 1373*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 137439321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1375*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1376*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1377*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 137839321564Skhei4; CHECK-NEXT: ret void 137939321564Skhei4; 138039321564Skhei4 %src = alloca %struct.Foo, align 4 138139321564Skhei4 %dest = alloca %struct.Foo, align 4 138239321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 138339321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 138439321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 138539321564Skhei4 store i32 13, ptr %dest 138639321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 138739321564Skhei4 138839321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 138939321564Skhei4 139039321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 139139321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 139239321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 139339321564Skhei4 ret void 139439321564Skhei4} 139539321564Skhei4 139639321564Skhei4define void @mod_src_before_store_after_load() { 139739321564Skhei4; CHECK-LABEL: define void @mod_src_before_store_after_load() { 139839321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 139939321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1400*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1401*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 140239321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 140339321564Skhei4; CHECK-NEXT: store i32 13, ptr [[DEST]], align 4 1404*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 140539321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 140639321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 4 1407*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1408*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1409*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 141039321564Skhei4; CHECK-NEXT: ret void 141139321564Skhei4; 141239321564Skhei4 %src = alloca %struct.Foo, align 4 141339321564Skhei4 %dest = alloca %struct.Foo, align 4 141439321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 141539321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 141639321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 141739321564Skhei4 store i32 13, ptr %dest 141839321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 141939321564Skhei4 142039321564Skhei4 %src.val = load %struct.Foo, ptr %src 142139321564Skhei4 store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src 142239321564Skhei4 store %struct.Foo %src.val, ptr %dest 142339321564Skhei4 142439321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 142539321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 142639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 142739321564Skhei4 ret void 142839321564Skhei4} 142939321564Skhei4 143039321564Skhei4; Tests that the optimization isn't performed, 143139321564Skhei4; when the source may have mod and dest may have ref after the full copy. 143239321564Skhei4define void @src_mod_dest_ref_after_copy() { 143339321564Skhei4; CHECK-LABEL: define void @src_mod_dest_ref_after_copy() { 143439321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 143539321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1436*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1437*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 143839321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 143939321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 144039321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 4 1441*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1442*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1443*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 144439321564Skhei4; CHECK-NEXT: ret void 144539321564Skhei4; 144639321564Skhei4 %src = alloca %struct.Foo, align 4 144739321564Skhei4 %dest = alloca %struct.Foo, align 4 144839321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 144939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 145039321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 145139321564Skhei4 145239321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 145339321564Skhei4 145439321564Skhei4 store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src 145539321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %dest) 145639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 145739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 145839321564Skhei4 ret void 145939321564Skhei4} 146039321564Skhei4 146139321564Skhei4; Tests that the optimization isn't performed. 146239321564Skhei4; Merging dest to src is no longer valid if conflicting Mod/Ref exist. 146339321564Skhei4define void @src_ref_dest_mod_after_copy() { 146439321564Skhei4; CHECK-LABEL: define void @src_ref_dest_mod_after_copy() { 146539321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 146639321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1467*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1468*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 146939321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 147039321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 147139321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[DEST]], align 4 1472*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 1473*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1474*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 147539321564Skhei4; CHECK-NEXT: ret void 147639321564Skhei4; 147739321564Skhei4 %src = alloca %struct.Foo, align 4 147839321564Skhei4 %dest = alloca %struct.Foo, align 4 147939321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 148039321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 148139321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 148239321564Skhei4 148339321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 148439321564Skhei4 148539321564Skhei4 store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %dest 148639321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 148739321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 148839321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 148939321564Skhei4 ret void 149039321564Skhei4} 149139321564Skhei4 149239321564Skhei4; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks 149339321564Skhei4define void @dest_alias_mod_before_copy() { 149439321564Skhei4; CHECK-LABEL: define void @dest_alias_mod_before_copy() { 149539321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 149639321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1497*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1498*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 149939321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 150039321564Skhei4; CHECK-NEXT: [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 1 150139321564Skhei4; CHECK-NEXT: store i32 13, ptr [[DEST_ALIAS]], align 4 1502*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 150339321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1504*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1505*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1506*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 150739321564Skhei4; CHECK-NEXT: ret void 150839321564Skhei4; 150939321564Skhei4 %src = alloca %struct.Foo, align 4 151039321564Skhei4 %dest = alloca %struct.Foo, align 4 151139321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 151239321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 151339321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 151439321564Skhei4 %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 1 151539321564Skhei4 store i32 13, ptr %dest.alias 151639321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 151739321564Skhei4 151839321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 151939321564Skhei4 152039321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 152139321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 152239321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 152339321564Skhei4 ret void 152439321564Skhei4} 152539321564Skhei4 152639321564Skhei4; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks 152739321564Skhei4define void @alias_src_ref_dest_mod_after_copy() { 152839321564Skhei4; CHECK-LABEL: define void @alias_src_ref_dest_mod_after_copy() { 152939321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 153039321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1531*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1532*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 153339321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1534*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 153539321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 153639321564Skhei4; CHECK-NEXT: [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 1 153739321564Skhei4; CHECK-NEXT: store i32 13, ptr [[DEST_ALIAS]], align 4 1538*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 1539*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1540*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 154139321564Skhei4; CHECK-NEXT: ret void 154239321564Skhei4; 154339321564Skhei4 %src = alloca %struct.Foo, align 4 154439321564Skhei4 %dest = alloca %struct.Foo, align 4 154539321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 154639321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 154739321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 154839321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 154939321564Skhei4 155039321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 155139321564Skhei4 155239321564Skhei4 %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 1 155339321564Skhei4 store i32 13, ptr %dest.alias 155439321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %src) 155539321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 155639321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 155739321564Skhei4 ret void 155839321564Skhei4} 155939321564Skhei4 1560e0911b98Skhei4; Tests that the optimization isn't performed when the source and destination 1561c4d37c35Skhei4; have mod ref conflict on bb2. 1562c4d37c35Skhei4define void @multi_bb_dataflow_conflict(i1 %b) { 1563c4d37c35Skhei4; CHECK-LABEL: define void @multi_bb_dataflow_conflict 1564e0911b98Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 1565e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 1566e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1567*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1568*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 1569e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1570*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1571e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1572e0911b98Skhei4; CHECK-NEXT: br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]] 1573e0911b98Skhei4; CHECK: bb0: 1574*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1575e0911b98Skhei4; CHECK-NEXT: br label [[BB2:%.*]] 1576e0911b98Skhei4; CHECK: bb1: 1577*29441e4fSNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 1578e0911b98Skhei4; CHECK-NEXT: br label [[BB2]] 1579e0911b98Skhei4; CHECK: bb2: 1580*29441e4fSNikita Popov; CHECK-NEXT: [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 1581*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1582*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 1583e0911b98Skhei4; CHECK-NEXT: ret void 1584e0911b98Skhei4; 1585e0911b98Skhei4 %src = alloca %struct.Foo, align 4 1586e0911b98Skhei4 %dest = alloca %struct.Foo, align 4 1587e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 1588e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 1589e0911b98Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 1590e0911b98Skhei4 %1 = call i32 @use_nocapture(ptr noundef nocapture %src) 1591e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 1592e0911b98Skhei4 br i1 %b, label %bb0, label %bb1 1593e0911b98Skhei4 1594e0911b98Skhei4bb0: 1595e0911b98Skhei4 %2 = call i32 @use_nocapture(ptr noundef nocapture %src) 1596e0911b98Skhei4 br label %bb2 1597e0911b98Skhei4 1598e0911b98Skhei4bb1: 1599e0911b98Skhei4 %3 = call i32 @use_nocapture(ptr noundef nocapture %dest) 1600e0911b98Skhei4 br label %bb2 1601e0911b98Skhei4 1602e0911b98Skhei4bb2: 1603c4d37c35Skhei4 %4 = call i32 @use_nocapture(ptr noundef nocapture %dest) 1604e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 1605e0911b98Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 1606e0911b98Skhei4 ret void 1607e0911b98Skhei4} 1608e0911b98Skhei4 1609e0911b98Skhei4; Tests that failure because after copy mod could be before copy on loop. 1610e0911b98Skhei4define void @multi_bb_loop_dest_mod_before_copy(i32 %n) { 1611e0911b98Skhei4; CHECK-LABEL: define void @multi_bb_loop_dest_mod_before_copy 1612e0911b98Skhei4; CHECK-SAME: (i32 [[N:%.*]]) { 1613e0911b98Skhei4; CHECK-NEXT: entry: 1614e0911b98Skhei4; CHECK-NEXT: [[NLT1:%.*]] = icmp slt i32 [[N]], 1 1615e0911b98Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 1616e0911b98Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 8 1617*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1618*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[DEST]]) 1619e0911b98Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4 1620e0911b98Skhei4; CHECK-NEXT: br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]] 1621e0911b98Skhei4; CHECK: loop_body: 1622e0911b98Skhei4; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ] 1623e0911b98Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DEST]], ptr align 8 [[SRC]], i64 12, i1 false) 1624e0911b98Skhei4; CHECK-NEXT: [[NEW_I]] = add i32 [[I]], 1 1625e0911b98Skhei4; CHECK-NEXT: store i32 [[NEW_I]], ptr [[DEST]], align 4 1626e0911b98Skhei4; CHECK-NEXT: [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]] 1627e0911b98Skhei4; CHECK-NEXT: br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]] 1628e0911b98Skhei4; CHECK: loop_exit: 1629e0911b98Skhei4; CHECK-NEXT: ret void 1630e0911b98Skhei4; 1631e0911b98Skhei4entry: 1632e0911b98Skhei4 %nlt1 = icmp slt i32 %n, 1 1633e0911b98Skhei4 %src = alloca %struct.Foo, align 8 1634e0911b98Skhei4 %dest = alloca %struct.Foo, align 8 1635e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 1636e0911b98Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %dest) 1637e0911b98Skhei4 store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src 1638e0911b98Skhei4 br i1 %nlt1, label %loop_exit, label %loop_body 1639e0911b98Skhei4 1640e0911b98Skhei4loop_body: 1641e0911b98Skhei4 %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ] 1642e0911b98Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false) 1643e0911b98Skhei4 %new_i = add i32 %i, 1 1644e0911b98Skhei4 store i32 %new_i, ptr %dest 1645e0911b98Skhei4 %igtn = icmp sgt i32 %new_i, %n 1646e0911b98Skhei4 br i1 %igtn, label %loop_exit, label %loop_body 1647e0911b98Skhei4 1648e0911b98Skhei4loop_exit: 1649e0911b98Skhei4 ret void 1650e0911b98Skhei4} 1651e0911b98Skhei4 165239321564Skhei4; Tests that failure because partial-sized lifetimes are counted as mod. 165339321564Skhei4define void @partial_lifetime() { 165439321564Skhei4; CHECK-LABEL: define void @partial_lifetime() { 165539321564Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4 165639321564Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4 1657*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 12, ptr captures(none) [[SRC]]) 1658*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 3, ptr captures(none) [[DEST]]) 165939321564Skhei4; CHECK-NEXT: store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4 1660*29441e4fSNikita Popov; CHECK-NEXT: [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]]) 166139321564Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false) 1662*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 3, ptr captures(none) [[SRC]]) 1663*29441e4fSNikita Popov; CHECK-NEXT: [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]]) 1664*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[SRC]]) 1665*29441e4fSNikita Popov; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 12, ptr captures(none) [[DEST]]) 166639321564Skhei4; CHECK-NEXT: ret void 166739321564Skhei4; 166839321564Skhei4 %src = alloca %struct.Foo, align 4 166939321564Skhei4 %dest = alloca %struct.Foo, align 4 167039321564Skhei4 call void @llvm.lifetime.start.p0(i64 12, ptr nocapture %src) 167139321564Skhei4 call void @llvm.lifetime.start.p0(i64 3, ptr nocapture %dest) 167239321564Skhei4 store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src 167339321564Skhei4 %1 = call i32 @use_nocapture(ptr nocapture %src) 167439321564Skhei4 167539321564Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false) 167639321564Skhei4 167739321564Skhei4 call void @llvm.lifetime.end.p0(i64 3, ptr nocapture %src) 167839321564Skhei4 %2 = call i32 @use_nocapture(ptr nocapture %dest) 167939321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %src) 168039321564Skhei4 call void @llvm.lifetime.end.p0(i64 12, ptr nocapture %dest) 168139321564Skhei4 ret void 168239321564Skhei4} 1683a92e1971Skhei4 1684a92e1971Skhei4; Do not merge or crash if the different block user comes first. 1685a92e1971Skhei4define void @crash_store63851(i1 %b) { 1686a92e1971Skhei4; CHECK-LABEL: define void @crash_store63851 1687a92e1971Skhei4; CHECK-SAME: (i1 [[B:%.*]]) { 1688a92e1971Skhei4; CHECK-NEXT: [[DEST:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 1689a92e1971Skhei4; CHECK-NEXT: [[SRC:%.*]] = alloca [[STRUCT_FOO]], align 8 1690a92e1971Skhei4; CHECK-NEXT: store i32 0, ptr [[DEST]], align 4 1691a92e1971Skhei4; CHECK-NEXT: br i1 [[B]], label [[THEN:%.*]], label [[ELSE:%.*]] 1692a92e1971Skhei4; CHECK: then: 1693*29441e4fSNikita Popov; CHECK-NEXT: [[T:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1694a92e1971Skhei4; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DEST]], ptr [[SRC]], i64 12, i1 false) 1695*29441e4fSNikita Popov; CHECK-NEXT: [[T3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]]) 1696*29441e4fSNikita Popov; CHECK-NEXT: [[T4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]]) 1697a92e1971Skhei4; CHECK-NEXT: br label [[ELSE]] 1698a92e1971Skhei4; CHECK: else: 1699a92e1971Skhei4; CHECK-NEXT: ret void 1700a92e1971Skhei4; 1701a92e1971Skhei4 %dest = alloca %struct.Foo, align 8 1702a92e1971Skhei4 %src = alloca %struct.Foo, align 8 1703a92e1971Skhei4 store i32 0, ptr %dest, align 4 1704a92e1971Skhei4 br i1 %b, label %then, label %else 1705a92e1971Skhei4 1706a92e1971Skhei4then: ; preds = %entry 1707a92e1971Skhei4 %t = call i32 @use_nocapture(ptr nocapture noundef %src) 1708a92e1971Skhei4 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 12, i1 false) 1709a92e1971Skhei4 %t3 = call i32 @use_nocapture(ptr nocapture noundef %src) 1710a92e1971Skhei4 %t4 = call i32 @use_nocapture(ptr nocapture noundef %dest) 1711a92e1971Skhei4 br label %else 1712a92e1971Skhei4 1713a92e1971Skhei4else: ; preds = %then, %entry 1714a92e1971Skhei4 ret void 1715a92e1971Skhei4 1716a92e1971Skhei4 uselistorder ptr %dest, { 1, 2, 0 } 1717a92e1971Skhei4} 1718