brintos

brintos / llvm-project-archived public Read only

0
0
Text · 79.7 KiB · 0c2e05f Raw
1790 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt < %s -passes=memcpyopt -verify-memoryssa -S | FileCheck %s3 4%struct.Foo = type { i32, i32, i32 }5 6declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)7declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)8declare void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) noalias nocapture writeonly, ptr addrspace(1) noalias nocapture readonly, i64, i1 immarg)9declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)10declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)11 12declare void @llvm.lifetime.start.p0(ptr nocapture)13declare void @llvm.lifetime.end.p0(ptr nocapture)14declare void @llvm.lifetime.start.p1(ptr addrspace(1) nocapture)15declare void @llvm.lifetime.end.p1(ptr addrspace(1) nocapture)16declare void @llvm.lifetime.start.p2(ptr addrspace(2) nocapture)17declare void @llvm.lifetime.end.p2(ptr addrspace(2) nocapture)18 19declare i32 @use_nocapture(ptr nocapture)20declare i32 @use_maycapture(ptr noundef)21declare i32 @use_readonly(ptr readonly)22declare i32 @use_writeonly(ptr noundef) memory(write)23 24define void @basic_memcpy() {25; CHECK-LABEL: define void @basic_memcpy() {26; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 427; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 428; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])29; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])30; CHECK-NEXT:    ret void31;32  %src = alloca %struct.Foo, align 433  %dest = alloca %struct.Foo, align 434  call void @llvm.lifetime.start.p0(ptr nocapture %src)35  call void @llvm.lifetime.start.p0(ptr nocapture %dest)36  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src37  %1 = call i32 @use_nocapture(ptr nocapture %src)38 39  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)40 41  %2 = call i32 @use_nocapture(ptr nocapture %dest)42 43  call void @llvm.lifetime.end.p0(ptr nocapture %src)44  call void @llvm.lifetime.end.p0(ptr nocapture %dest)45  ret void46}47 48define i32 @use_not_dominated_by_src_alloca() {49; CHECK-LABEL: define i32 @use_not_dominated_by_src_alloca() {50; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, align 451; CHECK-NEXT:    [[DEST_GEP:%.*]] = getelementptr i64, ptr [[SRC]], i64 -152; CHECK-NEXT:    [[DEST_USE:%.*]] = load i8, ptr [[DEST_GEP]], align 153; CHECK-NEXT:    ret i32 054;55  %dest = alloca i1, align 156  ; Replacing the use of dest with src causes no domination uses.57  %dest.gep = getelementptr i64, ptr %dest, i64 -158  %dest.use = load i8, ptr %dest.gep, align 159  %src = alloca i8, align 460  %src.val = load i1, ptr %src, align 461 62  store i1 %src.val, ptr %dest, align 163 64  ret i32 065}66 67define void @basic_memmove() {68; CHECK-LABEL: define void @basic_memmove() {69; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 470; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 471; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])72; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])73; CHECK-NEXT:    ret void74;75  %src = alloca %struct.Foo, align 476  %dest = alloca %struct.Foo, align 477  call void @llvm.lifetime.start.p0(ptr nocapture %src)78  call void @llvm.lifetime.start.p0(ptr nocapture %dest)79  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src80  %1 = call i32 @use_nocapture(ptr nocapture %src)81 82  call void @llvm.memmove.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)83 84  %2 = call i32 @use_nocapture(ptr nocapture %dest)85 86  call void @llvm.lifetime.end.p0(ptr nocapture %src)87  call void @llvm.lifetime.end.p0(ptr nocapture %dest)88  ret void89}90 91; Tests that the optimization succeeds with a load/store pair.92define void @load_store() {93; CHECK-LABEL: define void @load_store() {94; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 495; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 496; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])97; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])98; CHECK-NEXT:    ret void99;100  %src = alloca i32, align 4101  %dest = alloca i32, align 4102  call void @llvm.lifetime.start.p0(ptr nocapture %src)103  call void @llvm.lifetime.start.p0(ptr nocapture %dest)104  store i32 42, ptr %src105  %1 = call i32 @use_nocapture(ptr nocapture %src)106 107  %src.val = load i32, ptr %src108  store i32 %src.val, ptr %dest109 110  %2 = call i32 @use_nocapture(ptr nocapture %dest)111  call void @llvm.lifetime.end.p0(ptr nocapture %src)112  call void @llvm.lifetime.end.p0(ptr nocapture %dest)113  ret void114}115 116; Test scalable vectors.117define void @load_store_scalable(<vscale x 4 x i32> %x) {118; CHECK-LABEL: define void @load_store_scalable119; CHECK-SAME: (<vscale x 4 x i32> [[X:%.*]]) {120; CHECK-NEXT:    [[SRC:%.*]] = alloca <vscale x 4 x i32>, align 16121; CHECK-NEXT:    store <vscale x 4 x i32> [[X]], ptr [[SRC]], align 16122; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])123; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])124; CHECK-NEXT:    ret void125;126  %src = alloca <vscale x 4 x i32>127  %dest = alloca <vscale x 4 x i32>128  call void @llvm.lifetime.start.p0(ptr nocapture %src)129  call void @llvm.lifetime.start.p0(ptr nocapture %dest)130  store <vscale x 4 x i32> %x, ptr %src131  %1 = call i32 @use_nocapture(ptr nocapture %src)132 133  %src.val = load <vscale x 4 x i32>, ptr %src134  store <vscale x 4 x i32> %src.val, ptr %dest135 136  %2 = call i32 @use_nocapture(ptr nocapture %dest)137 138  call void @llvm.lifetime.end.p0(ptr nocapture %src)139  call void @llvm.lifetime.end.p0(ptr nocapture %dest)140  ret void141}142 143; Tests that merging two allocas shouldn't be more poisonous, smaller aligned src is valid.144define void @align_up() {145; CHECK-LABEL: define void @align_up() {146; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8147; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4148; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])149; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])150; CHECK-NEXT:    ret void151;152  %src = alloca %struct.Foo, align 4153  %dest = alloca %struct.Foo, align 8154  call void @llvm.lifetime.start.p0(ptr nocapture %src)155  call void @llvm.lifetime.start.p0(ptr nocapture %dest)156  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src157  %1 = call i32 @use_nocapture(ptr nocapture %src)158 159  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)160 161  %2 = call i32 @use_nocapture(ptr nocapture %dest)162  call void @llvm.lifetime.end.p0(ptr nocapture %src)163  call void @llvm.lifetime.end.p0(ptr nocapture %dest)164  ret void165}166 167; Tests that we correctly remove extra lifetime intrinsics when performing the168; optimization.169define void @remove_extra_lifetime_intrinsics() {170; CHECK-LABEL: define void @remove_extra_lifetime_intrinsics() {171; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4172; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4173; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])174; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])175; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])176; CHECK-NEXT:    ret void177;178  %src = alloca %struct.Foo, align 4179  %dest = alloca %struct.Foo, align 4180  call void @llvm.lifetime.start.p0(ptr nocapture %src)181  call void @llvm.lifetime.start.p0(ptr nocapture %dest)182  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src183  %1 = call i32 @use_nocapture(ptr nocapture %src)184 185  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)186 187  call void @llvm.lifetime.end.p0(ptr nocapture %src)188  %2 = call i32 @use_nocapture(ptr nocapture %dest)189  call void @llvm.lifetime.end.p0(ptr nocapture %src)190  call void @llvm.lifetime.start.p0(ptr nocapture %src)191  %3 = call i32 @use_nocapture(ptr nocapture %dest)192  call void @llvm.lifetime.end.p0(ptr nocapture %src)193  call void @llvm.lifetime.start.p0(ptr nocapture %dest)194  call void @llvm.lifetime.end.p0(ptr nocapture %dest)195  ret void196}197 198; Tests that we won't insert lifetime markers if they don't exist originally.199define void @no_lifetime() {200; CHECK-LABEL: define void @no_lifetime() {201; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4202; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4203; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])204; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])205; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])206; CHECK-NEXT:    ret void207;208  %src = alloca %struct.Foo, align 4209  %dest = alloca %struct.Foo, align 4210  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src211  %1 = call i32 @use_nocapture(ptr nocapture %src)212 213  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)214 215  %2 = call i32 @use_nocapture(ptr nocapture %dest)216  %3 = call i32 @use_nocapture(ptr nocapture %dest)217  ret void218}219 220; Tests that aliasing src or dest but no modification desn't prevent transformations.221define void @alias_no_mod() {222; CHECK-LABEL: define void @alias_no_mod() {223; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4224; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0225; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4226; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])227; CHECK-NEXT:    [[SRC_ALIAS:%.*]] = getelementptr [[STRUCT_FOO]], ptr [[SRC]], i32 0, i32 0228; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])229; CHECK-NEXT:    ret void230;231  %src = alloca %struct.Foo, align 4232  %dest = alloca %struct.Foo, align 4233  call void @llvm.lifetime.start.p0(ptr nocapture %src)234  call void @llvm.lifetime.start.p0(ptr nocapture %dest)235  %dest.alias = getelementptr %struct.Foo, ptr %dest, i32 0, i32 0236  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src237  %1 = call i32 @use_nocapture(ptr nocapture %src)238 239  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)240 241  %src.alias = getelementptr %struct.Foo, ptr %src, i32 0, i32 0242  %2 = call i32 @use_nocapture(ptr nocapture %dest)243  call void @llvm.lifetime.end.p0(ptr nocapture %src)244  call void @llvm.lifetime.end.p0(ptr nocapture %dest)245  ret void246}247 248; Scope domain249!0 = !{!0}250; Scope in that domain251!1 = !{!1, !0}252; Scope list253!2 = !{!1}254 255!3 = !{!"Whatever"}256 257; Tests that we remove scoped noalias metadata from a call.258define void @remove_scoped_noalias() {259; CHECK-LABEL: define void @remove_scoped_noalias() {260; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4261; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4262; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])263; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])264; CHECK-NEXT:    ret void265;266  %src = alloca %struct.Foo, align 4267  %dest = alloca %struct.Foo, align 4268  call void @llvm.lifetime.start.p0(ptr nocapture %src)269  call void @llvm.lifetime.start.p0(ptr nocapture %dest)270  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src271  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2272 273  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)274 275  call void @llvm.lifetime.end.p0(ptr nocapture %src)276  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2277  call void @llvm.lifetime.end.p0(ptr nocapture %dest)278  ret void279}280 281; Tests that we remove metadata on the merged alloca.282define void @remove_alloca_metadata() {283; CHECK-LABEL: define void @remove_alloca_metadata() {284; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4285; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4286; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])287; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])288; CHECK-NEXT:    ret void289;290  %src = alloca %struct.Foo, align 4, !annotation !3291  %dest = alloca %struct.Foo, align 4292  call void @llvm.lifetime.start.p0(ptr nocapture %src)293  call void @llvm.lifetime.start.p0(ptr nocapture %dest)294  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src295  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2296 297  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)298 299  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2300  call void @llvm.lifetime.end.p0(ptr nocapture %src)301  call void @llvm.lifetime.end.p0(ptr nocapture %dest)302  ret void303}304 305; Tests that we remove scoped noalias metadata from a call.306; And confirm that don't crash on noalias metadata on lifetime markers.307define void @noalias_on_lifetime() {308; CHECK-LABEL: define void @noalias_on_lifetime() {309; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4310; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4311; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])312; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])313; CHECK-NEXT:    ret void314;315  %src = alloca %struct.Foo, align 4316  %dest = alloca %struct.Foo, align 4317  call void @llvm.lifetime.start.p0(ptr nocapture %src)318  call void @llvm.lifetime.start.p0(ptr nocapture %dest)319  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src320  %1 = call i32 @use_nocapture(ptr nocapture %src), !alias.scope !2321 322  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)323 324  call void @llvm.lifetime.end.p0(ptr nocapture %src), !alias.scope !2325  %2 = call i32 @use_nocapture(ptr nocapture %dest), !noalias !2326  call void @llvm.lifetime.end.p0(ptr nocapture %dest), !noalias !2327  ret void328}329 330; Tests that we can merge alloca if the dest and src has only refs except lifetime intrinsics.331define void @src_ref_dest_ref_after_copy() {332; CHECK-LABEL: define void @src_ref_dest_ref_after_copy() {333; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4334; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4335; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]])336; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_readonly(ptr captures(none) [[SRC]])337; CHECK-NEXT:    ret void338;339  %src = alloca %struct.Foo, align 4340  %dest = alloca %struct.Foo, align 4341  call void @llvm.lifetime.start.p0(ptr nocapture %src)342  call void @llvm.lifetime.start.p0(ptr nocapture %dest)343  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src344 345  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)346 347  %1 = call i32 @use_readonly(ptr nocapture %src)348  %2 = call i32 @use_readonly(ptr nocapture %dest)349  call void @llvm.lifetime.end.p0(ptr nocapture %src)350  call void @llvm.lifetime.end.p0(ptr nocapture %dest)351  ret void352}353 354; Tests that we can merge alloca if the dest and src has only mods.355define void @src_mod_dest_mod_after_copy() {356; CHECK-LABEL: define void @src_mod_dest_mod_after_copy() {357; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4358; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4359; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]])360; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_writeonly(ptr captures(none) [[SRC]])361; CHECK-NEXT:    ret void362;363  %src = alloca %struct.Foo, align 4364  %dest = alloca %struct.Foo, align 4365  call void @llvm.lifetime.start.p0(ptr nocapture %src)366  call void @llvm.lifetime.start.p0(ptr nocapture %dest)367  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src368 369  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)370 371  %1 = call i32 @use_writeonly(ptr nocapture %src)372  %2 = call i32 @use_writeonly(ptr nocapture %dest)373  call void @llvm.lifetime.end.p0(ptr nocapture %src)374  call void @llvm.lifetime.end.p0(ptr nocapture %dest)375  ret void376}377 378define void @avoid_memory_use_last_user_crash() {379; CHECK-LABEL: define void @avoid_memory_use_last_user_crash() {380; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4381; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4382; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[SRC]], align 4383; CHECK-NEXT:    ret void384;385  %src = alloca %struct.Foo, align 4386  %dest = alloca %struct.Foo, align 4387  call void @llvm.lifetime.start.p0(ptr nocapture %src)388  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src389  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)390  call void @llvm.lifetime.end.p0(ptr nocapture %src)391  %v = load i32, ptr %dest392  ret void393}394 395; For multi-bb patch, we will insert it for next immediate post dominator block.396define void @terminator_lastuse() personality i32 0 {397; CHECK-LABEL: define void @terminator_lastuse() personality i32 0 {398; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4399; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4400; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])401; CHECK-NEXT:    [[RV:%.*]] = invoke i32 @use_nocapture(ptr [[SRC]])402; CHECK-NEXT:            to label [[SUC:%.*]] unwind label [[UNW:%.*]]403; CHECK:       unw:404; CHECK-NEXT:    [[LP:%.*]] = landingpad i32405; CHECK-NEXT:            cleanup406; CHECK-NEXT:    resume i32 0407; CHECK:       suc:408; CHECK-NEXT:    ret void409;410  %src = alloca %struct.Foo, align 4411  %dest = alloca %struct.Foo, align 4412  call void @llvm.lifetime.start.p0(ptr nocapture %src)413  call void @llvm.lifetime.start.p0(ptr nocapture %dest)414  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src415  %1 = call i32 @use_nocapture(ptr nocapture %src)416 417  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)418 419  call void @llvm.lifetime.end.p0(ptr %src)420  %rv = invoke i32 @use_nocapture(ptr %dest)421  to label %suc unwind label %unw422unw:423  %lp = landingpad i32 cleanup424  resume i32 0425suc:426  ret void427}428 429define void @multi_bb_memcpy(i1 %b) {430; CHECK-LABEL: define void @multi_bb_memcpy431; CHECK-SAME: (i1 [[B:%.*]]) {432; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4433; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4434; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])435; CHECK-NEXT:    br label [[BB0:%.*]]436; CHECK:       bb0:437; CHECK-NEXT:    br label [[BB1:%.*]]438; CHECK:       bb1:439; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])440; CHECK-NEXT:    ret void441;442  %src = alloca i32, align 4443  %dest = alloca i32, align 4444  call void @llvm.lifetime.start.p0(ptr nocapture %src)445  call void @llvm.lifetime.start.p0(ptr nocapture %dest)446  store i32 42, ptr %src447  %1 = call i32 @use_nocapture(ptr nocapture %src)448  br label %bb0449 450bb0:451  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 4, i1 false)452  br label %bb1453 454bb1:455  %2 = call i32 @use_nocapture(ptr nocapture %dest)456  call void @llvm.lifetime.end.p0(ptr nocapture %src)457  call void @llvm.lifetime.end.p0(ptr nocapture %dest)458  ret void459}460 461define void @multi_bb_load_store(i1 %b) {462; CHECK-LABEL: define void @multi_bb_load_store463; CHECK-SAME: (i1 [[B:%.*]]) {464; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4465; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4466; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])467; CHECK-NEXT:    br label [[BB0:%.*]]468; CHECK:       bb0:469; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])470; CHECK-NEXT:    ret void471;472  %src = alloca i32, align 4473  %dest = alloca i32, align 4474  call void @llvm.lifetime.start.p0(ptr nocapture %src)475  call void @llvm.lifetime.start.p0(ptr nocapture %dest)476  store i32 42, ptr %src477  %1 = call i32 @use_nocapture(ptr nocapture %src)478 479  %src.val = load i32, ptr %src480  store i32 %src.val, ptr %dest481  br label %bb0482 483bb0:484  %2 = call i32 @use_nocapture(ptr nocapture %dest)485  call void @llvm.lifetime.end.p0(ptr nocapture %src)486  call void @llvm.lifetime.end.p0(ptr nocapture %dest)487  ret void488}489 490; FIXME: merge allocas for bb-separated, but logically straight.491; We might be handle those load/store MemCpyOpt totally492define void @multi_bb_separated_load_store(i1 %b) {493; CHECK-LABEL: define void @multi_bb_separated_load_store494; CHECK-SAME: (i1 [[B:%.*]]) {495; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4496; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4497; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])498; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])499; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4500; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])501; CHECK-NEXT:    [[SRC_VAL:%.*]] = load i32, ptr [[SRC]], align 4502; CHECK-NEXT:    br label [[BB0:%.*]]503; CHECK:       bb0:504; CHECK-NEXT:    store i32 [[SRC_VAL]], ptr [[DEST]], align 4505; CHECK-NEXT:    br label [[BB1:%.*]]506; CHECK:       bb1:507; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])508; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])509; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])510; CHECK-NEXT:    ret void511;512  %src = alloca i32, align 4513  %dest = alloca i32, align 4514  call void @llvm.lifetime.start.p0(ptr nocapture %src)515  call void @llvm.lifetime.start.p0(ptr nocapture %dest)516  store i32 42, ptr %src517  %1 = call i32 @use_nocapture(ptr nocapture %src)518 519  %src.val = load i32, ptr %src520  br label %bb0521 522bb0:523  store i32 %src.val, ptr %dest524  br label %bb1525 526bb1:527  %2 = call i32 @use_nocapture(ptr nocapture %dest)528  call void @llvm.lifetime.end.p0(ptr nocapture %src)529  call void @llvm.lifetime.end.p0(ptr nocapture %dest)530  ret void531}532 533define void @multi_bb_simple_br(i1 %b) {534; CHECK-LABEL: define void @multi_bb_simple_br535; CHECK-SAME: (i1 [[B:%.*]]) {536; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4537; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4538; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])539; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]540; CHECK:       bb0:541; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])542; CHECK-NEXT:    br label [[BB2:%.*]]543; CHECK:       bb1:544; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])545; CHECK-NEXT:    br label [[BB2]]546; CHECK:       bb2:547; CHECK-NEXT:    ret void548;549  %src = alloca %struct.Foo, align 4550  %dest = alloca %struct.Foo, align 4551  call void @llvm.lifetime.start.p0(ptr nocapture %src)552  call void @llvm.lifetime.start.p0(ptr nocapture %dest)553  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src554  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)555  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)556  br i1 %b, label %bb0, label %bb1557 558bb0:559  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)560  br label %bb2561 562bb1:563  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)564  br label %bb2565 566bb2:567  call void @llvm.lifetime.end.p0(ptr nocapture %src)568  call void @llvm.lifetime.end.p0(ptr nocapture %dest)569  ret void570}571 572; Test for BasicBlock and Instruction mixed dominator finding.573define void @multi_bb_dom_test0(i1 %b) {574; CHECK-LABEL: define void @multi_bb_dom_test0575; CHECK-SAME: (i1 [[B:%.*]]) {576; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4577; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]578; CHECK:       bb0:579; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4580; CHECK-NEXT:    br label [[BB2:%.*]]581; CHECK:       bb1:582; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4583; CHECK-NEXT:    br label [[BB2]]584; CHECK:       bb2:585; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])586; CHECK-NEXT:    ret void587;588  %src = alloca %struct.Foo, align 4589  %dest = alloca %struct.Foo, align 4590  br i1 %b, label %bb0, label %bb1591 592bb0:593  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src594  br label %bb2595 596bb1:597  store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src598  br label %bb2599 600bb2:601  call void @llvm.lifetime.start.p0(ptr nocapture %dest)602  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)603  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)604 605  ret void606 607}608 609; Test for BasicBlock and Instruction mixed dominator finding.610define void @multi_bb_dom_test1(i1 %b) {611; CHECK-LABEL: define void @multi_bb_dom_test1612; CHECK-SAME: (i1 [[B:%.*]]) {613; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4614; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4615; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]616; CHECK:       bb0:617; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4618; CHECK-NEXT:    br label [[BB2:%.*]]619; CHECK:       bb1:620; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 40, i32 50, i32 60 }, ptr [[SRC]], align 4621; CHECK-NEXT:    br label [[BB2]]622; CHECK:       bb2:623; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])624; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)625; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])626; CHECK-NEXT:    ret void627; CHECK:       unr:628; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])629; CHECK-NEXT:    br label [[BB2]]630;631  %src = alloca %struct.Foo, align 4632  %dest = alloca %struct.Foo, align 4633  br i1 %b, label %bb0, label %bb1634 635bb0:636  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src637  br label %bb2638 639bb1:640  store %struct.Foo { i32 40, i32 50, i32 60 }, ptr %src641  br label %bb2642 643bb2:644  call void @llvm.lifetime.start.p0(ptr nocapture %dest)645  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1646  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)647 648  ret void649 650unr:651  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)652  br label %bb2653}654 655; Test for BasicBlock and Instruction mixed post-dominator finding.656define void @multi_bb_pdom_test0(i1 %b) {657; CHECK-LABEL: define void @multi_bb_pdom_test0658; CHECK-SAME: (i1 [[B:%.*]]) {659; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4660; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4661; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]662; CHECK:       bb0:663; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])664; CHECK-NEXT:    br label [[BB2:%.*]]665; CHECK:       bb1:666; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])667; CHECK-NEXT:    br label [[BB2]]668; CHECK:       bb2:669; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])670; CHECK-NEXT:    ret void671;672  %src = alloca %struct.Foo, align 4673  %dest = alloca %struct.Foo, align 4674  call void @llvm.lifetime.start.p0(ptr nocapture %dest)675  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src676  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1677  br i1 %b, label %bb0, label %bb1678 679bb0:680  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)681  br label %bb2682 683bb1:684  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)685  br label %bb2686 687bb2:688  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)689  call void @llvm.lifetime.end.p0(ptr nocapture %dest)690  ret void691 692  uselistorder ptr %dest, {  2, 3, 0, 1, 4, 5 }693}694 695; Test for inserting lifetime.end after the phi-node696define void @multi_bb_pdom_test1(i1 %b) {697; CHECK-LABEL: define void @multi_bb_pdom_test1698; CHECK-SAME: (i1 [[B:%.*]]) {699; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4700; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4701; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]702; CHECK:       bb0:703; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])704; CHECK-NEXT:    br label [[BB2:%.*]]705; CHECK:       bb1:706; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])707; CHECK-NEXT:    br label [[BB2]]708; CHECK:       bb2:709; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 42, [[BB0]] ], [ 41, [[BB1]] ]710; CHECK-NEXT:    ret void711;712  %src = alloca %struct.Foo, align 4713  %dest = alloca %struct.Foo, align 4714  call void @llvm.lifetime.start.p0(ptr nocapture %dest)715  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src716  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1717  br i1 %b, label %bb0, label %bb1718 719bb0:720  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)721  br label %bb2722 723bb1:724  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)725  br label %bb2726 727bb2:728  %i = phi i32 [ 42, %bb0 ], [ 41, %bb1 ]729  ret void730 731}732 733; Test for existing unreachable cycle734define void @multi_bb_pdom_test2(i1 %b) {735; CHECK-LABEL: define void @multi_bb_pdom_test2736; CHECK-SAME: (i1 [[B:%.*]]) {737; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4738; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4739; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])740; CHECK-NEXT:    ret void741; CHECK:       unr1:742; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])743; CHECK-NEXT:    br label [[UNR2:%.*]]744; CHECK:       unr2:745; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])746; CHECK-NEXT:    br label [[UNR1:%.*]]747;748  %src = alloca %struct.Foo, align 4749  %dest = alloca %struct.Foo, align 4750  call void @llvm.lifetime.start.p0(ptr nocapture %dest)751  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src752  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false); 1753  %1 = call i32 @use_nocapture(ptr noundef nocapture %dest)754  ret void755 756unr1:757  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)758  br label %unr2759 760unr2:761  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)762  br label %unr1763 764}765 766define void @multi_bb_loop(i32 %n) {767; CHECK-LABEL: define void @multi_bb_loop768; CHECK-SAME: (i32 [[N:%.*]]) {769; CHECK-NEXT:  entry:770; CHECK-NEXT:    [[NLT1:%.*]] = icmp slt i32 [[N]], 1771; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8772; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 4773; CHECK-NEXT:    br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]]774; CHECK:       loop_body:775; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ]776; CHECK-NEXT:    [[NEW_I]] = add i32 [[I]], 1777; CHECK-NEXT:    store i32 [[NEW_I]], ptr [[SRC]], align 4778; CHECK-NEXT:    [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]]779; CHECK-NEXT:    br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]]780; CHECK:       loop_exit:781; CHECK-NEXT:    ret void782;783entry:784  %nlt1 = icmp slt i32 %n, 1785  %src = alloca %struct.Foo, align 8786  %dest = alloca %struct.Foo, align 8787  call void @llvm.lifetime.start.p0(ptr nocapture %src)788  call void @llvm.lifetime.start.p0(ptr nocapture %dest)789  store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src790  br i1 %nlt1, label %loop_exit, label %loop_body791 792loop_body:793  %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ]794  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false)795  %new_i = add i32 %i, 1796  store i32 %new_i, ptr %src797  %igtn = icmp sgt i32 %new_i, %n798  br i1 %igtn, label %loop_exit, label %loop_body799 800loop_exit:801  ret void802}803 804define void @multi_bb_unreachable_modref(i1 %b0) {805; CHECK-LABEL: define void @multi_bb_unreachable_modref806; CHECK-SAME: (i1 [[B0:%.*]]) {807; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4808; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4809; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])810; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[EXIT:%.*]]811; CHECK:       exit:812; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])813; CHECK-NEXT:    ret void814; CHECK:       bb0:815; CHECK-NEXT:    ret void816;817  %src = alloca %struct.Foo, align 4818  %dest = alloca %struct.Foo, align 4819  call void @llvm.lifetime.start.p0(ptr nocapture %src)820  call void @llvm.lifetime.start.p0(ptr nocapture %dest)821  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src822  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)823  br i1 %b0, label %bb0, label %exit824 825exit:826  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)827  ret void828 829bb0:830  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)831  call void @llvm.lifetime.end.p0(ptr nocapture %src)832  call void @llvm.lifetime.end.p0(ptr nocapture %dest)833  ret void834}835 836define void @multi_bb_non_dominated(i1 %b0, i1 %b1) {837; CHECK-LABEL: define void @multi_bb_non_dominated838; CHECK-SAME: (i1 [[B0:%.*]], i1 [[B1:%.*]]) {839; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4840; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4841; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])842; CHECK-NEXT:    br i1 [[B0]], label [[BB0:%.*]], label [[BB1:%.*]]843; CHECK:       bb0:844; CHECK-NEXT:    br label [[BB2:%.*]]845; CHECK:       bb1:846; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])847; CHECK-NEXT:    br label [[BB2]]848; CHECK:       bb2:849; CHECK-NEXT:    ret void850;851  %src = alloca %struct.Foo, align 4852  %dest = alloca %struct.Foo, align 4853  call void @llvm.lifetime.start.p0(ptr nocapture %src)854  call void @llvm.lifetime.start.p0(ptr nocapture %dest)855  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src856  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)857  br i1 %b0, label %bb0, label %bb1858 859bb0:860  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)861  br label %bb2862 863bb1:864  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)865  br label %bb2866 867bb2:868  call void @llvm.lifetime.end.p0(ptr nocapture %src)869  call void @llvm.lifetime.end.p0(ptr nocapture %dest)870  ret void871}872 873; TODO: to merge following `is_def` cases, we need to do liveness analysis874; or something that distinguish the full-size-Mod as a Def.875; Tests that a memcpy that completely overwrites a stack value is a definition876; for the purposes of liveness analysis.877define void @memcpy_is_def() {878; CHECK-LABEL: define void @memcpy_is_def() {879; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4880; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4881; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])882; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])883; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4884; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])885; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)886; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])887; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[SRC]], ptr align 4 [[DEST]], i64 12, i1 false)888; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])889; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])890; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])891; CHECK-NEXT:    ret void892;893  %src = alloca %struct.Foo, align 4894  %dest = alloca %struct.Foo, align 4895  call void @llvm.lifetime.start.p0(ptr nocapture %src)896  call void @llvm.lifetime.start.p0(ptr nocapture %dest)897  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src898  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)899  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)900  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)901  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %src, ptr align 4 %dest, i64 12, i1 false)902  %3 = call i32 @use_nocapture(ptr noundef nocapture %src)903  call void @llvm.lifetime.end.p0(ptr nocapture %src)904  call void @llvm.lifetime.end.p0(ptr nocapture %dest)905  ret void906}907 908; TODO: merge allocas909; Tests that a memset that completely overwrites a stack value is a definition910; for the purposes of liveness analysis.911define void @memset_is_def() {912; CHECK-LABEL: define void @memset_is_def() {913; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4914; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4915; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])916; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])917; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4918; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])919; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)920; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])921; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[SRC]], i8 42, i64 12, i1 false)922; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])923; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])924; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])925; CHECK-NEXT:    ret void926;927  %src = alloca %struct.Foo, align 4928  %dest = alloca %struct.Foo, align 4929  call void @llvm.lifetime.start.p0(ptr nocapture %src)930  call void @llvm.lifetime.start.p0(ptr nocapture %dest)931  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src932  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)933  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)934  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)935  call void @llvm.memset.p0.i64(ptr align 4 %src, i8 42, i64 12, i1 false)936  %3 = call i32 @use_nocapture(ptr noundef nocapture %src)937  call void @llvm.lifetime.end.p0(ptr nocapture %src)938  call void @llvm.lifetime.end.p0(ptr nocapture %dest)939  ret void940}941 942; TODO: merge allocas943; Tests that a store that completely overwrites a stack value is a definition944; for the purposes of liveness analysis.945define void @store_is_def() {946; CHECK-LABEL: define void @store_is_def() {947; CHECK-NEXT:    [[SRC:%.*]] = alloca i32, align 4948; CHECK-NEXT:    [[DEST:%.*]] = alloca i32, align 4949; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])950; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])951; CHECK-NEXT:    store i32 42, ptr [[SRC]], align 4952; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])953; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4954; CHECK-NEXT:    store i32 [[TMP2]], ptr [[DEST]], align 4955; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])956; CHECK-NEXT:    store i32 64, ptr [[SRC]], align 4957; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])958; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])959; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])960; CHECK-NEXT:    ret void961;962  %src = alloca i32, align 4963  %dest = alloca i32, align 4964  call void @llvm.lifetime.start.p0(ptr nocapture %src)965  call void @llvm.lifetime.start.p0(ptr nocapture %dest)966  store i32 42, ptr %src967  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)968  %2 = load i32, ptr %src969  store i32 %2, ptr %dest970  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)971  store i32 64, ptr %src972  %4 = call i32 @use_nocapture(ptr noundef nocapture %src)973  call void @llvm.lifetime.end.p0(ptr nocapture %src)974  call void @llvm.lifetime.end.p0(ptr nocapture %dest)975  ret void976}977 978; TODO: merge src and dest, because any execution path doesn't cause conflicts.979; Tests that exists modref for both src/dest, but it never conflict on the execution.980define void @multi_bb_dataflow(i1 %b) {981; CHECK-LABEL: define void @multi_bb_dataflow982; CHECK-SAME: (i1 [[B:%.*]]) {983; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 4984; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 4985; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])986; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])987; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 4988; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])989; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)990; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]991; CHECK:       bb0:992; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])993; CHECK-NEXT:    br label [[BB2:%.*]]994; CHECK:       bb1:995; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])996; CHECK-NEXT:    br label [[BB2]]997; CHECK:       bb2:998; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])999; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1000; CHECK-NEXT:    ret void1001;1002  %src = alloca %struct.Foo, align 41003  %dest = alloca %struct.Foo, align 41004  call void @llvm.lifetime.start.p0(ptr nocapture %src)1005  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1006  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1007  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)1008  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1009  br i1 %b, label %bb0, label %bb11010 1011bb0:1012  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)1013  br label %bb21014 1015bb1:1016  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)1017  br label %bb21018 1019bb2:1020  call void @llvm.lifetime.end.p0(ptr nocapture %src)1021  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1022  ret void1023}1024 1025 1026; Optimization failures follow:1027 1028; Tests that a memcpy that doesn't completely overwrite a stack value is a use1029; for the purposes of liveness analysis, not a definition.1030define void @incomplete_memcpy() {1031; CHECK-LABEL: define void @incomplete_memcpy() {1032; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41033; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41034; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1035; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1036; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41037; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1038; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 11, i1 false)1039; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])1040; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1041; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1042; CHECK-NEXT:    ret void1043;1044  %src = alloca %struct.Foo, align 41045  %dest = alloca %struct.Foo, align 41046  call void @llvm.lifetime.start.p0(ptr nocapture %src)1047  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1048  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1049  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)1050  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 11, i1 false)1051  %2 = call i32 @use_nocapture(ptr noundef nocapture %dest)1052  call void @llvm.lifetime.end.p0(ptr nocapture %src)1053  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1054  ret void1055}1056 1057; Tests that a store that doesn't completely overwrite a stack value is a use1058; for the purposes of liveness analysis, not a definition.1059define void @incomplete_store() {1060; CHECK-LABEL: define void @incomplete_store() {1061; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41062; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41063; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1064; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1065; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41066; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1067; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SRC]], align 41068; CHECK-NEXT:    store i32 [[TMP2]], ptr [[DEST]], align 41069; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])1070; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1071; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1072; CHECK-NEXT:    ret void1073;1074  %src = alloca %struct.Foo, align 41075  %dest = alloca %struct.Foo, align 41076  call void @llvm.lifetime.start.p0(ptr nocapture %src)1077  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1078  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1079  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)1080  %2 = load i32, ptr %src1081  store i32 %2, ptr %dest1082  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)1083  call void @llvm.lifetime.end.p0(ptr nocapture %src)1084  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1085  ret void1086}1087 1088; Tests that dynamically-sized allocas are never merged.1089define void @dynamically_sized_alloca(i64 %i) {1090; CHECK-LABEL: define void @dynamically_sized_alloca1091; CHECK-SAME: (i64 [[I:%.*]]) {1092; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 [[I]], align 41093; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 [[I]], align 41094; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1095; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1096; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41097; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1098; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1099; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1100; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1101; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1102; CHECK-NEXT:    ret void1103;1104  %src = alloca i8, i64 %i, align 41105  %dest = alloca i8, i64 %i, align 41106  call void @llvm.lifetime.start.p0(ptr nocapture %src)1107  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1108  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1109  %1 = call i32 @use_nocapture(ptr nocapture %src)1110 1111  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1112 1113  %2 = call i32 @use_nocapture(ptr nocapture %dest)1114  call void @llvm.lifetime.end.p0(ptr nocapture %src)1115  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1116  ret void1117}1118 1119 1120; Tests that inalloca attributed allocas are never merged, to prevent stacksave/stackrestore handling.1121define void @inalloca() {1122; CHECK-LABEL: define void @inalloca() {1123; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41124; CHECK-NEXT:    [[DEST:%.*]] = alloca inalloca [[STRUCT_FOO]], align 41125; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1126; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1127; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41128; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1129; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1130; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1131; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1132; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1133; CHECK-NEXT:    ret void1134;1135  %src = alloca %struct.Foo, align 41136  %dest = alloca inalloca %struct.Foo, align 41137  call void @llvm.lifetime.start.p0(ptr nocapture %src)1138  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1139  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1140  %1 = call i32 @use_nocapture(ptr nocapture %src)1141 1142  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1143 1144  %2 = call i32 @use_nocapture(ptr nocapture %dest)1145  call void @llvm.lifetime.end.p0(ptr nocapture %src)1146  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1147  ret void1148}1149 1150; Tests that a memcpy with a dynamic size is never optimized.1151define void @dynamically_sized_memcpy(i64 %size) {1152; CHECK-LABEL: define void @dynamically_sized_memcpy1153; CHECK-SAME: (i64 [[SIZE:%.*]]) {1154; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41155; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41156; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1157; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1158; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41159; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1160; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 [[SIZE]], i1 false)1161; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1162; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1163; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1164; CHECK-NEXT:    ret void1165;1166  %src = alloca %struct.Foo, align 41167  %dest = alloca %struct.Foo, align 41168  call void @llvm.lifetime.start.p0(ptr nocapture %src)1169  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1170  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1171  %1 = call i32 @use_nocapture(ptr nocapture %src)1172 1173  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 %size, i1 false)1174 1175  %2 = call i32 @use_nocapture(ptr nocapture %dest)1176  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1177  call void @llvm.lifetime.end.p0(ptr nocapture %src)1178  ret void1179}1180 1181; Tests that allocas with different sizes aren't merged together.1182define void @mismatched_alloca_size() {1183; CHECK-LABEL: define void @mismatched_alloca_size() {1184; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 24, align 41185; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 12, align 41186; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1187; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1188; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41189; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1190; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1191; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1192; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1193; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1194; CHECK-NEXT:    ret void1195;1196  %src = alloca i8, i64 24, align 41197  %dest = alloca i8, i64 12, align 41198  call void @llvm.lifetime.start.p0(ptr nocapture %src)1199  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1200  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1201  %1 = call i32 @use_nocapture(ptr nocapture %src)1202 1203  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1204 1205  %2 = call i32 @use_nocapture(ptr nocapture %dest)1206  call void @llvm.lifetime.end.p0(ptr nocapture %src)1207  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1208  ret void1209}1210 1211; Tests that allocas with mismatched address spaces aren't combined.1212define void @mismatched_alloca_addrspace() {1213; CHECK-LABEL: define void @mismatched_alloca_addrspace() {1214; CHECK-NEXT:    [[SRC:%.*]] = alloca i8, i64 24, align 4, addrspace(1)1215; CHECK-NEXT:    [[DEST:%.*]] = alloca i8, i64 12, align 4, addrspace(2)1216; CHECK-NEXT:    call void @llvm.lifetime.start.p1(ptr addrspace(1) captures(none) [[SRC]])1217; CHECK-NEXT:    call void @llvm.lifetime.start.p2(ptr addrspace(2) captures(none) [[DEST]])1218; CHECK-NEXT:    store [[STRUCT_FOO:%.*]] { i32 10, i32 20, i32 30 }, ptr addrspace(1) [[SRC]], align 41219; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr addrspace(1) captures(none) [[SRC]])1220; CHECK-NEXT:    call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 [[DEST]], ptr addrspace(1) align 4 [[SRC]], i64 12, i1 false)1221; CHECK-NEXT:    call void @llvm.lifetime.end.p1(ptr addrspace(1) captures(none) [[SRC]])1222; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr addrspace(2) captures(none) [[DEST]])1223; CHECK-NEXT:    call void @llvm.lifetime.end.p2(ptr addrspace(2) captures(none) [[DEST]])1224; CHECK-NEXT:    ret void1225;1226  %src = alloca i8, i64 24, align 4, addrspace(1)1227  %dest = alloca i8, i64 12, align 4, addrspace(2)1228  call void @llvm.lifetime.start.p1(ptr addrspace(1) nocapture %src)1229  call void @llvm.lifetime.start.p2(ptr addrspace(2) nocapture %dest)1230  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr addrspace(1) %src1231  %1 = call i32 @use_nocapture(ptr addrspace(1) nocapture %src)1232 1233  call void @llvm.memcpy.p2.p1.i64(ptr addrspace(2) align 4 %dest, ptr addrspace(1) align 4 %src, i64 12, i1 false)1234 1235  call void @llvm.lifetime.end.p1(ptr addrspace(1) nocapture %src)1236  %2 = call i32 @use_nocapture(ptr addrspace(2) nocapture %dest)1237  call void @llvm.lifetime.end.p2(ptr addrspace(2) nocapture %dest)1238  ret void1239}1240 1241; Tests that volatile memcpys aren't removed.1242define void @volatile_memcpy() {1243; CHECK-LABEL: define void @volatile_memcpy() {1244; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41245; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41246; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1247; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1248; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41249; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1250; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 true)1251; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1252; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1253; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1254; CHECK-NEXT:    ret void1255;1256  %src = alloca %struct.Foo, align 41257  %dest = alloca %struct.Foo, align 41258  call void @llvm.lifetime.start.p0(ptr nocapture %src)1259  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1260  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1261  %1 = call i32 @use_nocapture(ptr nocapture %src)1262 1263  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 true)1264 1265  %2 = call i32 @use_nocapture(ptr nocapture %dest)1266  call void @llvm.lifetime.end.p0(ptr nocapture %src)1267  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1268  ret void1269}1270 1271; Tests that the optimization isn't performed when the destination is captured.1272define void @dest_captured() {1273; CHECK-LABEL: define void @dest_captured() {1274; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41275; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41276; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1277; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1278; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41279; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1280; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1281; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_maycapture(ptr [[DEST]])1282; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1283; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1284; CHECK-NEXT:    ret void1285;1286  %src = alloca %struct.Foo, align 41287  %dest = alloca %struct.Foo, align 41288  call void @llvm.lifetime.start.p0(ptr nocapture %src)1289  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1290  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1291 1292  %1 = call i32 @use_nocapture(ptr nocapture %src)1293 1294  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1295  %2 = call i32 @use_maycapture(ptr %dest)1296  call void @llvm.lifetime.end.p0(ptr nocapture %src)1297  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1298  ret void1299}1300 1301; Tests that the optimization isn't performed when the source is captured.1302define void @src_captured() {1303; CHECK-LABEL: define void @src_captured() {1304; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41305; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41306; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1307; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1308; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41309; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_maycapture(ptr [[SRC]])1310; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1311; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1312; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1313; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1314; CHECK-NEXT:    ret void1315;1316  %src = alloca %struct.Foo, align 41317  %dest = alloca %struct.Foo, align 41318  call void @llvm.lifetime.start.p0(ptr nocapture %src)1319  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1320  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1321  %1 = call i32 @use_maycapture(ptr %src)1322 1323  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1324 1325  %2 = call i32 @use_nocapture(ptr nocapture %dest)1326  call void @llvm.lifetime.end.p0(ptr nocapture %src)1327  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1328  ret void1329}1330 1331; Tests that failure if any modref exists before the copy,1332; Exactly ref seems safe because no mod say ref would be always undefined, but to make simple and conservative.1333define void @mod_ref_before_copy() {1334; CHECK-LABEL: define void @mod_ref_before_copy() {1335; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41336; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41337; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1338; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1339; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41340; CHECK-NEXT:    [[R:%.*]] = call i32 @use_readonly(ptr captures(none) [[DEST]])1341; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1342; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1343; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1344; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1345; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1346; CHECK-NEXT:    ret void1347;1348  %src = alloca %struct.Foo, align 41349  %dest = alloca %struct.Foo, align 41350  call void @llvm.lifetime.start.p0(ptr nocapture %src)1351  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1352  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1353  %r = call i32 @use_readonly(ptr nocapture %dest)1354  %1 = call i32 @use_nocapture(ptr nocapture %src)1355 1356  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1357 1358  call void @llvm.lifetime.end.p0(ptr nocapture %src)1359  %2 = call i32 @use_nocapture(ptr nocapture %dest)1360  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1361  ret void1362}1363 1364; Tests that failure because copy semantics will change if dest is replaced with src.1365define void @mod_dest_before_copy() {1366; CHECK-LABEL: define void @mod_dest_before_copy() {1367; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41368; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41369; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1370; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1371; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41372; CHECK-NEXT:    store i32 13, ptr [[DEST]], align 41373; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1374; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1375; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1376; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1377; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1378; CHECK-NEXT:    ret void1379;1380  %src = alloca %struct.Foo, align 41381  %dest = alloca %struct.Foo, align 41382  call void @llvm.lifetime.start.p0(ptr nocapture %src)1383  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1384  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1385  store i32 13, ptr %dest1386  %1 = call i32 @use_nocapture(ptr nocapture %src)1387 1388  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1389 1390  call void @llvm.lifetime.end.p0(ptr nocapture %src)1391  %2 = call i32 @use_nocapture(ptr nocapture %dest)1392  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1393  ret void1394}1395 1396define void @mod_src_before_store_after_load() {1397; CHECK-LABEL: define void @mod_src_before_store_after_load() {1398; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41399; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41400; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1401; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1402; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41403; CHECK-NEXT:    store i32 13, ptr [[DEST]], align 41404; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1405; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1406; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 41407; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1408; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1409; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1410; CHECK-NEXT:    ret void1411;1412  %src = alloca %struct.Foo, align 41413  %dest = alloca %struct.Foo, align 41414  call void @llvm.lifetime.start.p0(ptr nocapture %src)1415  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1416  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1417  store i32 13, ptr %dest1418  %1 = call i32 @use_nocapture(ptr nocapture %src)1419 1420  %src.val = load %struct.Foo, ptr %src1421  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src1422  store %struct.Foo %src.val, ptr %dest1423 1424  call void @llvm.lifetime.end.p0(ptr nocapture %src)1425  %2 = call i32 @use_nocapture(ptr nocapture %dest)1426  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1427  ret void1428}1429 1430; Tests that the optimization isn't performed,1431; when the source may have mod and dest may have ref after the full copy.1432define void @src_mod_dest_ref_after_copy() {1433; CHECK-LABEL: define void @src_mod_dest_ref_after_copy() {1434; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41435; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41436; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1437; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1438; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41439; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1440; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[SRC]], align 41441; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1442; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1443; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1444; CHECK-NEXT:    ret void1445;1446  %src = alloca %struct.Foo, align 41447  %dest = alloca %struct.Foo, align 41448  call void @llvm.lifetime.start.p0(ptr nocapture %src)1449  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1450  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1451 1452  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1453 1454  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %src1455  %1 = call i32 @use_nocapture(ptr nocapture %dest)1456  call void @llvm.lifetime.end.p0(ptr nocapture %src)1457  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1458  ret void1459}1460 1461; Tests that the optimization isn't performed.1462; Merging dest to src is no longer valid if conflicting Mod/Ref exist.1463define void @src_ref_dest_mod_after_copy() {1464; CHECK-LABEL: define void @src_ref_dest_mod_after_copy() {1465; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41466; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41467; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1468; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1469; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41470; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1471; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 13, i32 13, i32 13 }, ptr [[DEST]], align 41472; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1473; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1474; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1475; CHECK-NEXT:    ret void1476;1477  %src = alloca %struct.Foo, align 41478  %dest = alloca %struct.Foo, align 41479  call void @llvm.lifetime.start.p0(ptr nocapture %src)1480  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1481  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1482 1483  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1484 1485  store %struct.Foo { i32 13, i32 13, i32 13 }, ptr %dest1486  %1 = call i32 @use_nocapture(ptr nocapture %src)1487  call void @llvm.lifetime.end.p0(ptr nocapture %src)1488  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1489  ret void1490}1491 1492; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks1493define void @dest_alias_mod_before_copy() {1494; CHECK-LABEL: define void @dest_alias_mod_before_copy() {1495; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41496; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41497; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1498; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1499; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41500; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 11501; CHECK-NEXT:    store i32 13, ptr [[DEST_ALIAS]], align 41502; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1503; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1504; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1505; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1506; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1507; CHECK-NEXT:    ret void1508;1509  %src = alloca %struct.Foo, align 41510  %dest = alloca %struct.Foo, align 41511  call void @llvm.lifetime.start.p0(ptr nocapture %src)1512  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1513  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1514  %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 11515  store i32 13, ptr %dest.alias1516  %1 = call i32 @use_nocapture(ptr nocapture %src)1517 1518  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1519 1520  %2 = call i32 @use_nocapture(ptr nocapture %dest)1521  call void @llvm.lifetime.end.p0(ptr nocapture %src)1522  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1523  ret void1524}1525 1526; Tests that failure because alloca is modified through aliases, which requires recursive user ModRefChecks1527define void @alias_src_ref_dest_mod_after_copy() {1528; CHECK-LABEL: define void @alias_src_ref_dest_mod_after_copy() {1529; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41530; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41531; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1532; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1533; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41534; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1535; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1536; CHECK-NEXT:    [[DEST_ALIAS:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[DEST]], i64 0, i32 11537; CHECK-NEXT:    store i32 13, ptr [[DEST_ALIAS]], align 41538; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[SRC]])1539; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1540; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1541; CHECK-NEXT:    ret void1542;1543  %src = alloca %struct.Foo, align 41544  %dest = alloca %struct.Foo, align 41545  call void @llvm.lifetime.start.p0(ptr nocapture %src)1546  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1547  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1548  %1 = call i32 @use_nocapture(ptr nocapture %src)1549 1550  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1551 1552  %dest.alias = getelementptr inbounds %struct.Foo, ptr %dest, i64 0, i32 11553  store i32 13, ptr %dest.alias1554  %2 = call i32 @use_nocapture(ptr nocapture %src)1555  call void @llvm.lifetime.end.p0(ptr nocapture %src)1556  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1557  ret void1558}1559 1560; Tests that the optimization isn't performed when the source and destination1561; have mod ref conflict on bb2.1562define void @multi_bb_dataflow_conflict(i1 %b) {1563; CHECK-LABEL: define void @multi_bb_dataflow_conflict1564; CHECK-SAME: (i1 [[B:%.*]]) {1565; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41566; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 41567; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1568; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1569; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41570; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1571; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DEST]], ptr align 4 [[SRC]], i64 12, i1 false)1572; CHECK-NEXT:    br i1 [[B]], label [[BB0:%.*]], label [[BB1:%.*]]1573; CHECK:       bb0:1574; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1575; CHECK-NEXT:    br label [[BB2:%.*]]1576; CHECK:       bb1:1577; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])1578; CHECK-NEXT:    br label [[BB2]]1579; CHECK:       bb2:1580; CHECK-NEXT:    [[TMP4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])1581; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[SRC]])1582; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr captures(none) [[DEST]])1583; CHECK-NEXT:    ret void1584;1585  %src = alloca %struct.Foo, align 41586  %dest = alloca %struct.Foo, align 41587  call void @llvm.lifetime.start.p0(ptr nocapture %src)1588  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1589  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1590  %1 = call i32 @use_nocapture(ptr noundef nocapture %src)1591  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1592  br i1 %b, label %bb0, label %bb11593 1594bb0:1595  %2 = call i32 @use_nocapture(ptr noundef nocapture %src)1596  br label %bb21597 1598bb1:1599  %3 = call i32 @use_nocapture(ptr noundef nocapture %dest)1600  br label %bb21601 1602bb2:1603  %4 = call i32 @use_nocapture(ptr noundef nocapture %dest)1604  call void @llvm.lifetime.end.p0(ptr nocapture %src)1605  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1606  ret void1607}1608 1609; Tests that failure because after copy mod could be before copy on loop.1610define void @multi_bb_loop_dest_mod_before_copy(i32 %n) {1611; CHECK-LABEL: define void @multi_bb_loop_dest_mod_before_copy1612; CHECK-SAME: (i32 [[N:%.*]]) {1613; CHECK-NEXT:  entry:1614; CHECK-NEXT:    [[NLT1:%.*]] = icmp slt i32 [[N]], 11615; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 81616; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO]], align 81617; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[SRC]])1618; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr captures(none) [[DEST]])1619; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 0, i32 1, i32 42 }, ptr [[SRC]], align 41620; CHECK-NEXT:    br i1 [[NLT1]], label [[LOOP_EXIT:%.*]], label [[LOOP_BODY:%.*]]1621; CHECK:       loop_body:1622; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[NEW_I:%.*]], [[LOOP_BODY]] ], [ 1, [[ENTRY:%.*]] ]1623; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DEST]], ptr align 8 [[SRC]], i64 12, i1 false)1624; CHECK-NEXT:    [[NEW_I]] = add i32 [[I]], 11625; CHECK-NEXT:    store i32 [[NEW_I]], ptr [[DEST]], align 41626; CHECK-NEXT:    [[IGTN:%.*]] = icmp sgt i32 [[NEW_I]], [[N]]1627; CHECK-NEXT:    br i1 [[IGTN]], label [[LOOP_EXIT]], label [[LOOP_BODY]]1628; CHECK:       loop_exit:1629; CHECK-NEXT:    ret void1630;1631entry:1632  %nlt1 = icmp slt i32 %n, 11633  %src = alloca %struct.Foo, align 81634  %dest = alloca %struct.Foo, align 81635  call void @llvm.lifetime.start.p0(ptr nocapture %src)1636  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1637  store %struct.Foo { i32 0, i32 1, i32 42 }, ptr %src1638  br i1 %nlt1, label %loop_exit, label %loop_body1639 1640loop_body:1641  %i = phi i32 [ %new_i, %loop_body ], [ 1, %entry ]1642  call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dest, ptr align 8 %src, i64 12, i1 false)1643  %new_i = add i32 %i, 11644  store i32 %new_i, ptr %dest1645  %igtn = icmp sgt i32 %new_i, %n1646  br i1 %igtn, label %loop_exit, label %loop_body1647 1648loop_exit:1649  ret void1650}1651 1652; Tests that partial-sized lifetimes are not inhibiting the optimizer1653define void @partial_lifetime() {1654; CHECK-LABEL: define void @partial_lifetime() {1655; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41656; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[DEST]], align 41657; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1658; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @use_nocapture(ptr captures(none) [[DEST]])1659; CHECK-NEXT:    ret void1660;1661  %src = alloca %struct.Foo, align 41662  %dest = alloca %struct.Foo, align 41663  call void @llvm.lifetime.start.p0(ptr nocapture %src)1664  call void @llvm.lifetime.start.p0(ptr nocapture %dest)1665  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1666  %1 = call i32 @use_nocapture(ptr nocapture %src)1667 1668  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 12, i1 false)1669 1670  call void @llvm.lifetime.end.p0(ptr nocapture %src)1671  %2 = call i32 @use_nocapture(ptr nocapture %dest)1672  call void @llvm.lifetime.end.p0(ptr nocapture %src)1673  call void @llvm.lifetime.end.p0(ptr nocapture %dest)1674  ret void1675}1676 1677; Do not merge or crash if the different block user comes first.1678define void @crash_store63851(i1 %b) {1679; CHECK-LABEL: define void @crash_store638511680; CHECK-SAME: (i1 [[B:%.*]]) {1681; CHECK-NEXT:    [[DEST:%.*]] = alloca [[STRUCT_FOO:%.*]], align 81682; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO]], align 81683; CHECK-NEXT:    store i32 0, ptr [[DEST]], align 41684; CHECK-NEXT:    br i1 [[B]], label [[THEN:%.*]], label [[ELSE:%.*]]1685; CHECK:       then:1686; CHECK-NEXT:    [[T:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1687; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[DEST]], ptr [[SRC]], i64 12, i1 false)1688; CHECK-NEXT:    [[T3:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[SRC]])1689; CHECK-NEXT:    [[T4:%.*]] = call i32 @use_nocapture(ptr noundef captures(none) [[DEST]])1690; CHECK-NEXT:    br label [[ELSE]]1691; CHECK:       else:1692; CHECK-NEXT:    ret void1693;1694  %dest = alloca %struct.Foo, align 81695  %src = alloca %struct.Foo, align 81696  store i32 0, ptr %dest, align 41697  br i1 %b, label %then, label %else1698 1699then:                                             ; preds = %entry1700  %t = call i32 @use_nocapture(ptr nocapture noundef %src)1701  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 12, i1 false)1702  %t3 = call i32 @use_nocapture(ptr nocapture noundef %src)1703  %t4 = call i32 @use_nocapture(ptr nocapture noundef %dest)1704  br label %else1705 1706else:                                             ; preds = %then, %entry1707  ret void1708 1709  uselistorder ptr %dest, { 1, 2, 0 }1710}1711 1712declare ptr @captures_ret_only(ptr captures(ret: address, provenance))1713 1714define i32 @test_ret_only_capture() {1715; CHECK-LABEL: define i32 @test_ret_only_capture() {1716; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 41717; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 41718; CHECK-NEXT:    store i32 0, ptr [[A]], align 41719; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[B]], ptr [[A]], i64 4, i1 false)1720; CHECK-NEXT:    call void @captures_ret_only(ptr [[B]])1721; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[A]], align 41722; CHECK-NEXT:    ret i32 [[V]]1723;1724  %a = alloca i321725  %b = alloca i321726  store i32 0, ptr %a1727  call void @llvm.memcpy(ptr %b, ptr %a, i64 4, i1 false)1728  call void @captures_ret_only(ptr %b)1729  %v = load i32, ptr %a1730  ret i32 %v1731}1732 1733declare ptr @captures_address_only(ptr captures(address))1734 1735; Can transform: Only one address captured.1736define void @test_captures_address_captures_none() {1737; CHECK-LABEL: define void @test_captures_address_captures_none() {1738; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41739; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41740; CHECK-NEXT:    call void @captures_address_only(ptr [[SRC]])1741; CHECK-NEXT:    call void @use_nocapture(ptr [[SRC]])1742; CHECK-NEXT:    ret void1743;1744  %src = alloca %struct.Foo, align 41745  %dst = alloca %struct.Foo, align 41746  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1747  call void @captures_address_only(ptr %src)1748  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dst, ptr align 4 %src, i64 12, i1 false)1749  call void @use_nocapture(ptr %dst)1750  ret void1751}1752 1753; Can transform: Only one address captured.1754define void @test_captures_none_and_captures_address() {1755; CHECK-LABEL: define void @test_captures_none_and_captures_address() {1756; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41757; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41758; CHECK-NEXT:    call void @use_nocapture(ptr [[SRC]])1759; CHECK-NEXT:    call void @captures_address_only(ptr [[SRC]])1760; CHECK-NEXT:    ret void1761;1762  %src = alloca %struct.Foo, align 41763  %dst = alloca %struct.Foo, align 41764  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1765  call void @use_nocapture(ptr %src)1766  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dst, ptr align 4 %src, i64 12, i1 false)1767  call void @captures_address_only(ptr %dst)1768  ret void1769}1770 1771; Cannot transform: Both addresses captured.1772define void @test_captures_address_and_captures_address() {1773; CHECK-LABEL: define void @test_captures_address_and_captures_address() {1774; CHECK-NEXT:    [[SRC:%.*]] = alloca [[STRUCT_FOO:%.*]], align 41775; CHECK-NEXT:    [[DST:%.*]] = alloca [[STRUCT_FOO]], align 41776; CHECK-NEXT:    store [[STRUCT_FOO]] { i32 10, i32 20, i32 30 }, ptr [[SRC]], align 41777; CHECK-NEXT:    call void @captures_address_only(ptr [[SRC]])1778; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DST]], ptr align 4 [[SRC]], i64 12, i1 false)1779; CHECK-NEXT:    call void @captures_address_only(ptr [[DST]])1780; CHECK-NEXT:    ret void1781;1782  %src = alloca %struct.Foo, align 41783  %dst = alloca %struct.Foo, align 41784  store %struct.Foo { i32 10, i32 20, i32 30 }, ptr %src1785  call void @captures_address_only(ptr %src)1786  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dst, ptr align 4 %src, i64 12, i1 false)1787  call void @captures_address_only(ptr %dst)1788  ret void1789}1790