1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=memcpyopt,dse -S -verify-memoryssa | FileCheck %s 3 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) nounwind 13declare void @llvm.memcpy.p0.p1.i64(ptr nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind 14declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture, i64, i1) nounwind 15declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind 16declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind 17declare void @llvm.memcpy.inline.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind 18declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind 19 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 16 26; CHECK-NEXT: [[MEMTMP:%.*]] = alloca [[TMP0]], align 16 27; 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 void 31; 32entry: 33 %tmp2 = alloca %0 34 %memtmp = alloca %0, align 16 35 %tmp5 = fsub x86_fp80 0xK80000000000000000000, %z.1 36 call void @ccoshl(ptr sret(%0) %memtmp, x86_fp80 %tmp5, x86_fp80 %z.0) nounwind 37 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 void 40} 41 42declare void @ccoshl(ptr nocapture sret(%0), x86_fp80, x86_fp80) nounwind 43 44 45; The intermediate alloca and one of the memcpy's should be eliminated, the 46; 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 void 51; 52 %memtmp = alloca %0, align 16 53 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 void 56 57} 58 59; The intermediate alloca and one of the memcpy's should be eliminated, the 60; 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 void 65; 66 %memtmp = alloca %0, align 16 67 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 void 70 71} 72 73; The intermediate alloca and one of the memcpy's should be eliminated, the 74; 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 void 79; 80 %memtmp = alloca %0, align 16 81 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 void 84 85} 86 87; Same as @test2_memcpy, but the remaining memcpy should remain non-inline even 88; 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 void 93; 94 %memtmp = alloca %0, align 16 95 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 void 98 99} 100 101; Same as @test2_memcpy, but the remaining memcpy should remain inline even 102; 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 void 107; 108 %memtmp = alloca %0, align 16 109 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 void 112 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 void 120; 121 %memtmp = alloca %0, align 16 122 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 void 125 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 1 132; 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 void 135; 136 %tmp = alloca [16 x i8], align 1 137 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 void 140} 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 1 146; CHECK-NEXT: ret void 147; 148 %tmp = alloca [16 x i8], align 1 149 %src = getelementptr inbounds i8, ptr %arg, i64 1 150 %dest = getelementptr inbounds i8, ptr %arg, i64 1 151 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 void 154} 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 1 160; CHECK-NEXT: [[SRC:%.*]] = getelementptr inbounds i8, ptr [[ARG:%.*]], i64 1 161; CHECK-NEXT: [[DEST:%.*]] = getelementptr inbounds i8, ptr [[ARG]], i64 2 162; 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 void 165; 166 %tmp = alloca [16 x i8], align 1 167 %src = getelementptr inbounds i8, ptr %arg, i64 1 168 %dest = getelementptr inbounds i8, ptr %arg, i64 2 169 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 void 172} 173 174@x = external global %0 175 176define void @test3(ptr noalias writable sret(%0) %agg.result) nounwind { 177; CHECK-LABEL: @test3( 178; CHECK-NEXT: [[X_0:%.*]] = alloca [[TMP0:%.*]], align 16 179; 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 void 181; 182 %x.0 = alloca %0 183 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 void 186} 187 188 189; PR8644 190define void @test4(ptr %P) { 191; CHECK-LABEL: @test4( 192; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P:%.*]]) 193; CHECK-NEXT: ret void 194; 195 %A = alloca %1 196 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 void 199} 200 201; Make sure we don't remove the memcpy if the source address space doesn't match the byval argument 202define void @test4_addrspace(ptr addrspace(1) %P) { 203; CHECK-LABEL: @test4_addrspace( 204; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8 205; 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 void 208; 209 %a1 = alloca %1 210 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 void 213} 214 215define void @test4_write_between(ptr %P) { 216; CHECK-LABEL: @test4_write_between( 217; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8 218; 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 1 220; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[A1]]) 221; CHECK-NEXT: ret void 222; 223 %a1 = alloca %1 224 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false) 225 store i8 0, ptr %a1 226 call void @test4a(ptr align 1 byval(i8) %a1) 227 ret void 228} 229 230define i8 @test4_read_between(ptr %P) { 231; CHECK-LABEL: @test4_read_between( 232; CHECK-NEXT: [[A1:%.*]] = alloca [[TMP1:%.*]], align 8 233; 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 1 235; CHECK-NEXT: call void @test4a(ptr byval(i8) align 1 [[P]]) 236; CHECK-NEXT: ret i8 [[X]] 237; 238 %a1 = alloca %1 239 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a1, ptr align 4 %P, i64 8, i1 false) 240 %x = load i8, ptr %a1 241 call void @test4a(ptr align 1 byval(i8) %a1) 242 ret i8 %x 243} 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 void 253; 254 %a1 = alloca %1 255 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 %exit 257 258call: 259 call void @test4a(ptr align 1 byval(i8) %a1) 260 br label %exit 261 262exit: 263 ret void 264} 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 16 271 272declare void @test5a(ptr align 16 byval(%struct.S)) nounwind ssp 273 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 16 280; 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 0 282; CHECK-NEXT: store i8 4, ptr [[A]], align 1 283; CHECK-NEXT: call void @test5a(ptr byval([[STRUCT_S]]) align 16 [[Y]]) 284; CHECK-NEXT: ret i32 0 285; 286entry: 287 %y = alloca %struct.S, align 16 288 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 0 290 store i8 4, ptr %a 291 call void @test5a(ptr align 16 byval(%struct.S) %y) 292 ret i32 0 293} 294 295;; Noop memcpy should be zapped. 296define void @test6(ptr %P) { 297; CHECK-LABEL: @test6( 298; CHECK-NEXT: ret void 299; 300 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %P, ptr align 4 %P, i64 8, i1 false) 301 ret void 302} 303 304 305; PR9794 - Should forward memcpy into byval argument even though the memcpy 306; 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 4 317 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) nounwind 319 ret i32 %call 320} 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 on 326; 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 void 332; 333 %A = tail call ptr @malloc(i32 10) 334 %B = getelementptr inbounds i8, ptr %A, i64 2 335 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 2 338 tail call void @llvm.memcpy.p0.p0.i32(ptr %D, ptr %B, i32 7, i1 false) 339 ret void 340} 341 342declare noalias ptr @malloc(i32) willreturn allockind("alloc,uninitialized") allocsize(0) 343 344; rdar://11341081 345%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 4 351; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4 352; 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 void 357; 358entry: 359 %b = alloca %struct.big, align 4 360 %tmp = alloca %struct.big, align 4 361 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 void 367} 368 369define void @test9() nounwind ssp uwtable { 370; CHECK-LABEL: @test9( 371; CHECK-NEXT: entry: 372; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_BIG:%.*]], align 4 373; CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_BIG]], align 4 374; CHECK-NEXT: call void @f1(ptr sret([[STRUCT_BIG]]) [[B]]) 375; CHECK-NEXT: call void @f2(ptr [[B]]) 376; CHECK-NEXT: ret void 377; 378entry: 379 %b = alloca %struct.big, align 4 380 %tmp = alloca %struct.big, align 4 381 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 void 385} 386 387; rdar://14073661. 388; Test10 triggered assertion when the compiler try to get the size of the 389; opaque type of *x, where the x is the formal argument with attribute 'sret'. 390 391%opaque = type opaque 392declare 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 4 397; CHECK-NEXT: store i32 [[Y:%.*]], ptr [[A]], align 4 398; CHECK-NEXT: call void @foo(ptr noalias captures(none) [[A]]) 399; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[A]], align 4 400; CHECK-NEXT: store i32 [[C]], ptr [[X:%.*]], align 4 401; CHECK-NEXT: ret void 402; 403 %a = alloca i32, align 4 404 store i32 %y, ptr %a 405 call void @foo(ptr noalias nocapture %a) 406 %c = load i32, ptr %a 407 store i32 %c, ptr %x 408 ret void 409} 410 411; don't create new addressspacecasts when we don't know they're safe for the target 412define 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 void 416; 417 %A = alloca [20 x i32], align 4 418 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 void 421} 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 void 434; 435 %val1 = alloca i8, align 4 436 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 void 439} 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 4 445; 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 void 448; 449 %val1 = alloca i8, align 4 450 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 void 453} 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 4 459; 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 void 463; 464 %val1 = alloca i8, align 4 465 call void @f(ptr %val1) ; escape 466 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 void 469} 470 471; Can remove memcpy because alloca does not escape, so lack of noalias on the 472; 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 void 477; 478 %val1 = alloca i8, align 4 479 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 void 482} 483 484; Can remove memcpy because the function is argmem: read, so there cannot be 485; 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 4 489; 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 void 492; 493 %val1 = alloca i8, align 4 494 call void @f(ptr %val1) ; escape 495 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 void 498} 499 500; Can remove memcpy because the function is argmem: read, so there cannot be 501; a write to the escaped pointer. The readonly on the argument is redundant in 502; 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 4 506; 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 void 510; 511 %val1 = alloca i8, align 4 512 call void @f(ptr %val1) ; escape 513 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 void 516} 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 4 522; 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 void 525; 526 %val1 = alloca i8, align 4 527 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 void 530} 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 void 536; 537 %val1 = alloca i8, align 4 538 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 void 541} 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 void 547; 548 %val1 = alloca i8, align 4 549 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 void 552} 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 void 561; 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 void 565} 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 4 571; 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 void 574; 575 %val1 = alloca ptr, i64 %n 576 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 void 579} 580 581; Can't remove memcpy for scalable vector, because of memcpy size sufficiency is unknown 582define 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 8 585; 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 void 588; 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 void 593} 594 595; Can't remove memcpy because dst is modified between call and memcpy 596define void @immut_param_modified_dst(ptr align 4 noalias %val) { 597; CHECK-LABEL: @immut_param_modified_dst( 598; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 599; CHECK-NEXT: store i32 13, ptr [[VAL1]], align 4 600; CHECK-NEXT: call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]]) 601; CHECK-NEXT: ret void 602; 603 %val1 = alloca i8, align 4 604 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) 605 store i32 13, ptr %val1 606 call void @f(ptr nocapture align 4 noalias readonly %val1) 607 ret void 608} 609 610; Can't remove memcpy because src is modified between call and memcpy 611define void @immut_param_modified_src(ptr align 4 noalias %val) { 612; CHECK-LABEL: @immut_param_modified_src( 613; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 614; 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 4 616; CHECK-NEXT: call void @f(ptr noalias readonly align 4 captures(none) [[VAL1]]) 617; CHECK-NEXT: ret void 618; 619 %val1 = alloca i8, align 4 620 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) 621 store i32 13, ptr %val 622 call void @f(ptr nocapture align 4 noalias readonly %val1) 623 ret void 624} 625 626; Can't remove memcpy because memcpy is volatile 627define void @immut_param_volatile(ptr align 4 noalias %val) { 628; CHECK-LABEL: @immut_param_volatile( 629; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 630; 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 void 633; 634 %val1 = alloca i8, align 4 635 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 void 638} 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 4 644; 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 void 647; 648 %val1 = alloca i8, align 4 649 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 void 652} 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 void 658; 659 %val1 = alloca i8, align 4 660 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 void 663} 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 16 669; 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 void 672; 673 %val1 = alloca i8, align 16 674 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 void 677} 678 679define void @immut_param_enforced_alignment() { 680; CHECK-LABEL: @immut_param_enforced_alignment( 681; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4 682; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4 683; CHECK-NEXT: call void @f(ptr noalias readonly captures(none) [[VAL]]) 684; CHECK-NEXT: ret void 685; 686 %val = alloca i8, align 1 687 store i32 42, ptr %val 688 %val1 = alloca i8, align 4 689 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 void 692} 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 4 699; CHECK-NEXT: [[VAL2:%.*]] = alloca [16 x i8], align 16 700; 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 void 704; 705 %val1 = alloca [4 x i8], align 4 706 %val2 = alloca [16 x i8], align 16 707 %val3 = select i1 %c, ptr %val1, ptr %val2 708 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 void 711} 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 4 717; 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 void 720; 721 %val1 = alloca i8, align 4 722 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 void 725} 726 727define void @immut_unescaped_alloca() { 728; CHECK-LABEL: @immut_unescaped_alloca( 729; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4 730; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4 731; CHECK-NEXT: call void @f_full_readonly(ptr [[VAL]]) 732; CHECK-NEXT: ret void 733; 734 %val = alloca i8, align 4 735 store i32 42, ptr %val 736 %val1 = alloca i8, align 4 737 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 void 740} 741 742; Can't remove memcpy, because alloca src is modified 743define void @immut_unescaped_alloca_modified() { 744; CHECK-LABEL: @immut_unescaped_alloca_modified( 745; CHECK-NEXT: [[VAL:%.*]] = alloca i8, align 4 746; CHECK-NEXT: store i32 42, ptr [[VAL]], align 4 747; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 748; 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 void 751; 752 %val = alloca i8, align 4 753 store i32 42, ptr %val 754 %val1 = alloca i8, align 4 755 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) 756 store i32 13, ptr %val 757 call void @f_full_readonly(ptr %val1) 758 ret void 759} 760 761; TODO: Remove memcpy 762define 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 4 765; CHECK-NEXT: [[VAL2:%.*]] = alloca [16 x i8], align 4 766; 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 void 770; 771 %val1 = alloca [4 x i8], align 4 772 %val2 = alloca [16 x i8], align 4 773 %val3 = select i1 %c, ptr %val1, ptr %val2 774 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 void 777} 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 void 785; 786 %tmp = alloca i32, align 4 787 store i32 1, ptr %ptr, !noalias !2 788 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 !2 790 ret void 791} 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 void 798; 799 %tmp = alloca i32, align 4 800 store i32 1, ptr %ptr, !noalias !2 801 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 !2 803 ret void 804} 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 4 809; 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 void 811; 812 %tmp = alloca i32, align 4 813 store i32 1, ptr %ptr 814 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 !7 816 ret void 817} 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 void 823; 824 call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false) memory(none) 825 ret void 826} 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 16 834; 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 void 839; 840 %memtmp = alloca [32 x i8], align 16 841 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 void 846} 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 16 851; 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 void 856; 857 %memtmp = alloca [32 x i8], align 16 858 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 void 863} 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 void 871; 872 %memtmp = alloca [32 x i8], align 16 873 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 void 878} 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 void 886; 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 void 893} 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 void 901; 902 %val1 = alloca i8, align 4 903 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 void 908} 909 910!0 = !{!0} 911!1 = !{!1, !0} 912!2 = !{!1} 913!3 = !{!4} 914!4 = !{!5, !"cold"} 915!5 = !{i64 123, i64 456} 916!6 = !{i64 123} 917!7 = !{!"branch_weights", i32 10} 918