1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -basic-aa -enable-load-pre -enable-pre -lcssa -gvn -S < %s | FileCheck %s 3 4declare void @side_effect() nofree 5declare i1 @side_effect_cond() nofree 6declare void @may_free_memory() 7 8declare i32 @personality_function() 9 10; We can PRE the load from gc-managed memory away from the hot path. 11define i32 @test_load_on_cold_path_gc(i32 addrspace(1)* %p) gc "statepoint-example" personality i32 ()* @"personality_function" { 12; CHECK-LABEL: @test_load_on_cold_path_gc( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[X_PRE1:%.*]] = load i32, i32 addrspace(1)* [[P:%.*]], align 4 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[X_PRE1]], [[ENTRY:%.*]] ], [ [[X2:%.*]], [[BACKEDGE:%.*]] ] 18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE]] ] 19; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 20; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 21; CHECK: hot_path: 22; CHECK-NEXT: br label [[BACKEDGE]] 23; CHECK: cold_path: 24; CHECK-NEXT: call void @may_free_memory() 25; CHECK-NEXT: [[X_PRE:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4 26; CHECK-NEXT: br label [[BACKEDGE]] 27; CHECK: backedge: 28; CHECK-NEXT: [[X2]] = phi i32 [ [[X_PRE]], [[COLD_PATH]] ], [ [[X]], [[HOT_PATH]] ] 29; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 30; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 31; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 32; CHECK: exit: 33; CHECK-NEXT: ret i32 [[X]] 34; 35entry: 36 br label %loop 37 38loop: 39 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 40 %x = load i32, i32 addrspace(1)* %p 41 %cond = icmp ne i32 %x, 0 42 br i1 %cond, label %hot_path, label %cold_path 43 44hot_path: 45 br label %backedge 46 47cold_path: 48 call void @may_free_memory() 49 br label %backedge 50 51backedge: 52 %iv.next = add i32 %iv, %x 53 %loop.cond = icmp ult i32 %iv.next, 1000 54 br i1 %loop.cond, label %loop, label %exit 55 56exit: 57 ret i32 %x 58} 59 60; Do not PRE here because a loop-variant pointer. 61define i32 @test_load_on_cold_path_gc_variant_neg(i32 addrspace(1)* addrspace(1)* %pp) gc "statepoint-example" personality i32 ()* @"personality_function" { 62; CHECK-LABEL: @test_load_on_cold_path_gc_variant_neg( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: br label [[LOOP:%.*]] 65; CHECK: loop: 66; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 67; CHECK-NEXT: [[P:%.*]] = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* [[PP:%.*]], align 8 68; CHECK-NEXT: [[X:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4 69; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 70; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 71; CHECK: hot_path: 72; CHECK-NEXT: br label [[BACKEDGE]] 73; CHECK: cold_path: 74; CHECK-NEXT: call void @may_free_memory() 75; CHECK-NEXT: br label [[BACKEDGE]] 76; CHECK: backedge: 77; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 78; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 79; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 80; CHECK: exit: 81; CHECK-NEXT: ret i32 [[X]] 82; 83entry: 84 br label %loop 85 86loop: 87 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 88 %p = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pp 89 %x = load i32, i32 addrspace(1)* %p 90 %cond = icmp ne i32 %x, 0 91 br i1 %cond, label %hot_path, label %cold_path 92 93hot_path: 94 br label %backedge 95 96cold_path: 97 call void @may_free_memory() 98 br label %backedge 99 100backedge: 101 %iv.next = add i32 %iv, %x 102 %loop.cond = icmp ult i32 %iv.next, 1000 103 br i1 %loop.cond, label %loop, label %exit 104 105exit: 106 ret i32 %x 107} 108 109 110; TODO: We can PRE the load away from the hot path. 111define i32 @test_load_on_cold_path(i32* %p) { 112; CHECK-LABEL: @test_load_on_cold_path( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: br label [[LOOP:%.*]] 115; CHECK: loop: 116; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 117; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 118; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 119; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 120; CHECK: hot_path: 121; CHECK-NEXT: br label [[BACKEDGE]] 122; CHECK: cold_path: 123; CHECK-NEXT: call void @side_effect() #[[ATTR0:[0-9]+]] 124; CHECK-NEXT: br label [[BACKEDGE]] 125; CHECK: backedge: 126; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 127; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 128; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 129; CHECK: exit: 130; CHECK-NEXT: ret i32 [[X]] 131; 132entry: 133 br label %loop 134 135loop: 136 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 137 %x = load i32, i32* %p 138 %cond = icmp ne i32 %x, 0 139 br i1 %cond, label %hot_path, label %cold_path 140 141hot_path: 142 br label %backedge 143 144cold_path: 145 call void @side_effect() nofree 146 br label %backedge 147 148backedge: 149 %iv.next = add i32 %iv, %x 150 %loop.cond = icmp ult i32 %iv.next, 1000 151 br i1 %loop.cond, label %loop, label %exit 152 153exit: 154 ret i32 %x 155} 156 157; We should NOT PRE here because the function on the cold path may possibly 158; free the memory under the pointer. 159define i32 @test_load_on_cold_path_may_free_memory_neg(i32* %p) { 160; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_neg( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: br label [[LOOP:%.*]] 163; CHECK: loop: 164; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 165; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 166; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 167; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 168; CHECK: hot_path: 169; CHECK-NEXT: br label [[BACKEDGE]] 170; CHECK: cold_path: 171; CHECK-NEXT: call void @may_free_memory() 172; CHECK-NEXT: br label [[BACKEDGE]] 173; CHECK: backedge: 174; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 175; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 176; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 177; CHECK: exit: 178; CHECK-NEXT: ret i32 [[X]] 179; 180entry: 181 br label %loop 182 183loop: 184 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 185 %x = load i32, i32* %p 186 %cond = icmp ne i32 %x, 0 187 br i1 %cond, label %hot_path, label %cold_path 188 189hot_path: 190 br label %backedge 191 192cold_path: 193 call void @may_free_memory() 194 br label %backedge 195 196backedge: 197 %iv.next = add i32 %iv, %x 198 %loop.cond = icmp ult i32 %iv.next, 1000 199 br i1 %loop.cond, label %loop, label %exit 200 201exit: 202 ret i32 %x 203} 204 205declare void @may_modify_or_free_pointer(i32* %p) 206 207; TODO: Despite the fact that the function may free memory in general, it 208; cannot free memory allocated by alloca. 209define i32 @test_load_on_cold_path_may_free_memory_alloca() { 210; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca( 211; CHECK-NEXT: entry: 212; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4 213; CHECK-NEXT: call void @may_modify_or_free_pointer(i32* [[P]]) 214; CHECK-NEXT: br label [[LOOP:%.*]] 215; CHECK: loop: 216; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 217; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 218; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 219; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 220; CHECK: hot_path: 221; CHECK-NEXT: br label [[BACKEDGE]] 222; CHECK: cold_path: 223; CHECK-NEXT: call void @may_modify_or_free_pointer(i32* [[P]]) 224; CHECK-NEXT: br label [[BACKEDGE]] 225; CHECK: backedge: 226; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 227; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 228; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 229; CHECK: exit: 230; CHECK-NEXT: ret i32 [[X]] 231; 232entry: 233 %p = alloca i32 234 call void @may_modify_or_free_pointer(i32* %p) 235 br label %loop 236 237loop: 238 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 239 %x = load i32, i32* %p 240 %cond = icmp ne i32 %x, 0 241 br i1 %cond, label %hot_path, label %cold_path 242 243hot_path: 244 br label %backedge 245 246cold_path: 247 call void @may_modify_or_free_pointer(i32* %p) 248 br label %backedge 249 250backedge: 251 %iv.next = add i32 %iv, %x 252 %loop.cond = icmp ult i32 %iv.next, 1000 253 br i1 %loop.cond, label %loop, label %exit 254 255exit: 256 ret i32 %x 257} 258 259 260; PRE here is meaningless, so we should not do it. 261define i32 @test_load_on_both_paths(i32* %p) { 262; CHECK-LABEL: @test_load_on_both_paths( 263; CHECK-NEXT: entry: 264; CHECK-NEXT: br label [[LOOP:%.*]] 265; CHECK: loop: 266; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 267; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 268; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 269; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 270; CHECK: hot_path: 271; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 272; CHECK-NEXT: br label [[BACKEDGE]] 273; CHECK: cold_path: 274; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 275; CHECK-NEXT: br label [[BACKEDGE]] 276; CHECK: backedge: 277; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 278; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 279; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 280; CHECK: exit: 281; CHECK-NEXT: ret i32 [[X]] 282; 283entry: 284 br label %loop 285 286loop: 287 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 288 %x = load i32, i32* %p 289 %cond = icmp ne i32 %x, 0 290 br i1 %cond, label %hot_path, label %cold_path 291 292hot_path: 293 call void @side_effect() nofree 294 br label %backedge 295 296cold_path: 297 call void @side_effect() nofree 298 br label %backedge 299 300backedge: 301 %iv.next = add i32 %iv, %x 302 %loop.cond = icmp ult i32 %iv.next, 1000 303 br i1 %loop.cond, label %loop, label %exit 304 305exit: 306 ret i32 %x 307} 308 309 310; We could PRE here, but it doesn't seem very profitable. 311define i32 @test_load_on_backedge(i32* %p) { 312; CHECK-LABEL: @test_load_on_backedge( 313; CHECK-NEXT: entry: 314; CHECK-NEXT: br label [[LOOP:%.*]] 315; CHECK: loop: 316; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 317; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 318; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 319; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 320; CHECK: hot_path: 321; CHECK-NEXT: br label [[BACKEDGE]] 322; CHECK: cold_path: 323; CHECK-NEXT: br label [[BACKEDGE]] 324; CHECK: backedge: 325; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 326; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 327; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 328; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 329; CHECK: exit: 330; CHECK-NEXT: ret i32 [[X]] 331; 332entry: 333 br label %loop 334 335loop: 336 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 337 %x = load i32, i32* %p 338 %cond = icmp ne i32 %x, 0 339 br i1 %cond, label %hot_path, label %cold_path 340 341hot_path: 342 br label %backedge 343 344cold_path: 345 br label %backedge 346 347backedge: 348 %iv.next = add i32 %iv, %x 349 call void @side_effect() nofree 350 %loop.cond = icmp ult i32 %iv.next, 1000 351 br i1 %loop.cond, label %loop, label %exit 352 353exit: 354 ret i32 %x 355} 356 357; TODO: We can PRE via splitting of the critical edge in the cold path. 358define i32 @test_load_on_exiting_cold_path_01(i32* %p) { 359; CHECK-LABEL: @test_load_on_exiting_cold_path_01( 360; CHECK-NEXT: entry: 361; CHECK-NEXT: br label [[LOOP:%.*]] 362; CHECK: loop: 363; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 364; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 365; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 366; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 367; CHECK: hot_path: 368; CHECK-NEXT: br label [[BACKEDGE]] 369; CHECK: cold_path: 370; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 371; CHECK-NEXT: br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]] 372; CHECK: backedge: 373; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 374; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 375; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 376; CHECK: exit: 377; CHECK-NEXT: ret i32 [[X]] 378; CHECK: cold_exit: 379; CHECK-NEXT: ret i32 -1 380; 381entry: 382 br label %loop 383 384loop: 385 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 386 %x = load i32, i32* %p 387 %cond = icmp ne i32 %x, 0 388 br i1 %cond, label %hot_path, label %cold_path 389 390hot_path: 391 br label %backedge 392 393cold_path: 394 %side_cond = call i1 @side_effect_cond() nofree 395 br i1 %side_cond, label %backedge, label %cold_exit 396 397backedge: 398 %iv.next = add i32 %iv, %x 399 %loop.cond = icmp ult i32 %iv.next, 1000 400 br i1 %loop.cond, label %loop, label %exit 401 402exit: 403 ret i32 %x 404 405cold_exit: 406 ret i32 -1 407} 408 409; TODO: We can PRE via splitting of the critical edge in the cold path. 410define i32 @test_load_on_exiting_cold_path_02(i32* %p) gc "statepoint-example" personality i32 ()* @personality_function { 411; CHECK-LABEL: @test_load_on_exiting_cold_path_02( 412; CHECK-NEXT: entry: 413; CHECK-NEXT: br label [[LOOP:%.*]] 414; CHECK: loop: 415; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 416; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 417; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 418; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 419; CHECK: hot_path: 420; CHECK-NEXT: br label [[BACKEDGE]] 421; CHECK: cold_path: 422; CHECK-NEXT: invoke void @side_effect() 423; CHECK-NEXT: to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]] 424; CHECK: backedge: 425; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 426; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 427; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 428; CHECK: exit: 429; CHECK-NEXT: ret i32 [[X]] 430; CHECK: cold_exit: 431; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad token 432; CHECK-NEXT: cleanup 433; CHECK-NEXT: ret i32 -1 434; 435entry: 436 br label %loop 437 438loop: 439 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 440 %x = load i32, i32* %p 441 %cond = icmp ne i32 %x, 0 442 br i1 %cond, label %hot_path, label %cold_path 443 444hot_path: 445 br label %backedge 446 447cold_path: 448 invoke void @side_effect() to label %backedge unwind label %cold_exit 449 450backedge: 451 %iv.next = add i32 %iv, %x 452 %loop.cond = icmp ult i32 %iv.next, 1000 453 br i1 %loop.cond, label %loop, label %exit 454 455exit: 456 ret i32 %x 457 458cold_exit: 459 %landing_pad = landingpad token 460 cleanup 461 ret i32 -1 462} 463 464; Make sure we do not insert load into both cold path & backedge. 465define i32 @test_load_on_cold_path_and_backedge(i32* %p) { 466; CHECK-LABEL: @test_load_on_cold_path_and_backedge( 467; CHECK-NEXT: entry: 468; CHECK-NEXT: br label [[LOOP:%.*]] 469; CHECK: loop: 470; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 471; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 472; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 473; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 474; CHECK: hot_path: 475; CHECK-NEXT: br label [[BACKEDGE]] 476; CHECK: cold_path: 477; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 478; CHECK-NEXT: br label [[BACKEDGE]] 479; CHECK: backedge: 480; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 481; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 482; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 483; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 484; CHECK: exit: 485; CHECK-NEXT: ret i32 [[X]] 486; 487entry: 488 br label %loop 489 490loop: 491 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 492 %x = load i32, i32* %p 493 %cond = icmp ne i32 %x, 0 494 br i1 %cond, label %hot_path, label %cold_path 495 496hot_path: 497 br label %backedge 498 499cold_path: 500 call void @side_effect() nofree 501 br label %backedge 502 503backedge: 504 %iv.next = add i32 %iv, %x 505 %loop.cond = icmp ult i32 %iv.next, 1000 506 call void @side_effect() nofree 507 br i1 %loop.cond, label %loop, label %exit 508 509exit: 510 ret i32 %x 511} 512 513; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load. 514define i32 @test_load_multi_block_cold_path(i32* %p) { 515; CHECK-LABEL: @test_load_multi_block_cold_path( 516; CHECK-NEXT: entry: 517; CHECK-NEXT: br label [[LOOP:%.*]] 518; CHECK: loop: 519; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 520; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 521; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 522; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]] 523; CHECK: hot_path: 524; CHECK-NEXT: br label [[BACKEDGE]] 525; CHECK: cold_path.1: 526; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 527; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 528; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 529; CHECK-NEXT: br label [[BACKEDGE]] 530; CHECK: backedge: 531; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 532; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 533; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 534; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 535; CHECK: exit: 536; CHECK-NEXT: ret i32 [[X]] 537; 538entry: 539 br label %loop 540 541loop: 542 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 543 %x = load i32, i32* %p 544 %cond = icmp ne i32 %x, 0 545 br i1 %cond, label %hot_path, label %cold_path.1 546 547hot_path: 548 br label %backedge 549 550cold_path.1: 551 call void @side_effect() nofree 552 br label %cold_path.2 553 554cold_path.2: 555 call void @side_effect() nofree 556 br label %cold_path.3 557 558cold_path.3: 559 call void @side_effect() nofree 560 br label %backedge 561 562backedge: 563 %iv.next = add i32 %iv, %x 564 %loop.cond = icmp ult i32 %iv.next, 1000 565 call void @side_effect() nofree 566 br i1 %loop.cond, label %loop, label %exit 567 568exit: 569 ret i32 %x 570} 571 572; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load. 573define i32 @test_load_on_multi_exiting_cold_path(i32* %p) { 574; CHECK-LABEL: @test_load_on_multi_exiting_cold_path( 575; CHECK-NEXT: entry: 576; CHECK-NEXT: br label [[LOOP:%.*]] 577; CHECK: loop: 578; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 579; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 580; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 581; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]] 582; CHECK: hot_path: 583; CHECK-NEXT: br label [[BACKEDGE]] 584; CHECK: cold_path.1: 585; CHECK-NEXT: [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 586; CHECK-NEXT: br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]] 587; CHECK: cold_path.2: 588; CHECK-NEXT: [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 589; CHECK-NEXT: br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]] 590; CHECK: cold_path.3: 591; CHECK-NEXT: [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 592; CHECK-NEXT: br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]] 593; CHECK: backedge: 594; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 595; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 596; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 597; CHECK: exit: 598; CHECK-NEXT: ret i32 [[X]] 599; CHECK: cold_exit: 600; CHECK-NEXT: ret i32 -1 601; 602entry: 603 br label %loop 604 605loop: 606 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 607 %x = load i32, i32* %p 608 %cond = icmp ne i32 %x, 0 609 br i1 %cond, label %hot_path, label %cold_path.1 610 611hot_path: 612 br label %backedge 613 614cold_path.1: 615 %side_cond.1 = call i1 @side_effect_cond() nofree 616 br i1 %side_cond.1, label %cold_path.2, label %cold_exit 617 618cold_path.2: 619 %side_cond.2 = call i1 @side_effect_cond() nofree 620 br i1 %side_cond.2, label %cold_path.3, label %cold_exit 621 622cold_path.3: 623 %side_cond.3 = call i1 @side_effect_cond() nofree 624 br i1 %side_cond.3, label %backedge, label %cold_exit 625 626backedge: 627 %iv.next = add i32 %iv, %x 628 %loop.cond = icmp ult i32 %iv.next, 1000 629 br i1 %loop.cond, label %loop, label %exit 630 631exit: 632 ret i32 %x 633 634cold_exit: 635 ret i32 -1 636} 637 638; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop. 639define i32 @test_inner_loop(i32* %p) { 640; CHECK-LABEL: @test_inner_loop( 641; CHECK-NEXT: entry: 642; CHECK-NEXT: br label [[LOOP:%.*]] 643; CHECK: loop: 644; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 645; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 646; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 647; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 648; CHECK: hot_path: 649; CHECK-NEXT: br label [[BACKEDGE]] 650; CHECK: cold_path: 651; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 652; CHECK: inner_loop: 653; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 654; CHECK-NEXT: br i1 undef, label [[INNER_LOOP]], label [[BACKEDGE]] 655; CHECK: backedge: 656; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 657; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 658; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 659; CHECK: exit: 660; CHECK-NEXT: ret i32 [[X]] 661; 662entry: 663 br label %loop 664 665loop: 666 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 667 %x = load i32, i32* %p 668 %cond = icmp ne i32 %x, 0 669 br i1 %cond, label %hot_path, label %cold_path 670 671hot_path: 672 br label %backedge 673 674cold_path: 675 br label %inner_loop 676 677inner_loop: 678 call void @side_effect() nofree 679 br i1 undef, label %inner_loop, label %backedge 680 681backedge: 682 %iv.next = add i32 %iv, %x 683 %loop.cond = icmp ult i32 %iv.next, 1000 684 br i1 %loop.cond, label %loop, label %exit 685 686exit: 687 ret i32 %x 688} 689 690; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason. 691define i32 @test_multiple_cold_paths(i32* %p) { 692; CHECK-LABEL: @test_multiple_cold_paths( 693; CHECK-NEXT: entry: 694; CHECK-NEXT: br label [[LOOP:%.*]] 695; CHECK: loop: 696; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 697; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 698; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[X]], 0 699; CHECK-NEXT: br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]] 700; CHECK: hot_path.1: 701; CHECK-NEXT: br label [[DOM_1:%.*]] 702; CHECK: cold_path.1: 703; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 704; CHECK-NEXT: br label [[DOM_1]] 705; CHECK: dom.1: 706; CHECK-NEXT: [[COND_2:%.*]] = icmp ne i32 [[X]], 1 707; CHECK-NEXT: br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]] 708; CHECK: hot_path.2: 709; CHECK-NEXT: br label [[DOM_2:%.*]] 710; CHECK: cold_path.2: 711; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 712; CHECK-NEXT: br label [[DOM_2]] 713; CHECK: dom.2: 714; CHECK-NEXT: [[COND_3:%.*]] = icmp ne i32 [[X]], 2 715; CHECK-NEXT: br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]] 716; CHECK: hot_path.3: 717; CHECK-NEXT: br label [[BACKEDGE]] 718; CHECK: cold_path.3: 719; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 720; CHECK-NEXT: br label [[BACKEDGE]] 721; CHECK: backedge: 722; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 723; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 724; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 725; CHECK: exit: 726; CHECK-NEXT: ret i32 [[X]] 727; 728entry: 729 br label %loop 730 731loop: 732 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 733 %x = load i32, i32* %p 734 %cond.1 = icmp ne i32 %x, 0 735 br i1 %cond.1, label %hot_path.1, label %cold_path.1 736 737hot_path.1: 738 br label %dom.1 739 740cold_path.1: 741 call void @side_effect() nofree 742 br label %dom.1 743 744dom.1: 745 %cond.2 = icmp ne i32 %x, 1 746 br i1 %cond.2, label %hot_path.2, label %cold_path.2 747 748hot_path.2: 749 br label %dom.2 750 751cold_path.2: 752 call void @side_effect() nofree 753 br label %dom.2 754 755dom.2: 756 %cond.3 = icmp ne i32 %x, 2 757 br i1 %cond.3, label %hot_path.3, label %cold_path.3 758 759hot_path.3: 760 br label %backedge 761 762cold_path.3: 763 call void @side_effect() nofree 764 br label %backedge 765 766backedge: 767 %iv.next = add i32 %iv, %x 768 %loop.cond = icmp ult i32 %iv.next, 1000 769 br i1 %loop.cond, label %loop, label %exit 770 771exit: 772 ret i32 %x 773} 774 775; TODO: We can PRE via split of critical edge. 776define i32 @test_side_exit_after_merge(i32* %p) { 777; CHECK-LABEL: @test_side_exit_after_merge( 778; CHECK-NEXT: entry: 779; CHECK-NEXT: br label [[LOOP:%.*]] 780; CHECK: loop: 781; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 782; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 783; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 784; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 785; CHECK: hot_path: 786; CHECK-NEXT: br label [[BACKEDGE]] 787; CHECK: cold_path: 788; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[IV]], 1 789; CHECK-NEXT: br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]] 790; CHECK: do_call: 791; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 792; CHECK-NEXT: br label [[SIDE_EXITING]] 793; CHECK: side_exiting: 794; CHECK-NEXT: [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ] 795; CHECK-NEXT: br i1 [[SIDE_COND_PHI]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]] 796; CHECK: backedge: 797; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 798; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 799; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 800; CHECK: exit: 801; CHECK-NEXT: ret i32 [[X]] 802; CHECK: cold_exit: 803; CHECK-NEXT: ret i32 -1 804; 805entry: 806 br label %loop 807 808loop: 809 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 810 %x = load i32, i32* %p 811 %cond = icmp ne i32 %x, 0 812 br i1 %cond, label %hot_path, label %cold_path 813 814hot_path: 815 br label %backedge 816 817cold_path: 818 %cond.1 = icmp ne i32 %iv, 1 819 br i1 %cond.1, label %do_call, label %side_exiting 820 821do_call: 822 %side_cond = call i1 @side_effect_cond() nofree 823 br label %side_exiting 824 825side_exiting: 826 %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path] 827 br i1 %side_cond_phi, label %backedge, label %cold_exit 828 829backedge: 830 %iv.next = add i32 %iv, %x 831 %loop.cond = icmp ult i32 %iv.next, 1000 832 br i1 %loop.cond, label %loop, label %exit 833 834exit: 835 ret i32 %x 836 837cold_exit: 838 ret i32 -1 839} 840 841declare void @llvm.experimental.guard(i1, ...) 842 843define i32 @test_guard_1(i32* %p, i32 %g) { 844; CHECK-LABEL: @test_guard_1( 845; CHECK-NEXT: entry: 846; CHECK-NEXT: br label [[LOOP:%.*]] 847; CHECK: loop: 848; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 849; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]] 850; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ] 851; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 852; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 853; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 854; CHECK: hot_path: 855; CHECK-NEXT: br label [[BACKEDGE]] 856; CHECK: cold_path: 857; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 858; CHECK-NEXT: br label [[BACKEDGE]] 859; CHECK: backedge: 860; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 861; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 862; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 863; CHECK: exit: 864; CHECK-NEXT: ret i32 [[X]] 865; 866entry: 867 br label %loop 868 869loop: 870 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 871 %guard_cond = icmp ne i32 %iv, %g 872 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ] 873 %x = load i32, i32* %p 874 %cond = icmp ult i32 %x, 100 875 br i1 %cond, label %hot_path, label %cold_path 876 877hot_path: 878 br label %backedge 879 880cold_path: 881 call void @side_effect() nofree 882 br label %backedge 883 884backedge: 885 %iv.next = add i32 %iv, %x 886 %loop.cond = icmp ult i32 %iv.next, 1000 887 br i1 %loop.cond, label %loop, label %exit 888 889exit: 890 ret i32 %x 891} 892 893define i32 @test_guard_2(i32* %p, i32 %g) { 894; CHECK-LABEL: @test_guard_2( 895; CHECK-NEXT: entry: 896; CHECK-NEXT: br label [[LOOP:%.*]] 897; CHECK: loop: 898; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 899; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]] 900; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 901; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ] 902; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 903; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 904; CHECK: hot_path: 905; CHECK-NEXT: br label [[BACKEDGE]] 906; CHECK: cold_path: 907; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 908; CHECK-NEXT: br label [[BACKEDGE]] 909; CHECK: backedge: 910; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 911; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 912; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 913; CHECK: exit: 914; CHECK-NEXT: ret i32 [[X]] 915; 916entry: 917 br label %loop 918 919loop: 920 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 921 %guard_cond = icmp ne i32 %iv, %g 922 %x = load i32, i32* %p 923 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ] 924 %cond = icmp ult i32 %x, 100 925 br i1 %cond, label %hot_path, label %cold_path 926 927hot_path: 928 br label %backedge 929 930cold_path: 931 call void @side_effect() nofree 932 br label %backedge 933 934backedge: 935 %iv.next = add i32 %iv, %x 936 %loop.cond = icmp ult i32 %iv.next, 1000 937 br i1 %loop.cond, label %loop, label %exit 938 939exit: 940 ret i32 %x 941} 942