1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes='loop-mssa(unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s 3 4declare void @clobber() 5 6define i32 @partial_unswitch_true_successor(i32* %ptr, i32 %N) { 7; CHECK-LABEL: @partial_unswitch_true_successor( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 10; CHECK: loop.header: 11; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 12; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 13; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 14; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 15; CHECK: noclobber: 16; CHECK-NEXT: br label [[LOOP_LATCH]] 17; CHECK: clobber: 18; CHECK-NEXT: call void @clobber() 19; CHECK-NEXT: br label [[LOOP_LATCH]] 20; CHECK: loop.latch: 21; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 22; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 23; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 24; CHECK: exit: 25; CHECK-NEXT: ret i32 10 26; 27entry: 28 br label %loop.header 29 30loop.header: 31 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 32 %lv = load i32, i32* %ptr 33 %sc = icmp eq i32 %lv, 100 34 br i1 %sc, label %noclobber, label %clobber 35 36noclobber: 37 br label %loop.latch 38 39clobber: 40 call void @clobber() 41 br label %loop.latch 42 43loop.latch: 44 %c = icmp ult i32 %iv, %N 45 %iv.next = add i32 %iv, 1 46 br i1 %c, label %loop.header, label %exit 47 48exit: 49 ret i32 10 50} 51 52define i32 @partial_unswitch_false_successor(i32* %ptr, i32 %N) { 53; CHECK-LABEL: @partial_unswitch_false_successor( 54; CHECK-NEXT: entry: 55; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 56; CHECK: loop.header: 57; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 58; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 59; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 60; CHECK-NEXT: br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]] 61; CHECK: clobber: 62; CHECK-NEXT: call void @clobber() 63; CHECK-NEXT: br label [[LOOP_LATCH]] 64; CHECK: noclobber: 65; CHECK-NEXT: br label [[LOOP_LATCH]] 66; CHECK: loop.latch: 67; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 68; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 69; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 70; CHECK: exit: 71; CHECK-NEXT: ret i32 10 72; 73entry: 74 br label %loop.header 75 76loop.header: 77 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 78 %lv = load i32, i32* %ptr 79 %sc = icmp eq i32 %lv, 100 80 br i1 %sc, label %clobber, label %noclobber 81 82clobber: 83 call void @clobber() 84 br label %loop.latch 85 86noclobber: 87 br label %loop.latch 88 89loop.latch: 90 %c = icmp ult i32 %iv, %N 91 %iv.next = add i32 %iv, 1 92 br i1 %c, label %loop.header, label %exit 93 94exit: 95 ret i32 10 96} 97 98define i32 @partial_unswtich_gep_load_icmp(i32** %ptr, i32 %N) { 99; CHECK-LABEL: @partial_unswtich_gep_load_icmp( 100; CHECK-NEXT: entry: 101; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 102; CHECK: loop.header: 103; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 104; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32*, i32** [[PTR:%.*]], i32 1 105; CHECK-NEXT: [[LV_1:%.*]] = load i32*, i32** [[GEP]], align 8 106; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[LV_1]], align 4 107; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 108; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 109; CHECK: noclobber: 110; CHECK-NEXT: br label [[LOOP_LATCH]] 111; CHECK: clobber: 112; CHECK-NEXT: call void @clobber() 113; CHECK-NEXT: br label [[LOOP_LATCH]] 114; CHECK: loop.latch: 115; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 116; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 117; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 118; CHECK: exit: 119; CHECK-NEXT: ret i32 10 120; 121entry: 122 br label %loop.header 123 124loop.header: 125 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 126 %gep = getelementptr i32*, i32** %ptr, i32 1 127 %lv.1 = load i32*, i32** %gep 128 %lv = load i32, i32* %lv.1 129 %sc = icmp eq i32 %lv, 100 130 br i1 %sc, label %noclobber, label %clobber 131 132noclobber: 133 br label %loop.latch 134 135clobber: 136 call void @clobber() 137 br label %loop.latch 138 139loop.latch: 140 %c = icmp ult i32 %iv, %N 141 %iv.next = add i32 %iv, 1 142 br i1 %c, label %loop.header, label %exit 143 144exit: 145 ret i32 10 146} 147 148define i32 @partial_unswitch_reduction_phi(i32* %ptr, i32 %N) { 149; CHECK-LABEL: @partial_unswitch_reduction_phi( 150; CHECK-NEXT: entry: 151; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 152; CHECK: loop.header: 153; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 154; CHECK-NEXT: [[RED:%.*]] = phi i32 [ 20, [[ENTRY]] ], [ [[RED_NEXT:%.*]], [[LOOP_LATCH]] ] 155; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 156; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 157; CHECK-NEXT: br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]] 158; CHECK: clobber: 159; CHECK-NEXT: call void @clobber() 160; CHECK-NEXT: [[ADD_5:%.*]] = add i32 [[RED]], 5 161; CHECK-NEXT: br label [[LOOP_LATCH]] 162; CHECK: noclobber: 163; CHECK-NEXT: [[ADD_10:%.*]] = add i32 [[RED]], 10 164; CHECK-NEXT: br label [[LOOP_LATCH]] 165; CHECK: loop.latch: 166; CHECK-NEXT: [[RED_NEXT]] = phi i32 [ [[ADD_5]], [[CLOBBER]] ], [ [[ADD_10]], [[NOCLOBBER]] ] 167; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 168; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 169; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 170; CHECK: exit: 171; CHECK-NEXT: [[RED_NEXT_LCSSA:%.*]] = phi i32 [ [[RED_NEXT]], [[LOOP_LATCH]] ] 172; CHECK-NEXT: ret i32 [[RED_NEXT_LCSSA]] 173; 174entry: 175 br label %loop.header 176 177loop.header: 178 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 179 %red = phi i32 [ 20, %entry ], [ %red.next, %loop.latch ] 180 %lv = load i32, i32* %ptr 181 %sc = icmp eq i32 %lv, 100 182 br i1 %sc, label %clobber, label %noclobber 183 184clobber: 185 call void @clobber() 186 %add.5 = add i32 %red, 5 187 br label %loop.latch 188 189noclobber: 190 %add.10 = add i32 %red, 10 191 br label %loop.latch 192 193loop.latch: 194 %red.next = phi i32 [ %add.5, %clobber ], [ %add.10, %noclobber ] 195 %c = icmp ult i32 %iv, %N 196 %iv.next = add i32 %iv, 1 197 br i1 %c, label %loop.header, label %exit 198 199exit: 200 %red.next.lcssa = phi i32 [ %red.next, %loop.latch ] 201 ret i32 %red.next.lcssa 202} 203 204; Partial unswitching is possible, because the store in %noclobber does not 205; alias the load of the condition. 206define i32 @partial_unswitch_true_successor_noclobber(i32* noalias %ptr.1, i32* noalias %ptr.2, i32 %N) { 207; CHECK-LABEL: @partial_unswitch_true_successor_noclobber( 208; CHECK-NEXT: entry: 209; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 210; CHECK: loop.header: 211; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 212; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4 213; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 214; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 215; CHECK: noclobber: 216; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV]] 217; CHECK-NEXT: store i32 [[LV]], i32* [[GEP_1]], align 4 218; CHECK-NEXT: br label [[LOOP_LATCH]] 219; CHECK: clobber: 220; CHECK-NEXT: call void @clobber() 221; CHECK-NEXT: br label [[LOOP_LATCH]] 222; CHECK: loop.latch: 223; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 224; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 225; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 226; CHECK: exit: 227; CHECK-NEXT: ret i32 10 228; 229entry: 230 br label %loop.header 231 232loop.header: 233 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 234 %lv = load i32, i32* %ptr.1 235 %sc = icmp eq i32 %lv, 100 236 br i1 %sc, label %noclobber, label %clobber 237 238noclobber: 239 %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv 240 store i32 %lv, i32* %gep.1 241 br label %loop.latch 242 243clobber: 244 call void @clobber() 245 br label %loop.latch 246 247loop.latch: 248 %c = icmp ult i32 %iv, %N 249 %iv.next = add i32 %iv, 1 250 br i1 %c, label %loop.header, label %exit 251 252exit: 253 ret i32 10 254} 255 256define void @no_partial_unswitch_phi_cond(i1 %lc, i32 %N) { 257; CHECK-LABEL: @no_partial_unswitch_phi_cond( 258; CHECK-NEXT: entry: 259; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 260; CHECK: loop.header: 261; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 262; CHECK-NEXT: [[SC:%.*]] = phi i1 [ [[LC:%.*]], [[ENTRY]] ], [ true, [[LOOP_LATCH]] ] 263; CHECK-NEXT: br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]] 264; CHECK: clobber: 265; CHECK-NEXT: call void @clobber() 266; CHECK-NEXT: br label [[LOOP_LATCH]] 267; CHECK: noclobber: 268; CHECK-NEXT: br label [[LOOP_LATCH]] 269; CHECK: loop.latch: 270; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 271; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 272; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 273; CHECK: exit: 274; CHECK-NEXT: ret void 275; 276entry: 277 br label %loop.header 278 279loop.header: 280 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 281 %sc = phi i1 [ %lc, %entry ], [ true, %loop.latch ] 282 br i1 %sc, label %clobber, label %noclobber 283 284clobber: 285 call void @clobber() 286 br label %loop.latch 287 288noclobber: 289 br label %loop.latch 290 291loop.latch: 292 %c = icmp ult i32 %iv, %N 293 %iv.next = add i32 %iv, 1 294 br i1 %c, label %loop.header, label %exit 295 296exit: 297 ret void 298} 299 300define void @no_partial_unswitch_clobber_latch(i32* %ptr, i32 %N) { 301; CHECK-LABEL: @no_partial_unswitch_clobber_latch( 302; CHECK-NEXT: entry: 303; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 304; CHECK: loop.header: 305; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 306; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 307; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 308; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 309; CHECK: noclobber: 310; CHECK-NEXT: br label [[LOOP_LATCH]] 311; CHECK: clobber: 312; CHECK-NEXT: call void @clobber() 313; CHECK-NEXT: br label [[LOOP_LATCH]] 314; CHECK: loop.latch: 315; CHECK-NEXT: call void @clobber() 316; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 317; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 318; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 319; CHECK: exit: 320; CHECK-NEXT: ret void 321; 322entry: 323 br label %loop.header 324 325loop.header: 326 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 327 %lv = load i32, i32* %ptr 328 %sc = icmp eq i32 %lv, 100 329 br i1 %sc, label %noclobber, label %clobber 330 331noclobber: 332 br label %loop.latch 333 334clobber: 335 call void @clobber() 336 br label %loop.latch 337 338loop.latch: 339 call void @clobber() 340 %c = icmp ult i32 %iv, %N 341 %iv.next = add i32 %iv, 1 342 br i1 %c, label %loop.header, label %exit 343 344exit: 345 ret void 346} 347 348define void @no_partial_unswitch_clobber_header(i32* %ptr, i32 %N) { 349; CHECK-LABEL: @no_partial_unswitch_clobber_header( 350; CHECK-NEXT: entry: 351; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 352; CHECK: loop.header: 353; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 354; CHECK-NEXT: call void @clobber() 355; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 356; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 357; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 358; CHECK: noclobber: 359; CHECK-NEXT: br label [[LOOP_LATCH]] 360; CHECK: clobber: 361; CHECK-NEXT: call void @clobber() 362; CHECK-NEXT: br label [[LOOP_LATCH]] 363; CHECK: loop.latch: 364; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 365; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 366; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 367; CHECK: exit: 368; CHECK-NEXT: ret void 369; 370entry: 371 br label %loop.header 372 373loop.header: 374 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 375 call void @clobber() 376 %lv = load i32, i32* %ptr 377 %sc = icmp eq i32 %lv, 100 378 br i1 %sc, label %noclobber, label %clobber 379 380noclobber: 381 br label %loop.latch 382 383clobber: 384 call void @clobber() 385 br label %loop.latch 386 387loop.latch: 388 %c = icmp ult i32 %iv, %N 389 %iv.next = add i32 %iv, 1 390 br i1 %c, label %loop.header, label %exit 391 392exit: 393 ret void 394} 395 396define void @no_partial_unswitch_clobber_both(i32* %ptr, i32 %N) { 397; CHECK-LABEL: @no_partial_unswitch_clobber_both( 398; CHECK-NEXT: entry: 399; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 400; CHECK: loop.header: 401; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 402; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 403; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 404; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 405; CHECK: noclobber: 406; CHECK-NEXT: call void @clobber() 407; CHECK-NEXT: br label [[LOOP_LATCH]] 408; CHECK: clobber: 409; CHECK-NEXT: call void @clobber() 410; CHECK-NEXT: br label [[LOOP_LATCH]] 411; CHECK: loop.latch: 412; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 413; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 414; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 415; CHECK: exit: 416; CHECK-NEXT: ret void 417; 418entry: 419 br label %loop.header 420 421loop.header: 422 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 423 %lv = load i32, i32* %ptr 424 %sc = icmp eq i32 %lv, 100 425 br i1 %sc, label %noclobber, label %clobber 426 427noclobber: 428 call void @clobber() 429 br label %loop.latch 430 431clobber: 432 call void @clobber() 433 br label %loop.latch 434 435loop.latch: 436 %c = icmp ult i32 %iv, %N 437 %iv.next = add i32 %iv, 1 438 br i1 %c, label %loop.header, label %exit 439 440exit: 441 ret void 442} 443 444define i32 @no_partial_unswitch_true_successor_storeclobber(i32* %ptr.1, i32* %ptr.2, i32 %N) { 445; CHECK-LABEL: @no_partial_unswitch_true_successor_storeclobber( 446; CHECK-NEXT: entry: 447; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 448; CHECK: loop.header: 449; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 450; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4 451; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 452; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 453; CHECK: noclobber: 454; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV]] 455; CHECK-NEXT: store i32 [[LV]], i32* [[GEP_1]], align 4 456; CHECK-NEXT: br label [[LOOP_LATCH]] 457; CHECK: clobber: 458; CHECK-NEXT: call void @clobber() 459; CHECK-NEXT: br label [[LOOP_LATCH]] 460; CHECK: loop.latch: 461; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 462; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 463; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 464; CHECK: exit: 465; CHECK-NEXT: ret i32 10 466; 467entry: 468 br label %loop.header 469 470loop.header: 471 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 472 %lv = load i32, i32* %ptr.1 473 %sc = icmp eq i32 %lv, 100 474 br i1 %sc, label %noclobber, label %clobber 475 476noclobber: 477 %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv 478 store i32 %lv, i32* %gep.1 479 br label %loop.latch 480 481clobber: 482 call void @clobber() 483 br label %loop.latch 484 485loop.latch: 486 %c = icmp ult i32 %iv, %N 487 %iv.next = add i32 %iv, 1 488 br i1 %c, label %loop.header, label %exit 489 490exit: 491 ret i32 10 492} 493 494; Make sure the duplicated instructions are moved to a preheader that always 495; executes when the loop body also executes. Do not check the unswitched code, 496; because it is already checked in the @partial_unswitch_true_successor test 497; case. 498define i32 @partial_unswitch_true_successor_preheader_insertion(i32* %ptr, i32 %N) { 499; CHECK-LABEL: @partial_unswitch_true_successor_preheader_insertion( 500; CHECK-NEXT: entry: 501; CHECK-NEXT: [[EC:%.*]] = icmp ne i32* [[PTR:%.*]], null 502; CHECK-NEXT: br i1 [[EC]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]] 503; CHECK: loop.ph: 504; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 505; CHECK: loop.header: 506; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[LOOP_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 507; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR]], align 4 508; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 509; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 510; CHECK: noclobber: 511; CHECK-NEXT: br label [[LOOP_LATCH]] 512; CHECK: clobber: 513; CHECK-NEXT: call void @clobber() 514; CHECK-NEXT: br label [[LOOP_LATCH]] 515; CHECK: loop.latch: 516; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 517; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 518; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT:%.*]] 519; CHECK: exit.loopexit: 520; CHECK-NEXT: br label [[EXIT]] 521; CHECK: exit: 522; CHECK-NEXT: ret i32 10 523; 524 525entry: 526 %ec = icmp ne i32* %ptr, null 527 br i1 %ec, label %loop.ph, label %exit 528 529loop.ph: 530 br label %loop.header 531 532loop.header: 533 %iv = phi i32 [ 0, %loop.ph ], [ %iv.next, %loop.latch ] 534 %lv = load i32, i32* %ptr 535 %sc = icmp eq i32 %lv, 100 536 br i1 %sc, label %noclobber, label %clobber 537 538noclobber: 539 br label %loop.latch 540 541clobber: 542 call void @clobber() 543 br label %loop.latch 544 545loop.latch: 546 %c = icmp ult i32 %iv, %N 547 %iv.next = add i32 %iv, 1 548 br i1 %c, label %loop.header, label %exit 549 550exit: 551 ret i32 10 552} 553 554; Make sure the duplicated instructions are hoisted just before the branch of 555; the preheader. Do not check the unswitched code, because it is already checked 556; in the @partial_unswitch_true_successor test case 557define i32 @partial_unswitch_true_successor_insert_point(i32* %ptr, i32 %N) { 558; CHECK-LABEL: @partial_unswitch_true_successor_insert_point( 559; CHECK-NEXT: entry: 560; CHECK-NEXT: call void @clobber() 561; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 562; CHECK: loop.header: 563; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 564; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 565; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 566; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 567; CHECK: noclobber: 568; CHECK-NEXT: br label [[LOOP_LATCH]] 569; CHECK: clobber: 570; CHECK-NEXT: call void @clobber() 571; CHECK-NEXT: br label [[LOOP_LATCH]] 572; CHECK: loop.latch: 573; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 574; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 575; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 576; CHECK: exit: 577; CHECK-NEXT: ret i32 10 578; 579entry: 580 call void @clobber() 581 br label %loop.header 582 583loop.header: 584 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 585 %lv = load i32, i32* %ptr 586 %sc = icmp eq i32 %lv, 100 587 br i1 %sc, label %noclobber, label %clobber 588 589noclobber: 590 br label %loop.latch 591 592clobber: 593 call void @clobber() 594 br label %loop.latch 595 596loop.latch: 597 %c = icmp ult i32 %iv, %N 598 %iv.next = add i32 %iv, 1 599 br i1 %c, label %loop.header, label %exit 600 601exit: 602 ret i32 10 603} 604 605; Make sure invariant instructions in the loop are also hoisted to the preheader. 606; Do not check the unswitched code, because it is already checked in the 607; @partial_unswitch_true_successor test case 608define i32 @partial_unswitch_true_successor_hoist_invariant(i32* %ptr, i32 %N) { 609; CHECK-LABEL: @partial_unswitch_true_successor_hoist_invariant( 610; CHECK-NEXT: entry: 611; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 612; CHECK: loop.header: 613; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 614; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 1 615; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[GEP]], align 4 616; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 617; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 618; CHECK: noclobber: 619; CHECK-NEXT: br label [[LOOP_LATCH]] 620; CHECK: clobber: 621; CHECK-NEXT: call void @clobber() 622; CHECK-NEXT: br label [[LOOP_LATCH]] 623; CHECK: loop.latch: 624; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 625; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 626; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 627; CHECK: exit: 628; CHECK-NEXT: ret i32 10 629; 630entry: 631 br label %loop.header 632 633loop.header: 634 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 635 %gep = getelementptr i32, i32* %ptr, i64 1 636 %lv = load i32, i32* %gep 637 %sc = icmp eq i32 %lv, 100 638 br i1 %sc, label %noclobber, label %clobber 639 640noclobber: 641 br label %loop.latch 642 643clobber: 644 call void @clobber() 645 br label %loop.latch 646 647loop.latch: 648 %c = icmp ult i32 %iv, %N 649 %iv.next = add i32 %iv, 1 650 br i1 %c, label %loop.header, label %exit 651 652exit: 653 ret i32 10 654} 655 656; Do not unswitch if the condition depends on an atomic load. Duplicating such 657; loads is not safe. 658define i32 @no_partial_unswitch_atomic_load_unordered(i32* %ptr, i32 %N) { 659; CHECK-LABEL: @no_partial_unswitch_atomic_load_unordered( 660; CHECK-NEXT: entry: 661; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 662; CHECK: loop.header: 663; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 664; CHECK-NEXT: [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] unordered, align 4 665; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 666; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 667; CHECK: noclobber: 668; CHECK-NEXT: br label [[LOOP_LATCH]] 669; CHECK: clobber: 670; CHECK-NEXT: call void @clobber() 671; CHECK-NEXT: br label [[LOOP_LATCH]] 672; CHECK: loop.latch: 673; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 674; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 675; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 676; CHECK: exit: 677; CHECK-NEXT: ret i32 10 678; 679entry: 680 br label %loop.header 681 682loop.header: 683 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 684 %lv = load atomic i32, i32* %ptr unordered, align 4 685 %sc = icmp eq i32 %lv, 100 686 br i1 %sc, label %noclobber, label %clobber 687 688noclobber: 689 br label %loop.latch 690 691clobber: 692 call void @clobber() 693 br label %loop.latch 694 695loop.latch: 696 %c = icmp ult i32 %iv, %N 697 %iv.next = add i32 %iv, 1 698 br i1 %c, label %loop.header, label %exit 699 700exit: 701 ret i32 10 702} 703 704; Do not unswitch if the condition depends on an atomic load. Duplicating such 705; loads is not safe. 706define i32 @no_partial_unswitch_atomic_load_monotonic(i32* %ptr, i32 %N) { 707; CHECK-LABEL: @no_partial_unswitch_atomic_load_monotonic( 708; CHECK-NEXT: entry: 709; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 710; CHECK: loop.header: 711; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 712; CHECK-NEXT: [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] monotonic, align 4 713; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 714; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 715; CHECK: noclobber: 716; CHECK-NEXT: br label [[LOOP_LATCH]] 717; CHECK: clobber: 718; CHECK-NEXT: call void @clobber() 719; CHECK-NEXT: br label [[LOOP_LATCH]] 720; CHECK: loop.latch: 721; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 722; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 723; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 724; CHECK: exit: 725; CHECK-NEXT: ret i32 10 726; 727entry: 728 br label %loop.header 729 730loop.header: 731 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 732 %lv = load atomic i32, i32* %ptr monotonic, align 4 733 %sc = icmp eq i32 %lv, 100 734 br i1 %sc, label %noclobber, label %clobber 735 736noclobber: 737 br label %loop.latch 738 739clobber: 740 call void @clobber() 741 br label %loop.latch 742 743loop.latch: 744 %c = icmp ult i32 %iv, %N 745 %iv.next = add i32 %iv, 1 746 br i1 %c, label %loop.header, label %exit 747 748exit: 749 ret i32 10 750} 751 752 753declare i32 @get_value() 754 755; Do not unswitch if the condition depends on a call, that may clobber memory. 756; Duplicating such a call is not safe. 757define i32 @no_partial_unswitch_cond_call(i32* %ptr, i32 %N) { 758; CHECK-LABEL: @no_partial_unswitch_cond_call( 759; CHECK-NEXT: entry: 760; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 761; CHECK: loop.header: 762; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 763; CHECK-NEXT: [[LV:%.*]] = call i32 @get_value() 764; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 765; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]] 766; CHECK: noclobber: 767; CHECK-NEXT: br label [[LOOP_LATCH]] 768; CHECK: clobber: 769; CHECK-NEXT: call void @clobber() 770; CHECK-NEXT: br label [[LOOP_LATCH]] 771; CHECK: loop.latch: 772; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 773; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 774; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 775; CHECK: exit: 776; CHECK-NEXT: ret i32 10 777; 778entry: 779 br label %loop.header 780 781loop.header: 782 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 783 %lv = call i32 @get_value() 784 %sc = icmp eq i32 %lv, 100 785 br i1 %sc, label %noclobber, label %clobber 786 787noclobber: 788 br label %loop.latch 789 790clobber: 791 call void @clobber() 792 br label %loop.latch 793 794loop.latch: 795 %c = icmp ult i32 %iv, %N 796 %iv.next = add i32 %iv, 1 797 br i1 %c, label %loop.header, label %exit 798 799exit: 800 ret i32 10 801} 802 803define i32 @no_partial_unswitch_true_successor_exit(i32* %ptr, i32 %N) { 804; CHECK-LABEL: @no_partial_unswitch_true_successor_exit( 805; CHECK-NEXT: entry: 806; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 807; CHECK: loop.header: 808; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 809; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 810; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 811; CHECK-NEXT: br i1 [[SC]], label [[EXIT:%.*]], label [[CLOBBER:%.*]] 812; CHECK: clobber: 813; CHECK-NEXT: call void @clobber() 814; CHECK-NEXT: br label [[LOOP_LATCH]] 815; CHECK: loop.latch: 816; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 817; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 818; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT]] 819; CHECK: exit: 820; CHECK-NEXT: ret i32 10 821; 822entry: 823 br label %loop.header 824 825loop.header: 826 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 827 %lv = load i32, i32* %ptr 828 %sc = icmp eq i32 %lv, 100 829 br i1 %sc, label %exit, label %clobber 830 831clobber: 832 call void @clobber() 833 br label %loop.latch 834 835loop.latch: 836 %c = icmp ult i32 %iv, %N 837 %iv.next = add i32 %iv, 1 838 br i1 %c, label %loop.header, label %exit 839 840exit: 841 ret i32 10 842} 843 844define i32 @no_partial_unswitch_true_same_successor(i32* %ptr, i32 %N) { 845; CHECK-LABEL: @no_partial_unswitch_true_same_successor( 846; CHECK-NEXT: entry: 847; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 848; CHECK: loop.header: 849; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 850; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 851; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 852; CHECK-NEXT: br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[NOCLOBBER]] 853; CHECK: noclobber: 854; CHECK-NEXT: br label [[LOOP_LATCH]] 855; CHECK: loop.latch: 856; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 857; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 858; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 859; CHECK: exit: 860; CHECK-NEXT: ret i32 10 861; 862entry: 863 br label %loop.header 864 865loop.header: 866 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 867 %lv = load i32, i32* %ptr 868 %sc = icmp eq i32 %lv, 100 869 br i1 %sc, label %noclobber, label %noclobber 870 871noclobber: 872 br label %loop.latch 873 874loop.latch: 875 %c = icmp ult i32 %iv, %N 876 %iv.next = add i32 %iv, 1 877 br i1 %c, label %loop.header, label %exit 878 879exit: 880 ret i32 10 881} 882 883define i32 @partial_unswitch_true_to_latch(i32* %ptr, i32 %N) { 884; CHECK-LABEL: @partial_unswitch_true_to_latch( 885; CHECK-NEXT: entry: 886; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 887; CHECK: loop.header: 888; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 889; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4 890; CHECK-NEXT: [[SC:%.*]] = icmp eq i32 [[LV]], 100 891; CHECK-NEXT: br i1 [[SC]], label [[LOOP_LATCH]], label [[CLOBBER:%.*]] 892; CHECK: clobber: 893; CHECK-NEXT: call void @clobber() 894; CHECK-NEXT: br label [[LOOP_LATCH]] 895; CHECK: loop.latch: 896; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]] 897; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 898; CHECK-NEXT: br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]] 899; CHECK: exit: 900; CHECK-NEXT: ret i32 10 901; 902entry: 903 br label %loop.header 904 905loop.header: 906 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 907 %lv = load i32, i32* %ptr 908 %sc = icmp eq i32 %lv, 100 909 br i1 %sc, label %loop.latch, label %clobber 910 911clobber: 912 call void @clobber() 913 br label %loop.latch 914 915loop.latch: 916 %c = icmp ult i32 %iv, %N 917 %iv.next = add i32 %iv, 1 918 br i1 %c, label %loop.header, label %exit 919 920exit: 921 ret i32 10 922} 923