1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes='dse' -S %s | FileCheck %s 3 4declare void @escape_and_clobber(ptr) 5declare void @escape_writeonly(ptr) writeonly 6declare void @clobber() 7 8define i32 @test_not_captured_before_load_same_bb(ptr %in.ptr) { 9; CHECK-LABEL: @test_not_captured_before_load_same_bb( 10; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 11; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 12; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 13; CHECK-NEXT: store i32 99, ptr [[A]], align 4 14; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 15; CHECK-NEXT: ret i32 [[IN_LV_2]] 16; 17 %a = alloca i32, align 4 18 store i32 55, ptr %a 19 %in.lv.1 = load ptr , ptr %in.ptr, align 2 20 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 21 store i32 99, ptr %a, align 4 22 call void @escape_and_clobber(ptr %a) 23 ret i32 %in.lv.2 24} 25 26define i32 @test_not_captured_before_load_same_bb_escape_unreachable_block(ptr %in.ptr) { 27; CHECK-LABEL: @test_not_captured_before_load_same_bb_escape_unreachable_block( 28; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 29; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 30; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 31; CHECK-NEXT: store i32 99, ptr [[A]], align 4 32; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 33; CHECK-NEXT: ret i32 [[IN_LV_2]] 34; CHECK: unreach: 35; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 36; CHECK-NEXT: ret i32 0 37; 38 %a = alloca i32, align 4 39 store i32 55, ptr %a 40 %in.lv.1 = load ptr , ptr %in.ptr, align 2 41 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 42 store i32 99, ptr %a, align 4 43 call void @escape_and_clobber(ptr %a) 44 ret i32 %in.lv.2 45 46unreach: 47 call void @escape_and_clobber(ptr %a) 48 ret i32 0 49} 50 51define i32 @test_not_captured_before_load_same_bb_escape_unreachable_block2(ptr %in.ptr) { 52; CHECK-LABEL: @test_not_captured_before_load_same_bb_escape_unreachable_block2( 53; CHECK-NEXT: br label [[BB:%.*]] 54; CHECK: unreach: 55; CHECK-NEXT: call void @escape_and_clobber(ptr [[A:%.*]]) 56; CHECK-NEXT: ret i32 0 57; CHECK: bb: 58; CHECK-NEXT: [[A]] = alloca i32, align 4 59; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 60; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 61; CHECK-NEXT: store i32 99, ptr [[A]], align 4 62; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 63; CHECK-NEXT: ret i32 [[IN_LV_2]] 64; 65 br label %bb 66 67unreach: 68 call void @escape_and_clobber(ptr %a) 69 ret i32 0 70 71bb: 72 %a = alloca i32, align 4 73 store i32 55, ptr %a 74 %in.lv.1 = load ptr , ptr %in.ptr, align 2 75 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 76 store i32 99, ptr %a, align 4 77 call void @escape_and_clobber(ptr %a) 78 ret i32 %in.lv.2 79} 80 81define i32 @test_captured_and_clobbered_after_load_same_bb_2(ptr %in.ptr) { 82; CHECK-LABEL: @test_captured_and_clobbered_after_load_same_bb_2( 83; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 84; CHECK-NEXT: store i32 55, ptr [[A]], align 4 85; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 86; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 87; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 88; CHECK-NEXT: store i32 99, ptr [[A]], align 4 89; CHECK-NEXT: call void @clobber() 90; CHECK-NEXT: ret i32 [[IN_LV_2]] 91; 92 %a = alloca i32, align 4 93 store i32 55, ptr %a 94 %in.lv.1 = load ptr , ptr %in.ptr, align 2 95 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 96 call void @escape_and_clobber(ptr %a) 97 store i32 99, ptr %a, align 4 98 call void @clobber() 99 ret i32 %in.lv.2 100} 101 102define i32 @test_captured_after_load_same_bb_2_clobbered_later(ptr %in.ptr) { 103; CHECK-LABEL: @test_captured_after_load_same_bb_2_clobbered_later( 104; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 105; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 106; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 107; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 108; CHECK-NEXT: store i32 99, ptr [[A]], align 4 109; CHECK-NEXT: call void @clobber() 110; CHECK-NEXT: ret i32 [[IN_LV_2]] 111; 112 %a = alloca i32, align 4 113 store i32 55, ptr %a 114 %in.lv.1 = load ptr , ptr %in.ptr, align 2 115 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 116 call void @escape_writeonly(ptr %a) 117 store i32 99, ptr %a, align 4 118 call void @clobber() 119 ret i32 %in.lv.2 120} 121 122define i32 @test_captured_and_clobbered_before_load_same_bb_1(ptr %in.ptr) { 123; CHECK-LABEL: @test_captured_and_clobbered_before_load_same_bb_1( 124; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 125; CHECK-NEXT: store i32 55, ptr [[A]], align 4 126; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 127; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 128; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 129; CHECK-NEXT: store i32 99, ptr [[A]], align 4 130; CHECK-NEXT: call void @clobber() 131; CHECK-NEXT: ret i32 [[IN_LV_2]] 132; 133 %a = alloca i32, align 4 134 store i32 55, ptr %a 135 %in.lv.1 = load ptr , ptr %in.ptr, align 2 136 call void @escape_and_clobber(ptr %a) 137 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 138 store i32 99, ptr %a, align 4 139 call void @clobber() 140 ret i32 %in.lv.2 141} 142 143define i32 @test_captured_before_load_same_bb_1_clobbered_later(ptr %in.ptr) { 144; CHECK-LABEL: @test_captured_before_load_same_bb_1_clobbered_later( 145; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 146; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 147; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 148; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 149; CHECK-NEXT: store i32 99, ptr [[A]], align 4 150; CHECK-NEXT: call void @clobber() 151; CHECK-NEXT: ret i32 [[IN_LV_2]] 152; 153 %a = alloca i32, align 4 154 store i32 55, ptr %a 155 %in.lv.1 = load ptr , ptr %in.ptr, align 2 156 call void @escape_writeonly(ptr %a) 157 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 158 store i32 99, ptr %a, align 4 159 call void @clobber() 160 ret i32 %in.lv.2 161} 162 163define i32 @test_captured_before_load_same_bb_2(ptr %in.ptr) { 164; CHECK-LABEL: @test_captured_before_load_same_bb_2( 165; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 166; CHECK-NEXT: store i32 55, ptr [[A]], align 4 167; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 168; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 169; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 170; CHECK-NEXT: store i32 99, ptr [[A]], align 4 171; CHECK-NEXT: call void @clobber() 172; CHECK-NEXT: ret i32 [[IN_LV_2]] 173; 174 %a = alloca i32, align 4 175 store i32 55, ptr %a 176 call void @escape_writeonly(ptr %a) 177 %in.lv.1 = load ptr , ptr %in.ptr, align 2 178 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 179 store i32 99, ptr %a, align 4 180 call void @clobber() 181 ret i32 %in.lv.2 182} 183 184define i32 @test_not_captured_before_load_same_bb_clobber(ptr %in.ptr) { 185; CHECK-LABEL: @test_not_captured_before_load_same_bb_clobber( 186; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 187; CHECK-NEXT: call void @clobber() 188; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 189; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 190; CHECK-NEXT: store i32 99, ptr [[A]], align 4 191; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 192; CHECK-NEXT: ret i32 [[IN_LV_2]] 193; 194 %a = alloca i32, align 4 195 store i32 55, ptr %a 196 call void @clobber() 197 %in.lv.1 = load ptr , ptr %in.ptr, align 2 198 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 199 store i32 99, ptr %a, align 4 200 call void @escape_and_clobber(ptr %a) 201 ret i32 %in.lv.2 202} 203 204define i32 @test_captured_before_load_same_bb(ptr %in.ptr) { 205; CHECK-LABEL: @test_captured_before_load_same_bb( 206; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 207; CHECK-NEXT: store i32 55, ptr [[A]], align 4 208; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 209; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 210; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 211; CHECK-NEXT: store i32 99, ptr [[A]], align 4 212; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 213; CHECK-NEXT: ret i32 [[IN_LV_2]] 214; 215 %a = alloca i32, align 4 216 store i32 55, ptr %a 217 call void @escape_and_clobber(ptr %a) 218 %in.lv.1 = load ptr , ptr %in.ptr, align 2 219 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 220 store i32 99, ptr %a, align 4 221 call void @escape_and_clobber(ptr %a) 222 ret i32 %in.lv.2 223} 224 225define i32 @test_captured_sibling_path_to_load_other_blocks_1(ptr %in.ptr, i1 %c.1) { 226; CHECK-LABEL: @test_captured_sibling_path_to_load_other_blocks_1( 227; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 228; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 229; CHECK: then: 230; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 231; CHECK-NEXT: br label [[EXIT:%.*]] 232; CHECK: else: 233; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 234; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 235; CHECK-NEXT: br label [[EXIT]] 236; CHECK: exit: 237; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ] 238; CHECK-NEXT: store i32 99, ptr [[A]], align 4 239; CHECK-NEXT: call void @clobber() 240; CHECK-NEXT: ret i32 [[P]] 241; 242 %a = alloca i32, align 4 243 store i32 55, ptr %a 244 br i1 %c.1, label %then, label %else 245 246then: 247 call void @escape_writeonly(ptr %a) 248 br label %exit 249 250else: 251 %in.lv.1 = load ptr , ptr %in.ptr, align 2 252 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 253 br label %exit 254 255exit: 256 %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ] 257 store i32 99, ptr %a, align 4 258 call void @clobber() 259 ret i32 %p 260} 261 262define i32 @test_only_captured_sibling_path_with_ret_to_load_other_blocks(ptr %in.ptr, i1 %c.1) { 263; CHECK-LABEL: @test_only_captured_sibling_path_with_ret_to_load_other_blocks( 264; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 265; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 266; CHECK: then: 267; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 268; CHECK-NEXT: ret i32 0 269; CHECK: else: 270; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 271; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 272; CHECK-NEXT: br label [[EXIT:%.*]] 273; CHECK: exit: 274; CHECK-NEXT: call void @clobber() 275; CHECK-NEXT: ret i32 [[IN_LV_2]] 276; 277 %a = alloca i32, align 4 278 store i32 55, ptr %a 279 br i1 %c.1, label %then, label %else 280 281then: 282 call void @escape_writeonly(ptr %a) 283 ret i32 0 284 285else: 286 %in.lv.1 = load ptr , ptr %in.ptr, align 2 287 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 288 br label %exit 289 290exit: 291 store i32 99, ptr %a, align 4 292 call void @clobber() 293 ret i32 %in.lv.2 294} 295 296define i32 @test_captured_before_load_other_blocks_2(ptr %in.ptr, i1 %c.1) { 297; CHECK-LABEL: @test_captured_before_load_other_blocks_2( 298; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 299; CHECK-NEXT: store i32 55, ptr [[A]], align 4 300; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 301; CHECK: then: 302; CHECK-NEXT: br label [[EXIT:%.*]] 303; CHECK: else: 304; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 305; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 306; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 307; CHECK-NEXT: br label [[EXIT]] 308; CHECK: exit: 309; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ] 310; CHECK-NEXT: store i32 99, ptr [[A]], align 4 311; CHECK-NEXT: call void @clobber() 312; CHECK-NEXT: ret i32 [[P]] 313; 314 %a = alloca i32, align 4 315 store i32 55, ptr %a 316 br i1 %c.1, label %then, label %else 317 318then: 319 br label %exit 320 321else: 322 call void @escape_and_clobber(ptr %a) 323 %in.lv.1 = load ptr , ptr %in.ptr, align 2 324 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 325 br label %exit 326 327exit: 328 %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ] 329 store i32 99, ptr %a, align 4 330 call void @clobber() 331 ret i32 %p 332} 333 334define i32 @test_captured_before_load_other_blocks_4(ptr %in.ptr, i1 %c.1) { 335; CHECK-LABEL: @test_captured_before_load_other_blocks_4( 336; CHECK-NEXT: entry: 337; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 338; CHECK-NEXT: store i32 55, ptr [[A]], align 4 339; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 340; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 341; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 342; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 343; CHECK: then: 344; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 345; CHECK-NEXT: br label [[EXIT]] 346; CHECK: exit: 347; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ENTRY:%.*]] ] 348; CHECK-NEXT: store i32 99, ptr [[A]], align 4 349; CHECK-NEXT: call void @clobber() 350; CHECK-NEXT: ret i32 [[P]] 351; 352entry: 353 %a = alloca i32, align 4 354 store i32 55, ptr %a 355 call void @escape_writeonly(ptr %a) 356 %in.lv.1 = load ptr , ptr %in.ptr, align 2 357 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 358 br i1 %c.1, label %then, label %exit 359 360then: 361 call void @escape_writeonly(ptr %a) 362 br label %exit 363 364exit: 365 %p = phi i32 [ 0, %then ], [ %in.lv.2, %entry ] 366 store i32 99, ptr %a, align 4 367 call void @clobber() 368 ret i32 %p 369} 370 371define i32 @test_captured_before_load_other_blocks_5(ptr %in.ptr, i1 %c.1) { 372; CHECK-LABEL: @test_captured_before_load_other_blocks_5( 373; CHECK-NEXT: entry: 374; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 375; CHECK-NEXT: store i32 55, ptr [[A]], align 4 376; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 377; CHECK: then: 378; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 379; CHECK-NEXT: br label [[EXIT]] 380; CHECK: exit: 381; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 382; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 383; CHECK-NEXT: store i32 99, ptr [[A]], align 4 384; CHECK-NEXT: call void @clobber() 385; CHECK-NEXT: ret i32 [[IN_LV_2]] 386; 387entry: 388 %a = alloca i32, align 4 389 store i32 55, ptr %a 390 br i1 %c.1, label %then, label %exit 391 392then: 393 call void @escape_writeonly(ptr %a) 394 br label %exit 395 396exit: 397 %in.lv.1 = load ptr , ptr %in.ptr, align 2 398 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 399 store i32 99, ptr %a, align 4 400 call void @clobber() 401 ret i32 %in.lv.2 402} 403 404define i32 @test_captured_before_load_other_blocks_6(ptr %in.ptr, i1 %c.1) { 405; CHECK-LABEL: @test_captured_before_load_other_blocks_6( 406; CHECK-NEXT: entry: 407; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 408; CHECK-NEXT: store i32 55, ptr [[A]], align 4 409; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 410; CHECK: then: 411; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 412; CHECK-NEXT: br label [[EXIT]] 413; CHECK: exit: 414; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 415; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 416; CHECK-NEXT: store i32 99, ptr [[A]], align 4 417; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 418; CHECK-NEXT: call void @clobber() 419; CHECK-NEXT: ret i32 [[IN_LV_2]] 420; 421entry: 422 %a = alloca i32, align 4 423 store i32 55, ptr %a 424 br i1 %c.1, label %then, label %exit 425 426then: 427 call void @escape_writeonly(ptr %a) 428 br label %exit 429 430exit: 431 %in.lv.1 = load ptr , ptr %in.ptr, align 2 432 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 433 store i32 99, ptr %a, align 4 434 call void @escape_writeonly(ptr %a) 435 call void @clobber() 436 ret i32 %in.lv.2 437} 438 439define i32 @test_not_captured_before_load_other_blocks_1(ptr %in.ptr, i1 %c.1) { 440; CHECK-LABEL: @test_not_captured_before_load_other_blocks_1( 441; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 442; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 443; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 444; CHECK-NEXT: store i32 99, ptr [[A]], align 4 445; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 446; CHECK: then: 447; CHECK-NEXT: br label [[EXIT:%.*]] 448; CHECK: else: 449; CHECK-NEXT: br label [[EXIT]] 450; CHECK: exit: 451; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 452; CHECK-NEXT: ret i32 [[IN_LV_2]] 453; 454 %a = alloca i32, align 4 455 store i32 55, ptr %a 456 %in.lv.1 = load ptr , ptr %in.ptr, align 2 457 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 458 store i32 99, ptr %a, align 4 459 br i1 %c.1, label %then, label %else 460 461then: 462 br label %exit 463 464else: 465 br label %exit 466 467exit: 468 call void @escape_and_clobber(ptr %a) 469 ret i32 %in.lv.2 470} 471 472define i32 @test_not_captured_before_load_other_blocks_2(ptr %in.ptr, i1 %c.1) { 473; CHECK-LABEL: @test_not_captured_before_load_other_blocks_2( 474; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 475; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 476; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 477; CHECK-NEXT: store i32 99, ptr [[A]], align 4 478; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 479; CHECK: then: 480; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 481; CHECK-NEXT: br label [[EXIT:%.*]] 482; CHECK: else: 483; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 484; CHECK-NEXT: br label [[EXIT]] 485; CHECK: exit: 486; CHECK-NEXT: ret i32 [[IN_LV_2]] 487; 488 %a = alloca i32, align 4 489 store i32 55, ptr %a 490 %in.lv.1 = load ptr , ptr %in.ptr, align 2 491 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 492 store i32 99, ptr %a, align 4 493 br i1 %c.1, label %then, label %else 494 495then: 496 call void @escape_and_clobber(ptr %a) 497 br label %exit 498 499else: 500 call void @escape_and_clobber(ptr %a) 501 br label %exit 502 503exit: 504 ret i32 %in.lv.2 505} 506 507define i32 @test_not_captured_before_load_other_blocks_3(ptr %in.ptr, i1 %c.1) { 508; CHECK-LABEL: @test_not_captured_before_load_other_blocks_3( 509; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 510; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 511; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 512; CHECK-NEXT: store i32 99, ptr [[A]], align 4 513; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 514; CHECK: then: 515; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 516; CHECK-NEXT: br label [[EXIT:%.*]] 517; CHECK: else: 518; CHECK-NEXT: br label [[EXIT]] 519; CHECK: exit: 520; CHECK-NEXT: ret i32 [[IN_LV_2]] 521; 522 %a = alloca i32, align 4 523 store i32 55, ptr %a 524 %in.lv.1 = load ptr , ptr %in.ptr, align 2 525 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 526 store i32 99, ptr %a, align 4 527 br i1 %c.1, label %then, label %else 528 529then: 530 call void @escape_and_clobber(ptr %a) 531 br label %exit 532 533else: 534 br label %exit 535 536exit: 537 ret i32 %in.lv.2 538} 539 540define i32 @test_not_captured_before_load_other_blocks_4(ptr %in.ptr, i1 %c.1) { 541; CHECK-LABEL: @test_not_captured_before_load_other_blocks_4( 542; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 543; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 544; CHECK: then: 545; CHECK-NEXT: br label [[EXIT:%.*]] 546; CHECK: else: 547; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 548; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 549; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 550; CHECK-NEXT: br label [[EXIT]] 551; CHECK: exit: 552; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ] 553; CHECK-NEXT: store i32 99, ptr [[A]], align 4 554; CHECK-NEXT: call void @clobber() 555; CHECK-NEXT: ret i32 [[P]] 556; 557 %a = alloca i32, align 4 558 store i32 55, ptr %a 559 br i1 %c.1, label %then, label %else 560 561then: 562 br label %exit 563 564else: 565 %in.lv.1 = load ptr , ptr %in.ptr, align 2 566 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 567 call void @escape_writeonly(ptr %a) 568 br label %exit 569 570exit: 571 %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ] 572 store i32 99, ptr %a, align 4 573 call void @clobber() 574 ret i32 %p 575} 576 577define i32 @test_not_captured_before_load_other_blocks_5(ptr %in.ptr, i1 %c.1) { 578; CHECK-LABEL: @test_not_captured_before_load_other_blocks_5( 579; CHECK-NEXT: entry: 580; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 581; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 582; CHECK: then: 583; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 584; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 585; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 586; CHECK-NEXT: br label [[EXIT]] 587; CHECK: exit: 588; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ENTRY:%.*]] ] 589; CHECK-NEXT: store i32 99, ptr [[A]], align 4 590; CHECK-NEXT: call void @clobber() 591; CHECK-NEXT: ret i32 [[P]] 592; 593entry: 594 %a = alloca i32, align 4 595 store i32 55, ptr %a 596 br i1 %c.1, label %then, label %exit 597 598then: 599 %in.lv.1 = load ptr , ptr %in.ptr, align 2 600 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 601 call void @escape_writeonly(ptr %a) 602 br label %exit 603 604exit: 605 %p = phi i32 [ %in.lv.2, %then ], [ 0, %entry ] 606 store i32 99, ptr %a, align 4 607 call void @clobber() 608 ret i32 %p 609} 610 611define i32 @test_not_captured_before_load_other_blocks_6(ptr %in.ptr, i1 %c.1) { 612; CHECK-LABEL: @test_not_captured_before_load_other_blocks_6( 613; CHECK-NEXT: entry: 614; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 615; CHECK-NEXT: store i32 55, ptr [[A]], align 4 616; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 617; CHECK: then: 618; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 619; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 620; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 621; CHECK-NEXT: br label [[EXIT]] 622; CHECK: exit: 623; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ENTRY:%.*]] ] 624; CHECK-NEXT: store i32 99, ptr [[A]], align 4 625; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 626; CHECK-NEXT: call void @clobber() 627; CHECK-NEXT: ret i32 [[P]] 628; 629entry: 630 %a = alloca i32, align 4 631 store i32 55, ptr %a 632 br i1 %c.1, label %then, label %exit 633 634then: 635 %in.lv.1 = load ptr , ptr %in.ptr, align 2 636 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 637 call void @escape_writeonly(ptr %a) 638 br label %exit 639 640exit: 641 %p = phi i32 [ %in.lv.2, %then ], [ 0, %entry ] 642 store i32 99, ptr %a, align 4 643 call void @escape_writeonly(ptr %a) 644 call void @clobber() 645 ret i32 %p 646} 647 648define i32 @test_not_captured_before_load_other_blocks_7(ptr %in.ptr, i1 %c.1) { 649; CHECK-LABEL: @test_not_captured_before_load_other_blocks_7( 650; CHECK-NEXT: entry: 651; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 652; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 653; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 654; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 655; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] 656; CHECK: then: 657; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 658; CHECK-NEXT: br label [[EXIT]] 659; CHECK: exit: 660; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ENTRY:%.*]] ] 661; CHECK-NEXT: store i32 99, ptr [[A]], align 4 662; CHECK-NEXT: call void @clobber() 663; CHECK-NEXT: ret i32 [[P]] 664; 665entry: 666 %a = alloca i32, align 4 667 store i32 55, ptr %a 668 %in.lv.1 = load ptr , ptr %in.ptr, align 2 669 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 670 call void @escape_writeonly(ptr %a) 671 br i1 %c.1, label %then, label %exit 672 673then: 674 call void @escape_writeonly(ptr %a) 675 br label %exit 676 677exit: 678 %p = phi i32 [ 0, %then ], [ %in.lv.2, %entry ] 679 store i32 99, ptr %a, align 4 680 call void @clobber() 681 ret i32 %p 682} 683 684define i32 @test_not_captured_before_load_same_bb_but_read(ptr %in.ptr) { 685; CHECK-LABEL: @test_not_captured_before_load_same_bb_but_read( 686; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 687; CHECK-NEXT: store i32 55, ptr [[A]], align 4 688; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 689; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 690; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[A]], align 4 691; CHECK-NEXT: store i32 99, ptr [[A]], align 4 692; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 693; CHECK-NEXT: [[RES:%.*]] = add i32 [[IN_LV_2]], [[LV]] 694; CHECK-NEXT: ret i32 [[RES]] 695; 696 %a = alloca i32, align 4 697 store i32 55, ptr %a 698 %in.lv.1 = load ptr , ptr %in.ptr, align 2 699 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 700 %lv = load i32, ptr %a 701 store i32 99, ptr %a, align 4 702 call void @escape_and_clobber(ptr %a) 703 %res = add i32 %in.lv.2, %lv 704 ret i32 %res 705} 706 707define i32 @test_not_captured_before_load_may_alias_same_bb_but_read(ptr %in.ptr, ptr %b, i1 %c) { 708; CHECK-LABEL: @test_not_captured_before_load_may_alias_same_bb_but_read( 709; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 710; CHECK-NEXT: store i32 55, ptr [[A]], align 4 711; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 712; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 713; CHECK-NEXT: [[PTR:%.*]] = select i1 [[C:%.*]], ptr [[A]], ptr [[B:%.*]] 714; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[PTR]], align 4 715; CHECK-NEXT: store i32 99, ptr [[A]], align 4 716; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 717; CHECK-NEXT: [[RES:%.*]] = add i32 [[IN_LV_2]], [[LV]] 718; CHECK-NEXT: ret i32 [[RES]] 719; 720 %a = alloca i32, align 4 721 store i32 55, ptr %a 722 %in.lv.1 = load ptr , ptr %in.ptr, align 2 723 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 724 %ptr = select i1 %c, ptr %a, ptr %b 725 %lv = load i32, ptr %ptr 726 store i32 99, ptr %a, align 4 727 call void @escape_and_clobber(ptr %a) 728 %res = add i32 %in.lv.2, %lv 729 ret i32 %res 730} 731 732define i32 @test_captured_after_loop(ptr %in.ptr, i1 %c.1) { 733; CHECK-LABEL: @test_captured_after_loop( 734; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 735; CHECK-NEXT: br label [[LOOP:%.*]] 736; CHECK: loop: 737; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 738; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 739; CHECK-NEXT: store i32 99, ptr [[A]], align 4 740; CHECK-NEXT: br i1 [[C_1:%.*]], label [[LOOP]], label [[EXIT:%.*]] 741; CHECK: exit: 742; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 743; CHECK-NEXT: ret i32 [[IN_LV_2]] 744; 745 %a = alloca i32, align 4 746 store i32 55, ptr %a 747 br label %loop 748 749loop: 750 %in.lv.1 = load ptr , ptr %in.ptr, align 2 751 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 752 store i32 99, ptr %a, align 4 753 br i1 %c.1, label %loop, label %exit 754 755exit: 756 call void @escape_and_clobber(ptr %a) 757 ret i32 %in.lv.2 758} 759 760define i32 @test_captured_in_loop(ptr %in.ptr, i1 %c.1) { 761; CHECK-LABEL: @test_captured_in_loop( 762; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 763; CHECK-NEXT: store i32 55, ptr [[A]], align 4 764; CHECK-NEXT: br label [[LOOP:%.*]] 765; CHECK: loop: 766; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 767; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 768; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 769; CHECK-NEXT: store i32 99, ptr [[A]], align 4 770; CHECK-NEXT: br i1 [[C_1:%.*]], label [[LOOP]], label [[EXIT:%.*]] 771; CHECK: exit: 772; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 773; CHECK-NEXT: ret i32 [[IN_LV_2]] 774; 775 %a = alloca i32, align 4 776 store i32 55, ptr %a 777 br label %loop 778 779loop: 780 %in.lv.1 = load ptr , ptr %in.ptr, align 2 781 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 782 call void @escape_writeonly(ptr %a) 783 store i32 99, ptr %a, align 4 784 br i1 %c.1, label %loop, label %exit 785 786exit: 787 call void @escape_and_clobber(ptr %a) 788 ret i32 %in.lv.2 789} 790 791declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) 792 793@global = external global ptr 794 795define void @test_memset_not_captured_before_load() { 796; CHECK-LABEL: @test_memset_not_captured_before_load( 797; CHECK-NEXT: [[A:%.*]] = alloca [2 x i32], align 4 798; CHECK-NEXT: [[LV_1:%.*]] = load ptr, ptr @global, align 8 799; CHECK-NEXT: store i32 1, ptr [[A]], align 4 800; CHECK-NEXT: [[GEP_LV:%.*]] = getelementptr inbounds [10 x i16], ptr [[LV_1]], i64 0, i32 1 801; CHECK-NEXT: [[LV_2:%.*]] = load i16, ptr [[GEP_LV]], align 2 802; CHECK-NEXT: [[EXT_LV_2:%.*]] = zext i16 [[LV_2]] to i32 803; CHECK-NEXT: [[GEP_A_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1 804; CHECK-NEXT: store i32 [[EXT_LV_2]], ptr [[GEP_A_1]], align 4 805; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 806; CHECK-NEXT: ret void 807; 808 %a = alloca [2 x i32], align 4 809 call void @llvm.memset.p0.i32(ptr %a, i8 0, i32 8, i1 false) 810 %lv.1 = load ptr, ptr @global, align 8 811 store i32 1, ptr %a, align 4 812 %gep.lv = getelementptr inbounds [10 x i16], ptr %lv.1, i64 0, i32 1 813 %lv.2 = load i16, ptr %gep.lv, align 2 814 %ext.lv.2 = zext i16 %lv.2 to i32 815 %gep.a.1 = getelementptr inbounds [2 x i32], ptr %a, i32 0, i32 1 816 store i32 %ext.lv.2, ptr %gep.a.1, align 4 817 call void @escape_and_clobber(ptr %a) 818 ret void 819} 820 821define void @test_test_not_captured_before_load(i1 %c.1) { 822; CHECK-LABEL: @test_test_not_captured_before_load( 823; CHECK-NEXT: bb: 824; CHECK-NEXT: [[A:%.*]] = alloca [2 x i32], align 4 825; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 4 826; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr align 1 [[TMP0]], i8 0, i32 4, i1 false) 827; CHECK-NEXT: [[LV_1:%.*]] = load ptr, ptr @global, align 8 828; CHECK-NEXT: [[GEP_LV:%.*]] = getelementptr inbounds [10 x i16], ptr [[LV_1]], i64 0, i32 1 829; CHECK-NEXT: [[LV_2:%.*]] = load i16, ptr [[GEP_LV]], align 2 830; CHECK-NEXT: store i32 1, ptr [[A]], align 4 831; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 832; CHECK: then: 833; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 834; CHECK-NEXT: br label [[EXIT:%.*]] 835; CHECK: else: 836; CHECK-NEXT: br label [[EXIT]] 837; CHECK: exit: 838; CHECK-NEXT: [[EXT_LV_2:%.*]] = zext i16 [[LV_2]] to i32 839; CHECK-NEXT: [[GEP_A_1:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1 840; CHECK-NEXT: store i32 [[EXT_LV_2]], ptr [[GEP_A_1]], align 4 841; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 842; CHECK-NEXT: ret void 843; 844bb: 845 %a = alloca [2 x i32], align 4 846 call void @llvm.memset.p0.i32(ptr %a, i8 0, i32 8, i1 false) 847 %lv.1 = load ptr, ptr @global, align 8 848 %gep.lv = getelementptr inbounds [10 x i16], ptr %lv.1, i64 0, i32 1 849 %lv.2 = load i16, ptr %gep.lv, align 2 850 store i32 1, ptr %a, align 4 851 br i1 %c.1, label %then, label %else 852 853then: 854 call void @escape_and_clobber(ptr %a) 855 br label %exit 856 857else: 858 br label %exit 859 860exit: 861 %ext.lv.2 = zext i16 %lv.2 to i32 862 %gep.a.1 = getelementptr inbounds [2 x i32], ptr %a, i32 0, i32 1 863 store i32 %ext.lv.2, ptr %gep.a.1, align 4 864 call void @escape_and_clobber(ptr %a) 865 ret void 866} 867 868declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0 869declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1 870 871declare void @use.i64(i64) 872 873define i64 @test_a_not_captured_at_all(ptr %ptr, ptr %ptr.2, i1 %c) { 874; CHECK-LABEL: @test_a_not_captured_at_all( 875; CHECK-NEXT: entry: 876; CHECK-NEXT: [[A:%.*]] = alloca i64, align 8 877; CHECK-NEXT: [[B:%.*]] = alloca i64, align 8 878; CHECK-NEXT: store ptr [[B]], ptr [[PTR:%.*]], align 8 879; CHECK-NEXT: [[LV_1:%.*]] = load ptr, ptr [[PTR_2:%.*]], align 8 880; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[THEN:%.*]] 881; CHECK: then: 882; CHECK-NEXT: [[LV_2:%.*]] = load i64, ptr [[LV_1]], align 4 883; CHECK-NEXT: call void @use.i64(i64 [[LV_2]]) 884; CHECK-NEXT: br label [[EXIT]] 885; CHECK: exit: 886; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[A]]) 887; CHECK-NEXT: call void @clobber() 888; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[A]], i8 0, i64 8, i1 false) 889; CHECK-NEXT: [[L:%.*]] = load i64, ptr [[A]], align 4 890; CHECK-NEXT: ret i64 [[L]] 891; 892entry: 893 %a = alloca i64, align 8 894 %b = alloca i64, align 8 895 store ptr %b, ptr %ptr, align 8 896 %lv.1 = load ptr, ptr %ptr.2, align 8 897 br i1 %c, label %exit, label %then 898 899then: 900 %lv.2 = load i64, ptr %lv.1 901 call void @use.i64(i64 %lv.2) 902 br label %exit 903 904exit: 905 call void @llvm.lifetime.start.p0(i64 8, ptr %a) 906 store i64 99, ptr %a 907 call void @clobber() 908 call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 8, i1 false) 909 %l = load i64, ptr %a 910 ret i64 %l 911} 912 913define i32 @test_not_captured_both_paths_1(ptr %in.ptr, i1 %c.1) { 914; CHECK-LABEL: @test_not_captured_both_paths_1( 915; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 916; CHECK-NEXT: store i32 55, ptr [[A]], align 4 917; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 918; CHECK: then: 919; CHECK-NEXT: store i32 99, ptr [[A]], align 4 920; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 921; CHECK-NEXT: br label [[EXIT:%.*]] 922; CHECK: else: 923; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 924; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 925; CHECK-NEXT: store i32 99, ptr [[A]], align 4 926; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 927; CHECK-NEXT: br label [[EXIT]] 928; CHECK: exit: 929; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[IN_LV_2]], [[ELSE]] ] 930; CHECK-NEXT: call void @clobber() 931; CHECK-NEXT: ret i32 [[P]] 932; 933 %a = alloca i32, align 4 934 store i32 55, ptr %a 935 br i1 %c.1, label %then, label %else 936 937then: 938 store i32 99, ptr %a, align 4 939 call void @escape_writeonly(ptr %a) 940 br label %exit 941 942else: 943 %in.lv.1 = load ptr , ptr %in.ptr, align 2 944 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 945 store i32 99, ptr %a, align 4 946 call void @escape_writeonly(ptr %a) 947 br label %exit 948 949exit: 950 %p = phi i32 [ 0, %then ], [ %in.lv.2, %else ] 951 call void @clobber() 952 ret i32 %p 953} 954 955define i32 @test_not_captured_both_paths_2(ptr %in.ptr, i1 %c.1) { 956; CHECK-LABEL: @test_not_captured_both_paths_2( 957; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 958; CHECK-NEXT: store i32 55, ptr [[A]], align 4 959; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 960; CHECK: then: 961; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 962; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 963; CHECK-NEXT: store i32 99, ptr [[A]], align 4 964; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 965; CHECK-NEXT: br label [[EXIT:%.*]] 966; CHECK: else: 967; CHECK-NEXT: store i32 99, ptr [[A]], align 4 968; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 969; CHECK-NEXT: br label [[EXIT]] 970; CHECK: exit: 971; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ELSE]] ] 972; CHECK-NEXT: call void @clobber() 973; CHECK-NEXT: ret i32 [[P]] 974; 975 %a = alloca i32, align 4 976 store i32 55, ptr %a 977 br i1 %c.1, label %then, label %else 978 979then: 980 %in.lv.1 = load ptr , ptr %in.ptr, align 2 981 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 982 store i32 99, ptr %a, align 4 983 call void @escape_writeonly(ptr %a) 984 br label %exit 985 986else: 987 store i32 99, ptr %a, align 4 988 call void @escape_writeonly(ptr %a) 989 br label %exit 990 991exit: 992 %p = phi i32 [ %in.lv.2, %then ], [ 0, %else ] 993 call void @clobber() 994 ret i32 %p 995} 996 997define i32 @test_captured_before_store_both_paths_2(ptr %in.ptr, i1 %c.1) { 998; CHECK-LABEL: @test_captured_before_store_both_paths_2( 999; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 1000; CHECK-NEXT: store i32 55, ptr [[A]], align 4 1001; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 1002; CHECK: then: 1003; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 1004; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 1005; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 1006; CHECK-NEXT: store i32 99, ptr [[A]], align 4 1007; CHECK-NEXT: br label [[EXIT:%.*]] 1008; CHECK: else: 1009; CHECK-NEXT: call void @escape_writeonly(ptr [[A]]) 1010; CHECK-NEXT: store i32 99, ptr [[A]], align 4 1011; CHECK-NEXT: br label [[EXIT]] 1012; CHECK: exit: 1013; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[IN_LV_2]], [[THEN]] ], [ 0, [[ELSE]] ] 1014; CHECK-NEXT: call void @clobber() 1015; CHECK-NEXT: ret i32 [[P]] 1016; 1017 %a = alloca i32, align 4 1018 store i32 55, ptr %a 1019 br i1 %c.1, label %then, label %else 1020 1021then: 1022 call void @escape_writeonly(ptr %a) 1023 %in.lv.1 = load ptr , ptr %in.ptr, align 2 1024 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 1025 store i32 99, ptr %a, align 4 1026 br label %exit 1027 1028else: 1029 call void @escape_writeonly(ptr %a) 1030 store i32 99, ptr %a, align 4 1031 br label %exit 1032 1033exit: 1034 %p = phi i32 [ %in.lv.2, %then ], [ 0, %else ] 1035 call void @clobber() 1036 ret i32 %p 1037} 1038 1039 1040declare noalias ptr @alloc() nounwind 1041 1042define i32 @test_not_captured_before_load_same_bb_noalias_call(ptr %in.ptr) { 1043; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_call( 1044; CHECK-NEXT: [[A:%.*]] = call ptr @alloc() 1045; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 1046; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 1047; CHECK-NEXT: store i32 99, ptr [[A]], align 4 1048; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 1049; CHECK-NEXT: ret i32 [[IN_LV_2]] 1050; 1051 %a = call ptr @alloc() 1052 store i32 55, ptr %a 1053 %in.lv.1 = load ptr , ptr %in.ptr, align 2 1054 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 1055 store i32 99, ptr %a, align 4 1056 call void @escape_and_clobber(ptr %a) 1057 ret i32 %in.lv.2 1058} 1059 1060define i32 @test_not_captured_before_load_same_bb_noalias_arg(ptr %in.ptr, ptr noalias %a) { 1061; CHECK-LABEL: @test_not_captured_before_load_same_bb_noalias_arg( 1062; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 1063; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 1064; CHECK-NEXT: store i32 99, ptr [[A:%.*]], align 4 1065; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 1066; CHECK-NEXT: ret i32 [[IN_LV_2]] 1067; 1068 store i32 55, ptr %a 1069 %in.lv.1 = load ptr , ptr %in.ptr, align 2 1070 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 1071 store i32 99, ptr %a, align 4 1072 call void @escape_and_clobber(ptr %a) 1073 ret i32 %in.lv.2 1074} 1075 1076define i32 @instruction_captures_multiple_objects(ptr %p.1, ptr %p.2, ptr %p.3, i1 %c) { 1077; CHECK-LABEL: @instruction_captures_multiple_objects( 1078; CHECK-NEXT: entry: 1079; CHECK-NEXT: [[A_1:%.*]] = alloca i32, align 4 1080; CHECK-NEXT: [[A_2:%.*]] = alloca i32, align 4 1081; CHECK-NEXT: store i32 0, ptr [[P_1:%.*]], align 8 1082; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]] 1083; CHECK: then: 1084; CHECK-NEXT: [[LV_2:%.*]] = load ptr, ptr [[P_2:%.*]], align 8 1085; CHECK-NEXT: [[LV_2_2:%.*]] = load i32, ptr [[LV_2]], align 4 1086; CHECK-NEXT: ret i32 [[LV_2_2]] 1087; CHECK: else: 1088; CHECK-NEXT: [[LV_3:%.*]] = load ptr, ptr [[P_3:%.*]], align 8 1089; CHECK-NEXT: [[LV_3_2:%.*]] = load i32, ptr [[LV_3]], align 4 1090; CHECK-NEXT: call void @capture_and_clobber_multiple(ptr [[A_1]], ptr [[A_2]]) 1091; CHECK-NEXT: ret i32 [[LV_3_2]] 1092; 1093entry: 1094 %a.1 = alloca i32 1095 %a.2 = alloca i32 1096 store i32 0, ptr %p.1, align 8 1097 br i1 %c, label %then, label %else 1098 1099then: 1100 store i32 99, ptr %a.2, align 4 1101 %lv.2 = load ptr, ptr %p.2 1102 %lv.2.2 = load i32, ptr %lv.2 1103 store i32 0, ptr %a.1, align 8 1104 ret i32 %lv.2.2 1105 1106else: 1107 %lv.3 = load ptr, ptr %p.3 1108 %lv.3.2 = load i32, ptr %lv.3 1109 call void @capture_and_clobber_multiple(ptr %a.1, ptr %a.2) 1110 ret i32 %lv.3.2 1111} 1112 1113declare void @capture_and_clobber_multiple(ptr, ptr) 1114 1115declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) 1116 1117define i64 @earliest_escape_ptrtoint(ptr %p.1) { 1118; CHECK-LABEL: @earliest_escape_ptrtoint( 1119; CHECK-NEXT: entry: 1120; CHECK-NEXT: [[A_1:%.*]] = alloca i64, align 8 1121; CHECK-NEXT: [[A_2:%.*]] = alloca i64, align 8 1122; CHECK-NEXT: [[LV_1:%.*]] = load ptr, ptr [[P_1:%.*]], align 8 1123; CHECK-NEXT: [[LV_2:%.*]] = load i64, ptr [[LV_1]], align 4 1124; CHECK-NEXT: store ptr [[A_1]], ptr [[P_1]], align 8 1125; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[A_2]]) 1126; CHECK-NEXT: ret i64 [[LV_2]] 1127; 1128entry: 1129 %a.1 = alloca i64 1130 %a.2 = alloca i64 1131 store i64 99, ptr %a.1 1132 %lv.1 = load ptr, ptr %p.1 1133 %lv.2 = load i64, ptr %lv.1 1134 store ptr %a.1, ptr %p.1, align 8 1135 %int = ptrtoint ptr %a.2 to i64 1136 store i64 %int , ptr %a.2, align 8 1137 call void @llvm.lifetime.end.p0(i64 8, ptr %a.2) 1138 ret i64 %lv.2 1139} 1140 1141define i32 @test_not_captured_before_load_of_ptrtoint(i64 %in) { 1142; CHECK-LABEL: @test_not_captured_before_load_of_ptrtoint( 1143; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 1144; CHECK-NEXT: [[IN_PTR:%.*]] = inttoptr i64 [[IN:%.*]] to ptr 1145; CHECK-NEXT: [[IN_PTR_LOAD:%.*]] = load i32, ptr [[IN_PTR]], align 4 1146; CHECK-NEXT: store i32 99, ptr [[A]], align 4 1147; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 1148; CHECK-NEXT: ret i32 [[IN_PTR_LOAD]] 1149; 1150 %a = alloca i32, align 4 1151 store i32 55, ptr %a 1152 %in.ptr = inttoptr i64 %in to ptr 1153 %in.ptr.load = load i32, ptr %in.ptr 1154 store i32 99, ptr %a 1155 call void @escape_and_clobber(ptr %a) 1156 ret i32 %in.ptr.load 1157} 1158 1159declare ptr @getptr() 1160 1161define i32 @test_not_captured_before_load_of_call() { 1162; CHECK-LABEL: @test_not_captured_before_load_of_call( 1163; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 1164; CHECK-NEXT: [[IN_PTR:%.*]] = call ptr @getptr() #[[ATTR4:[0-9]+]] 1165; CHECK-NEXT: [[IN_PTR_LOAD:%.*]] = load i32, ptr [[IN_PTR]], align 4 1166; CHECK-NEXT: store i32 99, ptr [[A]], align 4 1167; CHECK-NEXT: call void @escape_and_clobber(ptr [[A]]) 1168; CHECK-NEXT: ret i32 [[IN_PTR_LOAD]] 1169; 1170 %a = alloca i32, align 4 1171 store i32 55, ptr %a 1172 %in.ptr = call ptr @getptr() readnone 1173 %in.ptr.load = load i32, ptr %in.ptr 1174 store i32 99, ptr %a 1175 call void @escape_and_clobber(ptr %a) 1176 ret i32 %in.ptr.load 1177} 1178 1179define i32 @test_not_captured_multiple_objects(i1 %c, ptr %in.ptr) { 1180; CHECK-LABEL: @test_not_captured_multiple_objects( 1181; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 1182; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 1183; CHECK-NEXT: [[O:%.*]] = select i1 [[C:%.*]], ptr [[A]], ptr [[B]] 1184; CHECK-NEXT: [[IN_LV_1:%.*]] = load ptr, ptr [[IN_PTR:%.*]], align 2 1185; CHECK-NEXT: [[IN_LV_2:%.*]] = load i32, ptr [[IN_LV_1]], align 2 1186; CHECK-NEXT: store i32 99, ptr [[O]], align 4 1187; CHECK-NEXT: call void @escape_and_clobber(ptr [[O]]) 1188; CHECK-NEXT: ret i32 [[IN_LV_2]] 1189; 1190 %a = alloca i32, align 4 1191 %b = alloca i32, align 4 1192 %o = select i1 %c, ptr %a, ptr %b 1193 store i32 55, ptr %o 1194 %in.lv.1 = load ptr , ptr %in.ptr, align 2 1195 %in.lv.2 = load i32 , ptr %in.lv.1, align 2 1196 store i32 99, ptr %o 1197 call void @escape_and_clobber(ptr %o) 1198 ret i32 %in.lv.2 1199} 1200