1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s 3 4target datalayout="p5:32:32-A5" 5 6@g1 = constant [32 x i8] zeroinitializer 7@g2 = addrspace(1) constant [32 x i8] zeroinitializer 8 9define i8 @remove_alloca_use_arg(i1 %cond) { 10; CHECK-LABEL: @remove_alloca_use_arg( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 13; CHECK: if: 14; CHECK-NEXT: br label [[SINK:%.*]] 15; CHECK: else: 16; CHECK-NEXT: br label [[SINK]] 17; CHECK: sink: 18; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[IF]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ELSE]] ] 19; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1 20; CHECK-NEXT: ret i8 [[LOAD]] 21; 22entry: 23 %alloca = alloca [32 x i8], align 4, addrspace(1) 24 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 25 br i1 %cond, label %if, label %else 26 27if: 28 %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2 29 br label %sink 30 31else: 32 %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1 33 br label %sink 34 35sink: 36 %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ] 37 %load = load i8, ptr addrspace(1) %ptr 38 ret i8 %load 39} 40 41define i8 @volatile_load_keep_alloca(i1 %cond) { 42; CHECK-LABEL: @volatile_load_keep_alloca( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1) 45; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) 46; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 47; CHECK: if: 48; CHECK-NEXT: [[VAL_IF:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 1 49; CHECK-NEXT: br label [[SINK:%.*]] 50; CHECK: else: 51; CHECK-NEXT: [[VAL_ELSE:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 2 52; CHECK-NEXT: br label [[SINK]] 53; CHECK: sink: 54; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ] 55; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, ptr addrspace(1) [[PTR]], align 1 56; CHECK-NEXT: ret i8 [[LOAD]] 57; 58entry: 59 %alloca = alloca [32 x i8], align 4, addrspace(1) 60 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 61 br i1 %cond, label %if, label %else 62 63if: 64 %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1 65 br label %sink 66 67else: 68 %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2 69 br label %sink 70 71sink: 72 %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ] 73 %load = load volatile i8, ptr addrspace(1) %ptr 74 ret i8 %load 75} 76 77 78define i8 @no_memcpy_keep_alloca(i1 %cond) { 79; CHECK-LABEL: @no_memcpy_keep_alloca( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1) 82; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 83; CHECK: if: 84; CHECK-NEXT: [[VAL_IF:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 1 85; CHECK-NEXT: br label [[SINK:%.*]] 86; CHECK: else: 87; CHECK-NEXT: [[VAL_ELSE:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 2 88; CHECK-NEXT: br label [[SINK]] 89; CHECK: sink: 90; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ] 91; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, ptr addrspace(1) [[PTR]], align 1 92; CHECK-NEXT: ret i8 [[LOAD]] 93; 94entry: 95 %alloca = alloca [32 x i8], align 4, addrspace(1) 96 br i1 %cond, label %if, label %else 97 98if: 99 %val.if = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1 100 br label %sink 101 102else: 103 %val.else = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2 104 br label %sink 105 106sink: 107 %ptr = phi ptr addrspace(1) [ %val.if, %if ], [ %val.else, %else ] 108 %load = load volatile i8, ptr addrspace(1) %ptr 109 ret i8 %load 110} 111 112define i8 @loop_phi_remove_alloca(i1 %cond) { 113; CHECK-LABEL: @loop_phi_remove_alloca( 114; CHECK-NEXT: entry: 115; CHECK-NEXT: br label [[BB_0:%.*]] 116; CHECK: bb.0: 117; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[BB_1:%.*]] ] 118; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]] 119; CHECK: bb.1: 120; CHECK-NEXT: br label [[BB_0]] 121; CHECK: exit: 122; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1 123; CHECK-NEXT: ret i8 [[LOAD]] 124; 125entry: 126 %alloca = alloca [32 x i8], align 4, addrspace(1) 127 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 128 %val1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1 129 br label %bb.0 130 131bb.0: 132 %ptr = phi ptr addrspace(1) [ %val1, %entry ], [ %val2, %bb.1 ] 133 br i1 %cond, label %bb.1, label %exit 134 135bb.1: 136 %val2 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2 137 br label %bb.0 138 139exit: 140 %load = load i8, ptr addrspace(1) %ptr 141 ret i8 %load 142} 143 144define i32 @remove_alloca_ptr_arg(i1 %c, ptr %ptr) { 145; CHECK-LABEL: @remove_alloca_ptr_arg( 146; CHECK-NEXT: entry: 147; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 148; CHECK: if: 149; CHECK-NEXT: br label [[JOIN]] 150; CHECK: join: 151; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ @g1, [[IF]] ], [ [[PTR:%.*]], [[ENTRY:%.*]] ] 152; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PHI]], align 4 153; CHECK-NEXT: ret i32 [[V]] 154; 155entry: 156 %alloca = alloca [32 x i8] 157 call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false) 158 br i1 %c, label %if, label %join 159 160if: 161 br label %join 162 163join: 164 %phi = phi ptr [ %alloca, %if ], [ %ptr, %entry ] 165 %v = load i32, ptr %phi 166 ret i32 %v 167} 168 169define i8 @loop_phi_late_memtransfer_remove_alloca(i1 %cond) { 170; CHECK-LABEL: @loop_phi_late_memtransfer_remove_alloca( 171; CHECK-NEXT: entry: 172; CHECK-NEXT: br label [[BB_0:%.*]] 173; CHECK: bb.0: 174; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds nuw (i8, ptr @g1, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds nuw (i8, ptr @g1, i64 2), [[BB_1:%.*]] ] 175; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]] 176; CHECK: bb.1: 177; CHECK-NEXT: br label [[BB_0]] 178; CHECK: exit: 179; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1 180; CHECK-NEXT: ret i8 [[LOAD]] 181; 182entry: 183 %alloca = alloca [32 x i8], align 4, addrspace(1) 184 %val1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 1 185 br label %bb.0 186 187bb.0: 188 %ptr = phi ptr addrspace(1) [ %val1, %entry ], [ %val2, %bb.1 ] 189 br i1 %cond, label %bb.1, label %exit 190 191bb.1: 192 %val2 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 2 193 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 194 br label %bb.0 195 196exit: 197 %load = load i8, ptr addrspace(1) %ptr 198 ret i8 %load 199} 200 201define i32 @test_memcpy_after_phi(i1 %cond, ptr %ptr) { 202; CHECK-LABEL: @test_memcpy_after_phi( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: [[A:%.*]] = alloca [32 x i8], align 1 205; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 206; CHECK: if: 207; CHECK-NEXT: br label [[JOIN]] 208; CHECK: join: 209; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[IF]] ], [ [[PTR:%.*]], [[ENTRY:%.*]] ] 210; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(32) [[PHI]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) 211; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PHI]], align 4 212; CHECK-NEXT: ret i32 [[V]] 213; 214entry: 215 %a = alloca [32 x i8] 216 br i1 %cond, label %if, label %join 217 218if: 219 br label %join 220 221join: 222 %phi = phi ptr [ %a, %if ], [ %ptr, %entry ] 223 call void @llvm.memcpy.p0.p0.i64(ptr %phi, ptr @g1, i64 32, i1 false) 224 %v = load i32, ptr %phi 225 ret i32 %v 226} 227 228define i32 @addrspace_diff_keep_alloca(i1 %cond, ptr %x) { 229; CHECK-LABEL: @addrspace_diff_keep_alloca( 230; CHECK-NEXT: entry: 231; CHECK-NEXT: [[A:%.*]] = alloca [32 x i8], align 1 232; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false) 233; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 234; CHECK: if: 235; CHECK-NEXT: br label [[JOIN]] 236; CHECK: join: 237; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 238; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PHI]], align 4 239; CHECK-NEXT: ret i32 [[V]] 240; 241entry: 242 %a = alloca [32 x i8] 243 call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false) 244 br i1 %cond, label %if, label %join 245 246if: 247 br label %join 248 249join: 250 %phi = phi ptr [ %a, %if ], [ %x, %entry ] 251 %v = load i32, ptr %phi 252 ret i32 %v 253} 254 255define i32 @addrspace_diff_keep_alloca_extra_gep(i1 %cond, ptr %x) { 256; CHECK-LABEL: @addrspace_diff_keep_alloca_extra_gep( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: [[A:%.*]] = alloca [32 x i8], align 1 259; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[A]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false) 260; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 261; CHECK: if: 262; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 4 263; CHECK-NEXT: br label [[JOIN]] 264; CHECK: join: 265; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[GEP]], [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 266; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PHI]], align 4 267; CHECK-NEXT: ret i32 [[V]] 268; 269entry: 270 %a = alloca [32 x i8] 271 call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false) 272 %gep = getelementptr i8, ptr %a, i64 4 273 br i1 %cond, label %if, label %join 274 275if: 276 br label %join 277 278join: 279 %phi = phi ptr [ %gep, %if ], [ %x, %entry ] 280 %v = load i32, ptr %phi 281 ret i32 %v 282} 283 284define i32 @addrspace_diff_remove_alloca(i1 %cond) { 285; CHECK-LABEL: @addrspace_diff_remove_alloca( 286; CHECK-NEXT: entry: 287; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 288; CHECK: if: 289; CHECK-NEXT: br label [[JOIN]] 290; CHECK: join: 291; CHECK-NEXT: [[PHI1:%.*]] = phi ptr addrspace(1) [ @g2, [[IF]] ], [ getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 2), [[ENTRY:%.*]] ] 292; CHECK-NEXT: [[V:%.*]] = load i32, ptr addrspace(1) [[PHI1]], align 4 293; CHECK-NEXT: ret i32 [[V]] 294; 295entry: 296 %a = alloca [32 x i8] 297 call void @llvm.memcpy.p0.p1.i64(ptr %a, ptr addrspace(1) @g2, i64 32, i1 false) 298 %gep = getelementptr inbounds [32 x i8], ptr %a, i32 0, i32 2 299 br i1 %cond, label %if, label %join 300 301if: 302 br label %join 303 304join: 305 %phi = phi ptr [ %a, %if ], [ %gep, %entry ] 306 %v = load i32, ptr %phi 307 ret i32 %v 308} 309 310define i32 @phi_loop(i1 %c) { 311; CHECK-LABEL: @phi_loop( 312; CHECK-NEXT: entry: 313; CHECK-NEXT: br label [[LOOP:%.*]] 314; CHECK: loop: 315; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ @g1, [[ENTRY:%.*]] ], [ [[PTR_NEXT:%.*]], [[LOOP]] ] 316; CHECK-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 4 317; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 318; CHECK: exit: 319; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PTR]], align 4 320; CHECK-NEXT: ret i32 [[V]] 321; 322entry: 323 %alloca = alloca [32 x i8] 324 call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false) 325 br label %loop 326 327loop: 328 %ptr = phi ptr [ %alloca, %entry ], [ %ptr.next, %loop ] 329 %ptr.next = getelementptr i8, ptr %ptr, i64 4 330 br i1 %c, label %exit, label %loop 331 332exit: 333 %v = load i32, ptr %ptr 334 ret i32 %v 335} 336 337define i32 @phi_loop_different_addrspace(i1 %c) { 338; CHECK-LABEL: @phi_loop_different_addrspace( 339; CHECK-NEXT: entry: 340; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1 341; CHECK-NEXT: call void @llvm.memcpy.p0.p1.i64(ptr noundef nonnull align 1 dereferenceable(32) [[ALLOCA]], ptr addrspace(1) noundef align 16 dereferenceable(32) @g2, i64 32, i1 false) 342; CHECK-NEXT: br label [[LOOP:%.*]] 343; CHECK: loop: 344; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[PTR_NEXT:%.*]], [[LOOP]] ] 345; CHECK-NEXT: [[PTR_NEXT]] = getelementptr i8, ptr [[PTR]], i64 4 346; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 347; CHECK: exit: 348; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[PTR]], align 4 349; CHECK-NEXT: ret i32 [[V]] 350; 351entry: 352 %alloca = alloca [32 x i8] 353 call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false) 354 br label %loop 355 356loop: 357 %ptr = phi ptr [ %alloca, %entry ], [ %ptr.next, %loop ] 358 %ptr.next = getelementptr i8, ptr %ptr, i64 4 359 br i1 %c, label %exit, label %loop 360 361exit: 362 %v = load i32, ptr %ptr 363 ret i32 %v 364} 365 366define i8 @select_same_addrspace_remove_alloca(i1 %cond, ptr %p) { 367; CHECK-LABEL: @select_same_addrspace_remove_alloca( 368; CHECK-NEXT: entry: 369; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr @g1, ptr [[P:%.*]] 370; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1 371; CHECK-NEXT: ret i8 [[LOAD]] 372; 373entry: 374 %alloca = alloca [32 x i8] 375 call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr @g1, i64 32, i1 false) 376 %ptr = select i1 %cond, ptr %alloca, ptr %p 377 %load = load i8, ptr %ptr 378 ret i8 %load 379} 380 381define i8 @select_after_memcpy_keep_alloca(i1 %cond, ptr %p) { 382; CHECK-LABEL: @select_after_memcpy_keep_alloca( 383; CHECK-NEXT: entry: 384; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1 385; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr [[ALLOCA]], ptr [[P:%.*]] 386; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(32) [[PTR]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) 387; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR]], align 1 388; CHECK-NEXT: ret i8 [[LOAD]] 389; 390entry: 391 %alloca = alloca [32 x i8] 392 %ptr = select i1 %cond, ptr %alloca, ptr %p 393 call void @llvm.memcpy.p0.p0.i64(ptr %ptr, ptr @g1, i64 32, i1 false) 394 %load = load i8, ptr %ptr 395 ret i8 %load 396} 397 398define i8 @select_diff_addrspace_keep_alloca(i1 %cond, ptr addrspace(1) %p) { 399; CHECK-LABEL: @select_diff_addrspace_keep_alloca( 400; CHECK-NEXT: entry: 401; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1) 402; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) 403; CHECK-NEXT: [[PTR:%.*]] = select i1 [[COND:%.*]], ptr addrspace(1) [[ALLOCA]], ptr addrspace(1) [[P:%.*]] 404; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1 405; CHECK-NEXT: ret i8 [[LOAD]] 406; 407entry: 408 %alloca = alloca [32 x i8], addrspace(1) 409 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 410 %ptr = select i1 %cond, ptr addrspace(1) %alloca, ptr addrspace(1) %p 411 %load = load i8, ptr addrspace(1) %ptr 412 ret i8 %load 413} 414 415define i8 @select_diff_addrspace_remove_alloca(i1 %cond, ptr %p) { 416; CHECK-LABEL: @select_diff_addrspace_remove_alloca( 417; CHECK-NEXT: entry: 418; CHECK-NEXT: ret i8 0 419; 420entry: 421 %alloca = alloca [32 x i8] 422 call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false) 423 %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2 424 %sel = select i1 %cond, ptr %alloca, ptr %gep 425 %gep2 = getelementptr inbounds i8, ptr %sel, i64 4 426 %load = load i8, ptr %gep2 427 ret i8 %load 428} 429 430define i8 @select_diff_addrspace_remove_alloca_asan(i1 %cond, ptr %p) sanitize_address { 431; CHECK-LABEL: @select_diff_addrspace_remove_alloca_asan( 432; CHECK-NEXT: entry: 433; CHECK-NEXT: [[GEP2:%.*]] = select i1 [[COND:%.*]], ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 4), ptr addrspace(1) getelementptr inbounds nuw (i8, ptr addrspace(1) @g2, i64 6) 434; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[GEP2]], align 1 435; CHECK-NEXT: ret i8 [[LOAD]] 436; 437entry: 438 %alloca = alloca [32 x i8] 439 call void @llvm.memcpy.p0.p1.i64(ptr %alloca, ptr addrspace(1) @g2, i64 32, i1 false) 440 %gep = getelementptr inbounds [32 x i8], ptr %alloca, i32 0, i32 2 441 %sel = select i1 %cond, ptr %alloca, ptr %gep 442 %gep2 = getelementptr inbounds i8, ptr %sel, i64 4 443 %load = load i8, ptr %gep2 444 ret i8 %load 445} 446 447declare i8 @readonly_callee(ptr readonly nocapture) 448 449; FIXME: This should be able to fold to call i8 @readonly_callee(ptr nonnull @g1) 450define i8 @call_readonly_remove_alloca() { 451; CHECK-LABEL: @call_readonly_remove_alloca( 452; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1) 453; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(32) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(32) @g1, i64 32, i1 false) 454; CHECK-NEXT: [[P:%.*]] = addrspacecast ptr addrspace(1) [[ALLOCA]] to ptr 455; CHECK-NEXT: [[V:%.*]] = call i8 @readonly_callee(ptr [[P]]) 456; CHECK-NEXT: ret i8 [[V]] 457; 458 %alloca = alloca [32 x i8], addrspace(1) 459 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 32, i1 false) 460 %p = addrspacecast ptr addrspace(1) %alloca to ptr 461 %v = call i8 @readonly_callee(ptr %p) 462 ret i8 %v 463} 464 465define i8 @call_readonly_keep_alloca2() { 466; CHECK-LABEL: @call_readonly_keep_alloca2( 467; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 1, addrspace(1) 468; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 1 dereferenceable(16) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(16) @g1, i64 16, i1 false) 469; CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[ALLOCA]], i64 16 470; CHECK-NEXT: call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) noundef nonnull align 1 dereferenceable(16) [[A1]], ptr addrspace(1) noundef align 16 dereferenceable(16) @g2, i64 16, i1 false) 471; CHECK-NEXT: [[P:%.*]] = addrspacecast ptr addrspace(1) [[ALLOCA]] to ptr 472; CHECK-NEXT: [[V:%.*]] = call i8 @readonly_callee(ptr [[P]]) 473; CHECK-NEXT: ret i8 [[V]] 474; 475 %alloca = alloca [32 x i8], addrspace(1) 476 call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) %alloca, ptr @g1, i64 16, i1 false) 477 %a1 = getelementptr inbounds [32 x i8], ptr addrspace(1) %alloca, i32 0, i32 16 478 call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %a1, ptr addrspace(1) @g2, i64 16, i1 false) 479 %p = addrspacecast ptr addrspace(1) %alloca to ptr 480 %v = call i8 @readonly_callee(ptr %p) 481 ret i8 %v 482} 483 484declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1), ptr, i64, i1) 485declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1) 486declare void @llvm.memcpy.p0.p1.i64(ptr, ptr addrspace(1), i64, i1) 487declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1) 488