brintos

brintos / llvm-project-archived public Read only

0
0
Text · 37.4 KiB · 89d8eb1 Raw
935 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=memcpyopt,dse -S -verify-memoryssa | FileCheck %s3 4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"5target triple = "i686-apple-darwin9"6 7%0 = type { x86_fp80, x86_fp80 }8%1 = type { i32, i32 }9 10@C = external constant [0 x i8]11 12declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) nocapture, ptr nocapture, i64, i1) nounwind13declare void @llvm.memcpy.p0.p1.i64(ptr nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind14declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind15declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind16declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind17declare void @llvm.memcpy.inline.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind18declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind19 20; Check that one of the memcpy's are removed.21;; FIXME: PR 8643 We should be able to eliminate the last memcpy here.22define void @test1(ptr sret(%0)  %agg.result, x86_fp80 %z.0, x86_fp80 %z.1) nounwind  {23; CHECK-LABEL: @test1(24; CHECK-NEXT:  entry:25; CHECK-NEXT:    [[TMP2:%.*]] = alloca [[TMP0:%.*]], align 1626; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [[TMP0]], align 1627; CHECK-NEXT:    [[TMP5:%.*]] = fsub x86_fp80 0xK80000000000000000000, [[Z_1:%.*]]28; CHECK-NEXT:    call void @ccoshl(ptr sret([[TMP0]]) [[TMP2]], x86_fp80 [[TMP5]], x86_fp80 [[Z_0:%.*]]) #[[ATTR2:[0-9]+]]29; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[AGG_RESULT:%.*]], ptr align 16 [[TMP2]], i32 32, i1 false)30; CHECK-NEXT:    ret void31;32entry:33  %tmp2 = alloca %034  %memtmp = alloca %0, align 1635  %tmp5 = fsub x86_fp80 0xK80000000000000000000, %z.136  call void @ccoshl(ptr sret(%0) %memtmp, x86_fp80 %tmp5, x86_fp80 %z.0) nounwind37  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %tmp2, ptr align 16 %memtmp, i32 32, i1 false)38  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 16 %tmp2, i32 32, i1 false)39  ret void40}41 42declare void @ccoshl(ptr nocapture sret(%0), x86_fp80, x86_fp80) nounwind43 44 45; The intermediate alloca and one of the memcpy's should be eliminated, the46; other should be related with a memmove.47define void @test2(ptr %P, ptr %Q) nounwind  {48; CHECK-LABEL: @test2(49; CHECK-NEXT:    call void @llvm.memmove.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)50; CHECK-NEXT:    ret void51;52  %memtmp = alloca %0, align 1653  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)54  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)55  ret void56 57}58 59; The intermediate alloca and one of the memcpy's should be eliminated, the60; other should be related with a memcpy.61define void @test2_constant(ptr %Q) nounwind  {62; CHECK-LABEL: @test2_constant(63; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 @C, i32 32, i1 false)64; CHECK-NEXT:    ret void65;66  %memtmp = alloca %0, align 1667  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 @C, i32 32, i1 false)68  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)69  ret void70 71}72 73; The intermediate alloca and one of the memcpy's should be eliminated, the74; other should be related with a memcpy.75define void @test2_memcpy(ptr noalias %P, ptr noalias %Q) nounwind  {76; CHECK-LABEL: @test2_memcpy(77; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)78; CHECK-NEXT:    ret void79;80  %memtmp = alloca %0, align 1681  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)82  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)83  ret void84 85}86 87; Same as @test2_memcpy, but the remaining memcpy should remain non-inline even88; if the one eliminated was inline.89define void @test3_memcpy(ptr noalias %P, ptr noalias %Q) nounwind  {90; CHECK-LABEL: @test3_memcpy(91; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)92; CHECK-NEXT:    ret void93;94  %memtmp = alloca %0, align 1695  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)96  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)97  ret void98 99}100 101; Same as @test2_memcpy, but the remaining memcpy should remain inline even102; if the one eliminated was not inline.103define void @test4_memcpy(ptr noalias %P, ptr noalias %Q) nounwind  {104; CHECK-LABEL: @test4_memcpy(105; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)106; CHECK-NEXT:    ret void107;108  %memtmp = alloca %0, align 16109  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)110  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)111  ret void112 113}114 115; Same as @test2_memcpy, and the inline-ness should be preserved.116define void @test5_memcpy(ptr noalias %P, ptr noalias %Q) nounwind  {117; CHECK-LABEL: @test5_memcpy(118; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)119; CHECK-NEXT:    ret void120;121  %memtmp = alloca %0, align 16122  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)123  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)124  ret void125 126}127 128; Similar to test5_memcpy, but without noalias; check that memcpy.inline is not folded into memmove.129define void @test6_memcpy(ptr %src, ptr %dest) nounwind {130; CHECK-LABEL: @test6_memcpy(131; CHECK-NEXT:    [[TMP:%.*]] = alloca [16 x i8], align 1132; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SRC:%.*]], i32 16, i1 false)133; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[DEST:%.*]], ptr align 1 [[TMP]], i32 16, i1 false)134; CHECK-NEXT:    ret void135;136  %tmp = alloca [16 x i8], align 1137  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)138  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)139  ret void140}141 142; When forwarding to memcpy(arg+1, arg+1), we don't need to create this memcpy.143define void @test6_memcpy_forward_back(ptr %arg) nounwind {144; CHECK-LABEL: @test6_memcpy_forward_back(145; CHECK-NEXT:    [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1146; CHECK-NEXT:    ret void147;148  %tmp = alloca [16 x i8], align 1149  %src = getelementptr inbounds i8, ptr %arg, i64 1150  %dest = getelementptr inbounds i8, ptr %arg, i64 1151  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)152  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)153  ret void154}155 156; We have to retain this `memcpy(arg+2, arg+1)` forwarding.157define void @test6_memcpy_forward_not_back(ptr %arg) nounwind {158; CHECK-LABEL: @test6_memcpy_forward_not_back(159; CHECK-NEXT:    [[TMP:%.*]] = alloca [16 x i8], align 1160; CHECK-NEXT:    [[SRC:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1161; CHECK-NEXT:    [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2162; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SRC]], i32 16, i1 false)163; CHECK-NEXT:    call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 [[DEST]], ptr align 1 [[TMP]], i32 16, i1 false)164; CHECK-NEXT:    ret void165;166  %tmp = alloca [16 x i8], align 1167  %src = getelementptr inbounds i8, ptr %arg, i64 1168  %dest = getelementptr inbounds i8, ptr %arg, i64 2169  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %tmp, ptr align 1 %src, i32 16, i1 false)170  call void @llvm.memcpy.inline.p0.p0.i32(ptr align 1 %dest, ptr align 1 %tmp, i32 16, i1 false)171  ret void172}173 174@x = external global %0175 176define void @test3(ptr noalias writable sret(%0) %agg.result) nounwind  {177; CHECK-LABEL: @test3(178; CHECK-NEXT:    [[X_0:%.*]] = alloca [[TMP0:%.*]], align 16179; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[AGG_RESULT:%.*]], ptr align 16 @x, i32 32, i1 false)180; CHECK-NEXT:    ret void181;182  %x.0 = alloca %0183  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x.0, ptr align 16 @x, i32 32, i1 false)184  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %agg.result, ptr align 16 %x.0, i32 32, i1 false)185  ret void186}187 188 189; PR8644190define void @test4(ptr %P) {191; CHECK-LABEL: @test4(192; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P:%.*]])193; CHECK-NEXT:    ret void194;195  %A = alloca %1196  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 %P, i64 8, i1 false)197  call void @test4a(ptr align 1 byval(i8) %A)198  ret void199}200 201; Make sure we don't remove the memcpy if the source address space doesn't match the byval argument202define void @test4_addrspace(ptr addrspace(1) %P) {203; CHECK-LABEL: @test4_addrspace(204; CHECK-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8205; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr align 4 [[A1]], ptr addrspace(1) align 4 [[P:%.*]], i64 8, i1 false)206; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[A1]])207; CHECK-NEXT:    ret void208;209  %a1 = alloca %1210  call void @llvm.memcpy.p0.p1.i64(ptr align 4 %a1, ptr addrspace(1) align 4 %P, i64 8, i1 false)211  call void @test4a(ptr align 1 byval(i8) %a1)212  ret void213}214 215define void @test4_write_between(ptr %P) {216; CHECK-LABEL: @test4_write_between(217; CHECK-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8218; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A1]], ptr align 4 [[P:%.*]], i64 8, i1 false)219; CHECK-NEXT:    store i8 0, ptr [[A1]], align 1220; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[A1]])221; CHECK-NEXT:    ret void222;223  %a1 = alloca %1224  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)225  store i8 0, ptr %a1226  call void @test4a(ptr align 1 byval(i8) %a1)227  ret void228}229 230define i8 @test4_read_between(ptr %P) {231; CHECK-LABEL: @test4_read_between(232; CHECK-NEXT:    [[A1:%.*]] = alloca [[TMP1:%.*]], align 8233; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A1]], ptr align 4 [[P:%.*]], i64 8, i1 false)234; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[A1]], align 1235; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P]])236; CHECK-NEXT:    ret i8 [[X]]237;238  %a1 = alloca %1239  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)240  %x = load i8, ptr %a1241  call void @test4a(ptr align 1 byval(i8) %a1)242  ret i8 %x243}244 245define void @test4_non_local(ptr %P, i1 %c) {246; CHECK-LABEL: @test4_non_local(247; CHECK-NEXT:    br i1 [[C:%.*]], label [[CALL:%.*]], label [[EXIT:%.*]]248; CHECK:       call:249; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P:%.*]])250; CHECK-NEXT:    br label [[EXIT]]251; CHECK:       exit:252; CHECK-NEXT:    ret void253;254  %a1 = alloca %1255  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false)256  br i1 %c, label %call, label %exit257 258call:259  call void @test4a(ptr align 1 byval(i8) %a1)260  br label %exit261 262exit:263  ret void264}265 266declare void @test4a(ptr align 1 byval(i8))267 268%struct.S = type { i128, [4 x i8]}269 270@sS = external global %struct.S, align 16271 272declare void @test5a(ptr align 16 byval(%struct.S)) nounwind ssp273 274 275; rdar://8713376 - This memcpy can't be eliminated.276define i32 @test5(i32 %x) nounwind ssp {277; CHECK-LABEL: @test5(278; CHECK-NEXT:  entry:279; CHECK-NEXT:    [[Y:%.*]] = alloca [[STRUCT_S:%.*]], align 16280; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[Y]], ptr align 16 @sS, i64 32, i1 false)281; CHECK-NEXT:    [[A:%.*]] = getelementptr [[STRUCT_S]], ptr [[Y]], i64 0, i32 1, i64 0282; CHECK-NEXT:    store i8 4, ptr [[A]], align 1283; CHECK-NEXT:    call void @test5a(ptr byval([[STRUCT_S]]) align 16 [[Y]])284; CHECK-NEXT:    ret i32 0285;286entry:287  %y = alloca %struct.S, align 16288  call void @llvm.memcpy.p0.p0.i64(ptr align 16 %y, ptr align 16 @sS, i64 32, i1 false)289  %a = getelementptr %struct.S, ptr %y, i64 0, i32 1, i64 0290  store i8 4, ptr %a291  call void @test5a(ptr align 16 byval(%struct.S) %y)292  ret i32 0293}294 295;; Noop memcpy should be zapped.296define void @test6(ptr %P) {297; CHECK-LABEL: @test6(298; CHECK-NEXT:    ret void299;300  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %P, ptr align 4 %P, i64 8, i1 false)301  ret void302}303 304 305; PR9794 - Should forward memcpy into byval argument even though the memcpy306; isn't itself 8 byte aligned.307%struct.p = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }308 309define i32 @test7(ptr nocapture align 8 byval(%struct.p) %q) nounwind ssp {310; CHECK-LABEL: @test7(311; CHECK-NEXT:  entry:312; CHECK-NEXT:    [[CALL:%.*]] = call i32 @g(ptr byval([[STRUCT_P:%.*]]) align 8 [[Q:%.*]]) #[[ATTR2]]313; CHECK-NEXT:    ret i32 [[CALL]]314;315entry:316  %agg.tmp = alloca %struct.p, align 4317  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %q, i64 48, i1 false)318  %call = call i32 @g(ptr align 8 byval(%struct.p) %agg.tmp) nounwind319  ret i32 %call320}321 322declare i32 @g(ptr align 8 byval(%struct.p))323 324 325; PR11142 - When looking for a memcpy-memcpy dependency, don't get stuck on326; instructions between the memcpy's that only affect the destination pointer.327@test8.str = internal constant [7 x i8] c"ABCDEF\00"328 329define void @test8() {330; CHECK-LABEL: @test8(331; CHECK-NEXT:    ret void332;333  %A = tail call ptr @malloc(i32 10)334  %B = getelementptr inbounds i8, ptr %A, i64 2335  tail call void @llvm.memcpy.p0.p0.i32(ptr %B, ptr @test8.str, i32 7, i1 false)336  %C = tail call ptr @malloc(i32 10)337  %D = getelementptr inbounds i8, ptr %C, i64 2338  tail call void @llvm.memcpy.p0.p0.i32(ptr %D, ptr %B, i32 7, i1 false)339  ret void340}341 342declare noalias ptr @malloc(i32) willreturn allockind("alloc,uninitialized") allocsize(0)343 344; rdar://11341081345%struct.big = type { [50 x i32] }346 347define void @test9_addrspacecast() nounwind ssp uwtable {348; CHECK-LABEL: @test9_addrspacecast(349; CHECK-NEXT:  entry:350; CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4351; CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4352; CHECK-NEXT:    call void @f1(ptr sret([[STRUCT_BIG]]) [[B]])353; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast ptr [[B]] to ptr addrspace(1)354; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr [[TMP]] to ptr addrspace(1)355; CHECK-NEXT:    call void @f2(ptr [[B]])356; CHECK-NEXT:    ret void357;358entry:359  %b = alloca %struct.big, align 4360  %tmp = alloca %struct.big, align 4361  call void @f1(ptr sret(%struct.big) %tmp)362  %0 = addrspacecast ptr %b to ptr addrspace(1)363  %1 = addrspacecast ptr %tmp to ptr addrspace(1)364  call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 4 %0, ptr addrspace(1) align 4 %1, i64 200, i1 false)365  call void @f2(ptr %b)366  ret void367}368 369define void @test9() nounwind ssp uwtable {370; CHECK-LABEL: @test9(371; CHECK-NEXT:  entry:372; CHECK-NEXT:    [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4373; CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4374; CHECK-NEXT:    call void @f1(ptr sret([[STRUCT_BIG]]) [[B]])375; CHECK-NEXT:    call void @f2(ptr [[B]])376; CHECK-NEXT:    ret void377;378entry:379  %b = alloca %struct.big, align 4380  %tmp = alloca %struct.big, align 4381  call void @f1(ptr sret(%struct.big) %tmp)382  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %b, ptr align 4 %tmp, i64 200, i1 false)383  call void @f2(ptr %b)384  ret void385}386 387; rdar://14073661.388; Test10 triggered assertion when the compiler try to get the size of the389; opaque type of *x, where the x is the formal argument with attribute 'sret'.390 391%opaque = type opaque392declare void @foo(ptr noalias nocapture)393 394define void @test10(ptr noalias nocapture sret(%opaque) %x, i32 %y) {395; CHECK-LABEL: @test10(396; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4397; CHECK-NEXT:    store i32 [[Y:%.*]], ptr [[A]], align 4398; CHECK-NEXT:    call void @foo(ptr noalias captures(none) [[A]])399; CHECK-NEXT:    [[C:%.*]] = load i32, ptr [[A]], align 4400; CHECK-NEXT:    store i32 [[C]], ptr [[X:%.*]], align 4401; CHECK-NEXT:    ret void402;403  %a = alloca i32, align 4404  store i32 %y, ptr %a405  call void @foo(ptr noalias nocapture %a)406  %c = load i32, ptr %a407  store i32 %c, ptr %x408  ret void409}410 411; don't create new addressspacecasts when we don't know they're safe for the target412define void @test11(ptr addrspace(1) nocapture dereferenceable(80) %P) {413; CHECK-LABEL: @test11(414; CHECK-NEXT:    call void @llvm.memset.p1.i64(ptr addrspace(1) align 4 [[P:%.*]], i8 0, i64 80, i1 false)415; CHECK-NEXT:    ret void416;417  %A = alloca [20 x i32], align 4418  call void @llvm.memset.p0.i64(ptr align 4 %A, i8 0, i64 80, i1 false)419  call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 %P, ptr align 4 %A, i64 80, i1 false)420  ret void421}422 423declare void @f1(ptr nocapture sret(%struct.big))424declare void @f2(ptr)425 426declare void @f(ptr)427declare void @f_byval(ptr byval(i32))428declare void @f_full_readonly(ptr nocapture noalias readonly)429 430define void @immut_param(ptr align 4 noalias %val) {431; CHECK-LABEL: @immut_param(432; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL:%.*]])433; CHECK-NEXT:    ret void434;435  %val1 = alloca i8, align 4436  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)437  call void @f(ptr align 4 nocapture noalias readonly %val1)438  ret void439}440 441; Can't remove memcpy because dest may be captured.442define void @immut_param_maycapture(ptr align 4 noalias %val) {443; CHECK-LABEL: @immut_param_maycapture(444; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4445; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)446; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 [[VAL1]])447; CHECK-NEXT:    ret void448;449  %val1 = alloca i8, align 4450  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)451  call void @f(ptr align 4 noalias readonly %val1)452  ret void453}454 455; Can't remove memcpy because dest may be aliased.456define void @immut_param_mayalias(ptr align 4 noalias %val) {457; CHECK-LABEL: @immut_param_mayalias(458; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4459; CHECK-NEXT:    call void @f(ptr [[VAL1]])460; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)461; CHECK-NEXT:    call void @f(ptr readonly align 4 captures(none) [[VAL1]])462; CHECK-NEXT:    ret void463;464  %val1 = alloca i8, align 4465  call void @f(ptr %val1) ; escape466  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)467  call void @f(ptr align 4 nocapture readonly %val1)468  ret void469}470 471; Can remove memcpy because alloca does not escape, so lack of noalias on the472; argument doesn't matter.473define void @immut_param_unescaped_alloca(ptr align 4 noalias %val) {474; CHECK-LABEL: @immut_param_unescaped_alloca(475; CHECK-NEXT:    call void @f(ptr readonly align 4 captures(none) [[VAL:%.*]])476; CHECK-NEXT:    ret void477;478  %val1 = alloca i8, align 4479  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)480  call void @f(ptr align 4 nocapture readonly %val1)481  ret void482}483 484; Can remove memcpy because the function is argmem: read, so there cannot be485; a write to the escaped pointer.486define void @immut_param_memory_argmem_read(ptr align 4 noalias %val) {487; CHECK-LABEL: @immut_param_memory_argmem_read(488; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4489; CHECK-NEXT:    call void @f(ptr [[VAL1]])490; CHECK-NEXT:    call void @f(ptr readonly align 4 captures(none) [[VAL:%.*]]) #[[ATTR6:[0-9]+]]491; CHECK-NEXT:    ret void492;493  %val1 = alloca i8, align 4494  call void @f(ptr %val1) ; escape495  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)496  call void @f(ptr align 4 nocapture readonly %val1) memory(argmem: read)497  ret void498}499 500; Can remove memcpy because the function is argmem: read, so there cannot be501; a write to the escaped pointer. The readonly on the argument is redundant in502; this case.503define void @immut_param_memory_argmem_read_no_readonly(ptr align 4 noalias %val) {504; CHECK-LABEL: @immut_param_memory_argmem_read_no_readonly(505; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4506; CHECK-NEXT:    call void @f(ptr [[VAL1]])507; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)508; CHECK-NEXT:    call void @f(ptr align 4 captures(none) [[VAL1]]) #[[ATTR6]]509; CHECK-NEXT:    ret void510;511  %val1 = alloca i8, align 4512  call void @f(ptr %val1) ; escape513  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)514  call void @f(ptr align 4 nocapture %val1) memory(argmem: read)515  ret void516}517 518; Can't remove memcpy because dest may be written.519define void @immut_param_maywrite(ptr align 4 noalias %val) {520; CHECK-LABEL: @immut_param_maywrite(521; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4522; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)523; CHECK-NEXT:    call void @f(ptr noalias align 4 captures(none) [[VAL1]])524; CHECK-NEXT:    ret void525;526  %val1 = alloca i8, align 4527  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)528  call void @f(ptr align 4 nocapture noalias %val1)529  ret void530}531 532define void @immut_param_readonly(ptr align 4 noalias %val) {533; CHECK-LABEL: @immut_param_readonly(534; CHECK-NEXT:    call void @f_full_readonly(ptr align 4 [[VAL:%.*]])535; CHECK-NEXT:    ret void536;537  %val1 = alloca i8, align 4538  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)539  call void @f_full_readonly(ptr align 4 %val1)540  ret void541}542 543define void @immut_param_no_align(ptr align 4 noalias %val) {544; CHECK-LABEL: @immut_param_no_align(545; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL:%.*]])546; CHECK-NEXT:    ret void547;548  %val1 = alloca i8, align 4549  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)550  call void @f(ptr nocapture noalias readonly %val1)551  ret void552}553 554@gp = external constant [0 x i8]555; Can't remove memcpy because dest is not unescaped alloca, so cpying is meaningfull.556define void @immut_param_global(ptr align 4 noalias %val) {557; CHECK-LABEL: @immut_param_global(558; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 @gp, ptr align 4 [[VAL:%.*]], i64 1, i1 false)559; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) @gp)560; CHECK-NEXT:    ret void561;562  call void @llvm.memcpy.p0.p0.i64(ptr align 4 @gp, ptr align 4 %val, i64 1, i1 false)563  call void @f(ptr nocapture align 4 noalias readonly @gp)564  ret void565}566 567; Can't remove memcpy for VLA because of unknown size and alignment.568define void @immut_param_vla(ptr align 4 noalias %val, i64 %n) {569; CHECK-LABEL: @immut_param_vla(570; CHECK-NEXT:    [[VAL1:%.*]] = alloca ptr, i64 [[N:%.*]], align 4571; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)572; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])573; CHECK-NEXT:    ret void574;575  %val1 = alloca ptr, i64 %n576  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)577  call void @f(ptr nocapture align 4 noalias readonly %val1)578  ret void579}580 581; Can't remove memcpy for scalable vector, because of memcpy size sufficiency is unknown582define void @immut_param_scalable_vector(ptr align 4 noalias %val) {583; CHECK-LABEL: @immut_param_scalable_vector(584; CHECK-NEXT:    [[VAL1:%.*]] = alloca <vscale x 2 x i32>, align 8585; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 2, i1 false)586; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])587; CHECK-NEXT:    ret void588;589  %val1 = alloca <vscale x 2 x i32>590  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 2, i1 false)591  call void @f(ptr nocapture align 4 noalias readonly %val1)592  ret void593}594 595; Can't remove memcpy because dst is modified between call and memcpy596define void @immut_param_modified_dst(ptr align 4 noalias %val) {597; CHECK-LABEL: @immut_param_modified_dst(598; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4599; CHECK-NEXT:    store i32 13, ptr [[VAL1]], align 4600; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])601; CHECK-NEXT:    ret void602;603  %val1 = alloca i8, align 4604  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)605  store i32 13, ptr %val1606  call void @f(ptr nocapture align 4 noalias readonly %val1)607  ret void608}609 610; Can't remove memcpy because src is modified between call and memcpy611define void @immut_param_modified_src(ptr align 4 noalias %val) {612; CHECK-LABEL: @immut_param_modified_src(613; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4614; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)615; CHECK-NEXT:    store i32 13, ptr [[VAL]], align 4616; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])617; CHECK-NEXT:    ret void618;619  %val1 = alloca i8, align 4620  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)621  store i32 13, ptr %val622  call void @f(ptr nocapture align 4 noalias readonly %val1)623  ret void624}625 626; Can't remove memcpy because memcpy is volatile627define void @immut_param_volatile(ptr align 4 noalias %val) {628; CHECK-LABEL: @immut_param_volatile(629; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4630; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 true)631; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])632; CHECK-NEXT:    ret void633;634  %val1 = alloca i8, align 4635  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 true)636  call void @f(ptr nocapture align 4 noalias readonly %val1)637  ret void638}639 640; Can't remove memcpy because address spaces are different.641define void @immut_param_different_addrespace(ptr addrspace(1) align 4 noalias %val) {642; CHECK-LABEL: @immut_param_different_addrespace(643; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4644; CHECK-NEXT:    call void @llvm.memcpy.p0.p1.i64(ptr align 4 [[VAL1]], ptr addrspace(1) align 4 [[VAL:%.*]], i64 1, i1 false)645; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]])646; CHECK-NEXT:    ret void647;648  %val1 = alloca i8, align 4649  call void @llvm.memcpy.p0.p1.i64(ptr align 4 %val1, ptr addrspace(1) align 4 %val, i64 1, i1 false)650  call void @f(ptr nocapture align 4 noalias readonly %val1)651  ret void652}653 654define void @immut_param_bigger_align(ptr align 16 noalias %val) {655; CHECK-LABEL: @immut_param_bigger_align(656; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL:%.*]])657; CHECK-NEXT:    ret void658;659  %val1 = alloca i8, align 4660  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr %val, i64 1, i1 false)661  call void @f(ptr nocapture noalias readonly %val1)662  ret void663}664 665; Can't remove memcpy if we remove, the bigger alignment couldn't replaced by smaller one.666define void @immut_param_smaller_align(ptr align 4 noalias %val) {667; CHECK-LABEL: @immut_param_smaller_align(668; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 16669; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[VAL1]], ptr [[VAL:%.*]], i64 1, i1 false)670; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL1]])671; CHECK-NEXT:    ret void672;673  %val1 = alloca i8, align 16674  call void @llvm.memcpy.p0.p0.i64(ptr align 16 %val1, ptr %val, i64 1, i1 false)675  call void @f(ptr nocapture noalias readonly %val1)676  ret void677}678 679define void @immut_param_enforced_alignment() {680; CHECK-LABEL: @immut_param_enforced_alignment(681; CHECK-NEXT:    [[VAL:%.*]] = alloca i8, align 4682; CHECK-NEXT:    store i32 42, ptr [[VAL]], align 4683; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL]])684; CHECK-NEXT:    ret void685;686  %val = alloca i8, align 1687  store i32 42, ptr %val688  %val1 = alloca i8, align 4689  call void @llvm.memcpy.p0.p0.i64(ptr %val1, ptr %val, i64 1, i1 false)690  call void @f(ptr nocapture noalias readonly %val1)691  ret void692}693 694; Can't remove memcpy, because if the %val directly passed to @f,695; alignment of ptr to f's argument will be different.696define void @immut_invalid_align_branched(i1 %c, ptr noalias %val) {697; CHECK-LABEL: @immut_invalid_align_branched(698; CHECK-NEXT:    [[VAL1:%.*]] = alloca [4 x i8], align 4699; CHECK-NEXT:    [[VAL2:%.*]] = alloca [16 x i8], align 16700; CHECK-NEXT:    [[VAL3:%.*]] = select i1 [[C:%.*]], ptr [[VAL1]], ptr [[VAL2]]701; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL3]], ptr align 4 [[VAL:%.*]], i64 4, i1 false)702; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL3]])703; CHECK-NEXT:    ret void704;705  %val1 = alloca [4 x i8], align 4706  %val2 = alloca [16 x i8], align 16707  %val3 = select i1 %c, ptr %val1, ptr %val2708  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val3, ptr align 4 %val, i64 4, i1 false)709  call void @f(ptr nocapture noalias readonly %val3)710  ret void711}712 713; Can't remove memcpy, because alias might modify the src.714define void @immut_but_alias_src(ptr %val) {715; CHECK-LABEL: @immut_but_alias_src(716; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4717; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false)718; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL1]])719; CHECK-NEXT:    ret void720;721  %val1 = alloca i8, align 4722  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)723  call void @f(ptr nocapture noalias readonly %val1)724  ret void725}726 727define void @immut_unescaped_alloca() {728; CHECK-LABEL: @immut_unescaped_alloca(729; CHECK-NEXT:    [[VAL:%.*]] = alloca i8, align 4730; CHECK-NEXT:    store i32 42, ptr [[VAL]], align 4731; CHECK-NEXT:    call void @f_full_readonly(ptr [[VAL]])732; CHECK-NEXT:    ret void733;734  %val = alloca i8, align 4735  store i32 42, ptr %val736  %val1 = alloca i8, align 4737  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)738  call void @f_full_readonly(ptr %val1)739  ret void740}741 742; Can't remove memcpy, because alloca src is modified743define void @immut_unescaped_alloca_modified() {744; CHECK-LABEL: @immut_unescaped_alloca_modified(745; CHECK-NEXT:    [[VAL:%.*]] = alloca i8, align 4746; CHECK-NEXT:    store i32 42, ptr [[VAL]], align 4747; CHECK-NEXT:    [[VAL1:%.*]] = alloca i8, align 4748; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL]], i64 1, i1 false)749; CHECK-NEXT:    call void @f_full_readonly(ptr [[VAL1]])750; CHECK-NEXT:    ret void751;752  %val = alloca i8, align 4753  store i32 42, ptr %val754  %val1 = alloca i8, align 4755  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)756  store i32 13, ptr %val757  call void @f_full_readonly(ptr %val1)758  ret void759}760 761; TODO: Remove memcpy762define void @immut_valid_align_branched(i1 %c, ptr noalias align 4 %val) {763; CHECK-LABEL: @immut_valid_align_branched(764; CHECK-NEXT:    [[VAL1:%.*]] = alloca [4 x i8], align 4765; CHECK-NEXT:    [[VAL2:%.*]] = alloca [16 x i8], align 4766; CHECK-NEXT:    [[VAL3:%.*]] = select i1 [[C:%.*]], ptr [[VAL1]], ptr [[VAL2]]767; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL3]], ptr align 4 [[VAL:%.*]], i64 4, i1 false)768; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[VAL3]])769; CHECK-NEXT:    ret void770;771  %val1 = alloca [4 x i8], align 4772  %val2 = alloca [16 x i8], align 4773  %val3 = select i1 %c, ptr %val1, ptr %val2774  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val3, ptr align 4 %val, i64 4, i1 false)775  call void @f(ptr nocapture noalias readonly %val3)776  ret void777}778 779; Merge/drop noalias metadata when replacing parameter.780define void @immut_param_noalias_metadata(ptr align 4 byval(i32) %ptr) {781; CHECK-LABEL: @immut_param_noalias_metadata(782; CHECK-NEXT:    store i32 1, ptr [[PTR:%.*]], align 4, !noalias [[META0:![0-9]+]]783; CHECK-NEXT:    call void @f(ptr noalias readonly captures(none) [[PTR]])784; CHECK-NEXT:    ret void785;786  %tmp = alloca i32, align 4787  store i32 1, ptr %ptr, !noalias !2788  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)789  call void @f(ptr nocapture noalias readonly %tmp), !alias.scope !2790  ret void791}792 793define void @byval_param_noalias_metadata(ptr align 4 byval(i32) %ptr) {794; CHECK-LABEL: @byval_param_noalias_metadata(795; CHECK-NEXT:    store i32 1, ptr [[PTR:%.*]], align 4, !noalias [[META0]]796; CHECK-NEXT:    call void @f_byval(ptr byval(i32) align 4 [[PTR]])797; CHECK-NEXT:    ret void798;799  %tmp = alloca i32, align 4800  store i32 1, ptr %ptr, !noalias !2801  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)802  call void @f_byval(ptr align 4 byval(i32) %tmp), !alias.scope !2803  ret void804}805 806define void @byval_param_profile_metadata(ptr align 4 byval(i32) %ptr) {807; CHECK-LABEL: @byval_param_profile_metadata(808; CHECK-NEXT:    store i32 1, ptr [[PTR2:%.*]], align 4809; CHECK-NEXT:    call void @f_byval(ptr byval(i32) align 4 [[PTR2]]), !prof [[PROF3:![0-9]+]], !memprof [[META4:![0-9]+]], !callsite [[META7:![0-9]+]]810; CHECK-NEXT:    ret void811;812  %tmp = alloca i32, align 4813  store i32 1, ptr %ptr814  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %ptr, i64 4, i1 false)815  call void @f_byval(ptr align 4 byval(i32) %tmp), !memprof !3, !callsite !6, !prof !7816  ret void817}818 819define void @memcpy_memory_none(ptr %p, ptr %p2, i64 %size) {820; CHECK-LABEL: @memcpy_memory_none(821; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[SIZE:%.*]], i1 false) #[[ATTR7:[0-9]+]]822; CHECK-NEXT:    ret void823;824  call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none)825  ret void826}827 828declare void @do_something()829declare void @capture(ptr)830 831define void @memcpy_memcpy_escape_before(ptr noalias %P, ptr noalias %Q) {832; CHECK-LABEL: @memcpy_memcpy_escape_before(833; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [32 x i8], align 16834; CHECK-NEXT:    call void @capture(ptr [[MEMTMP]])835; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)836; CHECK-NEXT:    call void @do_something()837; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[MEMTMP]], i32 32, i1 false)838; CHECK-NEXT:    ret void839;840  %memtmp = alloca [32 x i8], align 16841  call void @capture(ptr %memtmp)842  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)843  call void @do_something()844  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)845  ret void846}847 848define void @memcpy_memcpy_escape_after1(ptr noalias %P, ptr noalias %Q) {849; CHECK-LABEL: @memcpy_memcpy_escape_after1(850; CHECK-NEXT:    [[MEMTMP:%.*]] = alloca [32 x i8], align 16851; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[MEMTMP]], ptr align 16 [[P:%.*]], i32 32, i1 false)852; CHECK-NEXT:    call void @do_something()853; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P]], i32 32, i1 false)854; CHECK-NEXT:    call void @capture(ptr [[MEMTMP]])855; CHECK-NEXT:    ret void856;857  %memtmp = alloca [32 x i8], align 16858  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)859  call void @do_something()860  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)861  call void @capture(ptr %memtmp)862  ret void863}864 865define void @memcpy_memcpy_escape_after2(ptr noalias %P, ptr noalias %Q) {866; CHECK-LABEL: @memcpy_memcpy_escape_after2(867; CHECK-NEXT:    call void @do_something()868; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[Q:%.*]], ptr align 16 [[P:%.*]], i32 32, i1 false)869; CHECK-NEXT:    call void @capture(ptr [[P]])870; CHECK-NEXT:    ret void871;872  %memtmp = alloca [32 x i8], align 16873  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %memtmp, ptr align 16 %P, i32 32, i1 false)874  call void @do_something()875  call void @llvm.memcpy.p0.p0.i32(ptr align 16 %Q, ptr align 16 %memtmp, i32 32, i1 false)876  call void @capture(ptr %P)877  ret void878}879 880define void @memcpy_byval_escape_after(ptr noalias %P) {881; CHECK-LABEL: @memcpy_byval_escape_after(882; CHECK-NEXT:    call void @do_something()883; CHECK-NEXT:    call void @test4a(ptr byval(i8) align 1 [[P:%.*]])884; CHECK-NEXT:    call void @capture(ptr [[P]])885; CHECK-NEXT:    ret void886;887  %A = alloca [8 x i8]888  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %A, ptr align 4 %P, i64 8, i1 false)889  call void @do_something()890  call void @test4a(ptr align 1 byval(i8) %A)891  call void @capture(ptr %P)892  ret void893}894 895define void @memcpy_immut_escape_after(ptr align 4 noalias %val) {896; CHECK-LABEL: @memcpy_immut_escape_after(897; CHECK-NEXT:    call void @do_something()898; CHECK-NEXT:    call void @f(ptr noalias readonly align 4 captures(none) [[VAL:%.*]])899; CHECK-NEXT:    call void @capture(ptr [[VAL]])900; CHECK-NEXT:    ret void901;902  %val1 = alloca i8, align 4903  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false)904  call void @do_something()905  call void @f(ptr align 4 nocapture noalias readonly %val1)906  call void @capture(ptr %val)907  ret void908}909 910declare void @two_args(ptr, ptr)911 912; Should not perform call slot optimization: The function accepts the913; destination as an argument and may read/write it.914define void @test(ptr noalias writable dereferenceable(4) %p) {915; CHECK-LABEL: @test(916; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4917; CHECK-NEXT:    [[RET:%.*]] = call ptr @two_args(ptr [[A]], ptr captures(ret: address, provenance) [[P:%.*]]) #[[ATTR2]]918; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[P]], ptr [[A]], i64 4, i1 false)919; CHECK-NEXT:    ret void920;921  %a = alloca i32922  %ret = call ptr @two_args(ptr %a, ptr captures(ret: address, provenance) %p) nounwind923  call void @llvm.memcpy(ptr align 4 %p, ptr %a, i64 4, i1 false)924  ret void925}926 927!0 = !{!0}928!1 = !{!1, !0}929!2 = !{!1}930!3 = !{!4}931!4 = !{!5, !"cold"}932!5 = !{i64 123, i64 456}933!6 = !{i64 123}934!7 = !{!"branch_weights", i32 10}935