1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i32) 5declare void @sideeffect() 6 7; negative test (but we could allow this?) - don't hoist to conditional predecessor block 8 9define i32 @add_const_incoming0_speculative(i1 %b, i32 %x, i32 %y) { 10; CHECK-LABEL: @add_const_incoming0_speculative( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 13; CHECK: if: 14; CHECK-NEXT: br label [[THEN]] 15; CHECK: then: 16; CHECK-NEXT: [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 17; CHECK-NEXT: [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 18; CHECK-NEXT: [[R:%.*]] = add i32 [[P0]], [[P1]] 19; CHECK-NEXT: ret i32 [[R]] 20; 21entry: 22 br i1 %b, label %if, label %then 23 24if: 25 br label %then 26 27then: 28 %p0 = phi i32 [ 42, %if ], [ %x, %entry ] 29 %p1 = phi i32 [ 17, %if ], [ %y, %entry ] 30 %r = add i32 %p0, %p1 31 ret i32 %r 32} 33 34define i32 @add_const_incoming0_nonspeculative(i1 %b, i32 %x, i32 %y) { 35; CHECK-LABEL: @add_const_incoming0_nonspeculative( 36; CHECK-NEXT: entry: 37; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 38; CHECK: if: 39; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 40; CHECK-NEXT: br label [[THEN]] 41; CHECK: then: 42; CHECK-NEXT: [[R:%.*]] = phi i32 [ 59, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ] 43; CHECK-NEXT: ret i32 [[R]] 44; 45entry: 46 br i1 %b, label %if, label %then 47 48if: 49 br label %then 50 51then: 52 %p0 = phi i32 [ 42, %entry ], [ %x, %if ] 53 %p1 = phi i32 [ 17, %entry ], [ %y, %if ] 54 %r = add i32 %p0, %p1 55 ret i32 %r 56} 57 58; negative test (but we could allow this?) - don't hoist to conditional predecessor block 59 60define i32 @sub_const_incoming0(i1 %b, i32 %x, i32 %y) { 61; CHECK-LABEL: @sub_const_incoming0( 62; CHECK-NEXT: entry: 63; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 64; CHECK: if: 65; CHECK-NEXT: br label [[THEN]] 66; CHECK: then: 67; CHECK-NEXT: [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 68; CHECK-NEXT: [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 69; CHECK-NEXT: [[R:%.*]] = sub i32 [[P1]], [[P0]] 70; CHECK-NEXT: ret i32 [[R]] 71; 72entry: 73 br i1 %b, label %if, label %then 74 75if: 76 br label %then 77 78then: 79 %p0 = phi i32 [ 42, %if ], [ %x, %entry ] 80 %p1 = phi i32 [ 17, %if ], [ %y, %entry ] 81 %r = sub i32 %p1, %p0 82 ret i32 %r 83} 84 85define i32 @sub_const_incoming1(i1 %b, i32 %x, i32 %y) { 86; CHECK-LABEL: @sub_const_incoming1( 87; CHECK-NEXT: entry: 88; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 89; CHECK: if: 90; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]] 91; CHECK-NEXT: br label [[THEN]] 92; CHECK: then: 93; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF]] ], [ 25, [[ENTRY:%.*]] ] 94; CHECK-NEXT: ret i32 [[R]] 95; 96entry: 97 br i1 %b, label %if, label %then 98 99if: 100 br label %then 101 102then: 103 %p0 = phi i32 [ %x, %if ], [ 42, %entry ] 104 %p1 = phi i32 [ %y, %if ], [ 17, %entry ] 105 %r = sub i32 %p0, %p1 106 ret i32 %r 107} 108 109define i8 @mul_const_incoming1(i1 %b, i8 %x, i8 %y) { 110; CHECK-LABEL: @mul_const_incoming1( 111; CHECK-NEXT: entry: 112; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 113; CHECK: if: 114; CHECK-NEXT: [[TMP0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]] 115; CHECK-NEXT: br label [[THEN]] 116; CHECK: then: 117; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ -54, [[ENTRY:%.*]] ] 118; CHECK-NEXT: ret i8 [[R]] 119; 120entry: 121 br i1 %b, label %if, label %then 122 123if: 124 br label %then 125 126then: 127 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 128 %p1 = phi i8 [ %y, %if ], [ 17, %entry ] 129 %r = mul i8 %p0, %p1 130 ret i8 %r 131} 132 133define i8 @and_const_incoming1(i1 %b, i8 %x, i8 %y) { 134; CHECK-LABEL: @and_const_incoming1( 135; CHECK-NEXT: entry: 136; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 137; CHECK: if: 138; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], [[Y:%.*]] 139; CHECK-NEXT: br label [[THEN]] 140; CHECK: then: 141; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 0, [[ENTRY:%.*]] ] 142; CHECK-NEXT: ret i8 [[R]] 143; 144entry: 145 br i1 %b, label %if, label %then 146 147if: 148 br label %then 149 150then: 151 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 152 %p1 = phi i8 [ %y, %if ], [ 17, %entry ] 153 %r = and i8 %p0, %p1 154 ret i8 %r 155} 156 157define i8 @xor_const_incoming1(i1 %b, i8 %x, i8 %y) { 158; CHECK-LABEL: @xor_const_incoming1( 159; CHECK-NEXT: entry: 160; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 161; CHECK: if: 162; CHECK-NEXT: [[TMP0:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] 163; CHECK-NEXT: br label [[THEN]] 164; CHECK: then: 165; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 59, [[ENTRY:%.*]] ] 166; CHECK-NEXT: ret i8 [[R]] 167; 168entry: 169 br i1 %b, label %if, label %then 170 171if: 172 br label %then 173 174then: 175 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 176 %p1 = phi i8 [ %y, %if ], [ 17, %entry ] 177 %r = xor i8 %p0, %p1 178 ret i8 %r 179} 180 181define i64 @or_const_incoming1(i1 %b, i64 %x, i64 %y) { 182; CHECK-LABEL: @or_const_incoming1( 183; CHECK-NEXT: entry: 184; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 185; CHECK: if: 186; CHECK-NEXT: [[TMP0:%.*]] = or i64 [[X:%.*]], [[Y:%.*]] 187; CHECK-NEXT: br label [[THEN]] 188; CHECK: then: 189; CHECK-NEXT: [[R:%.*]] = phi i64 [ [[TMP0]], [[IF]] ], [ 19, [[ENTRY:%.*]] ] 190; CHECK-NEXT: ret i64 [[R]] 191; 192entry: 193 br i1 %b, label %if, label %then 194 195if: 196 br label %then 197 198then: 199 %p0 = phi i64 [ %x, %if ], [ 3, %entry ] 200 %p1 = phi i64 [ %y, %if ], [ 16, %entry ] 201 %r = or i64 %p0, %p1 202 ret i64 %r 203} 204 205define i64 @or_const_incoming01(i1 %b, i64 %x, i64 %y) { 206; CHECK-LABEL: @or_const_incoming01( 207; CHECK-NEXT: entry: 208; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 209; CHECK: if: 210; CHECK-NEXT: [[TMP0:%.*]] = or i64 [[X:%.*]], [[Y:%.*]] 211; CHECK-NEXT: br label [[THEN]] 212; CHECK: then: 213; CHECK-NEXT: [[R:%.*]] = phi i64 [ 19, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ] 214; CHECK-NEXT: ret i64 [[R]] 215; 216entry: 217 br i1 %b, label %if, label %then 218 219if: 220 br label %then 221 222then: 223 %p0 = phi i64 [ 3, %entry ], [ %x, %if] 224 %p1 = phi i64 [ %y, %if ], [ 16, %entry ] 225 %r = or i64 %p0, %p1 226 ret i64 %r 227} 228 229define i64 @or_const_incoming10(i1 %b, i64 %x, i64 %y) { 230; CHECK-LABEL: @or_const_incoming10( 231; CHECK-NEXT: entry: 232; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 233; CHECK: if: 234; CHECK-NEXT: [[TMP0:%.*]] = or i64 [[Y:%.*]], [[X:%.*]] 235; CHECK-NEXT: br label [[THEN]] 236; CHECK: then: 237; CHECK-NEXT: [[R:%.*]] = phi i64 [ [[TMP0]], [[IF]] ], [ 19, [[ENTRY:%.*]] ] 238; CHECK-NEXT: ret i64 [[R]] 239; 240entry: 241 br i1 %b, label %if, label %then 242 243if: 244 br label %then 245 246then: 247 %p0 = phi i64 [ %y, %if ], [ 16, %entry ] 248 %p1 = phi i64 [ 3, %entry ], [ %x, %if] 249 %r = or i64 %p0, %p1 250 ret i64 %r 251} 252 253; negative test (but we could allow this?) - don't hoist to conditional predecessor block 254 255define i8 @ashr_const_incoming0_speculative(i1 %b, i8 %x, i8 %y) { 256; CHECK-LABEL: @ashr_const_incoming0_speculative( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 259; CHECK: if: 260; CHECK-NEXT: br label [[THEN]] 261; CHECK: then: 262; CHECK-NEXT: [[P0:%.*]] = phi i8 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 263; CHECK-NEXT: [[P1:%.*]] = phi i8 [ 3, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 264; CHECK-NEXT: [[R:%.*]] = ashr i8 [[P0]], [[P1]] 265; CHECK-NEXT: ret i8 [[R]] 266; 267entry: 268 br i1 %b, label %if, label %then 269 270if: 271 br label %then 272 273then: 274 %p0 = phi i8 [ 42, %if ], [ %x, %entry ] 275 %p1 = phi i8 [ 3, %if ], [ %y, %entry ] 276 %r = ashr i8 %p0, %p1 277 ret i8 %r 278} 279 280define i8 @ashr_const_incoming0(i1 %b, i8 %x, i8 %y) { 281; CHECK-LABEL: @ashr_const_incoming0( 282; CHECK-NEXT: entry: 283; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 284; CHECK: if: 285; CHECK-NEXT: [[TMP0:%.*]] = ashr i8 [[X:%.*]], [[Y:%.*]] 286; CHECK-NEXT: br label [[THEN]] 287; CHECK: then: 288; CHECK-NEXT: [[R:%.*]] = phi i8 [ 5, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ] 289; CHECK-NEXT: ret i8 [[R]] 290; 291entry: 292 br i1 %b, label %if, label %then 293 294if: 295 br label %then 296 297then: 298 %p0 = phi i8 [ 42, %entry ], [ %x, %if ] 299 %p1 = phi i8 [ 3, %entry ], [ %y, %if ] 300 %r = ashr i8 %p0, %p1 301 ret i8 %r 302} 303 304define i8 @lshr_const_incoming1(i1 %b, i8 %x, i8 %y) { 305; CHECK-LABEL: @lshr_const_incoming1( 306; CHECK-NEXT: entry: 307; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 308; CHECK: if: 309; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]] 310; CHECK-NEXT: br label [[THEN]] 311; CHECK: then: 312; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 5, [[ENTRY:%.*]] ] 313; CHECK-NEXT: ret i8 [[R]] 314; 315entry: 316 br i1 %b, label %if, label %then 317 318if: 319 br label %then 320 321then: 322 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 323 %p1 = phi i8 [ %y, %if ], [ 3, %entry ] 324 %r = lshr i8 %p0, %p1 325 ret i8 %r 326} 327 328define i8 @shl_const_incoming1(i1 %b, i8 %x, i8 %y) { 329; CHECK-LABEL: @shl_const_incoming1( 330; CHECK-NEXT: entry: 331; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 332; CHECK: if: 333; CHECK-NEXT: [[TMP0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]] 334; CHECK-NEXT: br label [[THEN]] 335; CHECK: then: 336; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 80, [[ENTRY:%.*]] ] 337; CHECK-NEXT: ret i8 [[R]] 338; 339entry: 340 br i1 %b, label %if, label %then 341 342if: 343 br label %then 344 345then: 346 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 347 %p1 = phi i8 [ %y, %if ], [ 3, %entry ] 348 %r = shl nsw nuw i8 %p0, %p1 349 ret i8 %r 350} 351 352define i8 @sdiv_not_safe_to_speculate(i1 %b, i8 %x, i8 %y) { 353; CHECK-LABEL: @sdiv_not_safe_to_speculate( 354; CHECK-NEXT: entry: 355; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 356; CHECK: if: 357; CHECK-NEXT: br label [[THEN]] 358; CHECK: then: 359; CHECK-NEXT: [[P0:%.*]] = phi i8 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 360; CHECK-NEXT: [[P1:%.*]] = phi i8 [ 3, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 361; CHECK-NEXT: [[R:%.*]] = sdiv exact i8 [[P0]], [[P1]] 362; CHECK-NEXT: ret i8 [[R]] 363; 364entry: 365 br i1 %b, label %if, label %then 366 367if: 368 br label %then 369 370then: 371 %p0 = phi i8 [ 42, %if ], [ %x, %entry ] 372 %p1 = phi i8 [ 3, %if ], [ %y, %entry ] 373 %r = sdiv exact i8 %p0, %p1 374 ret i8 %r 375} 376 377define i8 @sdiv_const_incoming1(i1 %b, i8 %x, i8 %y) { 378; CHECK-LABEL: @sdiv_const_incoming1( 379; CHECK-NEXT: entry: 380; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 381; CHECK: if: 382; CHECK-NEXT: [[TMP0:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]] 383; CHECK-NEXT: br label [[THEN]] 384; CHECK: then: 385; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ -2, [[ENTRY:%.*]] ] 386; CHECK-NEXT: ret i8 [[R]] 387; 388entry: 389 br i1 %b, label %if, label %then 390 391if: 392 br label %then 393 394then: 395 %p0 = phi i8 [ %x, %if ], [ -42, %entry ] 396 %p1 = phi i8 [ %y, %if ], [ 17, %entry ] 397 %r = sdiv i8 %p0, %p1 398 ret i8 %r 399} 400 401define i8 @udiv_const_incoming1(i1 %b, i8 %x, i8 %y) { 402; CHECK-LABEL: @udiv_const_incoming1( 403; CHECK-NEXT: entry: 404; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 405; CHECK: if: 406; CHECK-NEXT: [[TMP0:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]] 407; CHECK-NEXT: br label [[THEN]] 408; CHECK: then: 409; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 12, [[ENTRY:%.*]] ] 410; CHECK-NEXT: ret i8 [[R]] 411; 412entry: 413 br i1 %b, label %if, label %then 414 415if: 416 br label %then 417 418then: 419 %p0 = phi i8 [ %x, %if ], [ -42, %entry ] 420 %p1 = phi i8 [ %y, %if ], [ 17, %entry ] 421 %r = udiv i8 %p0, %p1 422 ret i8 %r 423} 424 425define i8 @srem_const_incoming1(i1 %b, i8 %x, i8 %y) { 426; CHECK-LABEL: @srem_const_incoming1( 427; CHECK-NEXT: entry: 428; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 429; CHECK: if: 430; CHECK-NEXT: [[TMP0:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]] 431; CHECK-NEXT: br label [[THEN]] 432; CHECK: then: 433; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 8, [[ENTRY:%.*]] ] 434; CHECK-NEXT: ret i8 [[R]] 435; 436entry: 437 br i1 %b, label %if, label %then 438 439if: 440 br label %then 441 442then: 443 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 444 %p1 = phi i8 [ %y, %if ], [ -17, %entry ] 445 %r = srem i8 %p0, %p1 446 ret i8 %r 447} 448 449define i8 @urem_const_incoming1(i1 %b, i8 %x, i8 %y) { 450; CHECK-LABEL: @urem_const_incoming1( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 453; CHECK: if: 454; CHECK-NEXT: [[TMP0:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]] 455; CHECK-NEXT: br label [[THEN]] 456; CHECK: then: 457; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 42, [[ENTRY:%.*]] ] 458; CHECK-NEXT: ret i8 [[R]] 459; 460entry: 461 br i1 %b, label %if, label %then 462 463if: 464 br label %then 465 466then: 467 %p0 = phi i8 [ %x, %if ], [ 42, %entry ] 468 %p1 = phi i8 [ %y, %if ], [ -17, %entry ] 469 %r = urem i8 %p0, %p1 470 ret i8 %r 471} 472 473define float @fmul_const_incoming1(i1 %b, float %x, float %y) { 474; CHECK-LABEL: @fmul_const_incoming1( 475; CHECK-NEXT: entry: 476; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 477; CHECK: if: 478; CHECK-NEXT: [[TMP0:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 479; CHECK-NEXT: br label [[THEN]] 480; CHECK: then: 481; CHECK-NEXT: [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 7.140000e+02, [[ENTRY:%.*]] ] 482; CHECK-NEXT: ret float [[R]] 483; 484entry: 485 br i1 %b, label %if, label %then 486 487if: 488 br label %then 489 490then: 491 %p0 = phi float [ %x, %if ], [ 42.0, %entry ] 492 %p1 = phi float [ %y, %if ], [ 17.0, %entry ] 493 %r = fmul float %p0, %p1 494 ret float %r 495} 496 497define float @fadd_const_incoming1(i1 %b, float %x, float %y) { 498; CHECK-LABEL: @fadd_const_incoming1( 499; CHECK-NEXT: entry: 500; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 501; CHECK: if: 502; CHECK-NEXT: [[TMP0:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]] 503; CHECK-NEXT: br label [[THEN]] 504; CHECK: then: 505; CHECK-NEXT: [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 5.900000e+01, [[ENTRY:%.*]] ] 506; CHECK-NEXT: ret float [[R]] 507; 508entry: 509 br i1 %b, label %if, label %then 510 511if: 512 br label %then 513 514then: 515 %p0 = phi float [ %x, %if ], [ 42.0, %entry ] 516 %p1 = phi float [ %y, %if ], [ 17.0, %entry ] 517 %r = fadd fast float %p0, %p1 518 ret float %r 519} 520 521define float @fsub_const_incoming1(i1 %b, float %x, float %y) { 522; CHECK-LABEL: @fsub_const_incoming1( 523; CHECK-NEXT: entry: 524; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 525; CHECK: if: 526; CHECK-NEXT: [[TMP0:%.*]] = fsub nnan ninf float [[X:%.*]], [[Y:%.*]] 527; CHECK-NEXT: br label [[THEN]] 528; CHECK: then: 529; CHECK-NEXT: [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 2.500000e+01, [[ENTRY:%.*]] ] 530; CHECK-NEXT: ret float [[R]] 531; 532entry: 533 br i1 %b, label %if, label %then 534 535if: 536 br label %then 537 538then: 539 %p0 = phi float [ %x, %if ], [ 42.0, %entry ] 540 %p1 = phi float [ %y, %if ], [ 17.0, %entry ] 541 %r = fsub ninf nnan float %p0, %p1 542 ret float %r 543} 544 545define float @frem_const_incoming1(i1 %b, float %x, float %y) { 546; CHECK-LABEL: @frem_const_incoming1( 547; CHECK-NEXT: entry: 548; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 549; CHECK: if: 550; CHECK-NEXT: [[TMP0:%.*]] = frem nsz float [[X:%.*]], [[Y:%.*]] 551; CHECK-NEXT: br label [[THEN]] 552; CHECK: then: 553; CHECK-NEXT: [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 8.000000e+00, [[ENTRY:%.*]] ] 554; CHECK-NEXT: ret float [[R]] 555; 556entry: 557 br i1 %b, label %if, label %then 558 559if: 560 br label %then 561 562then: 563 %p0 = phi float [ %x, %if ], [ 42.0, %entry ] 564 %p1 = phi float [ %y, %if ], [ 17.0, %entry ] 565 %r = frem nsz float %p0, %p1 566 ret float %r 567} 568 569define i32 @add_const_incoming0_use1(i1 %b, i32 %x, i32 %y) { 570; CHECK-LABEL: @add_const_incoming0_use1( 571; CHECK-NEXT: entry: 572; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 573; CHECK: if: 574; CHECK-NEXT: br label [[THEN]] 575; CHECK: then: 576; CHECK-NEXT: [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 577; CHECK-NEXT: [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 578; CHECK-NEXT: call void @use(i32 [[P0]]) 579; CHECK-NEXT: [[R:%.*]] = add i32 [[P0]], [[P1]] 580; CHECK-NEXT: ret i32 [[R]] 581; 582entry: 583 br i1 %b, label %if, label %then 584 585if: 586 br label %then 587 588then: 589 %p0 = phi i32 [ 42, %if ], [ %x, %entry ] 590 %p1 = phi i32 [ 17, %if ], [ %y, %entry ] 591 call void @use(i32 %p0) 592 %r = add i32 %p0, %p1 593 ret i32 %r 594} 595 596define i32 @add_const_incoming0_use2(i1 %b, i32 %x, i32 %y) { 597; CHECK-LABEL: @add_const_incoming0_use2( 598; CHECK-NEXT: entry: 599; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 600; CHECK: if: 601; CHECK-NEXT: br label [[THEN]] 602; CHECK: then: 603; CHECK-NEXT: [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 604; CHECK-NEXT: [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ] 605; CHECK-NEXT: call void @use(i32 [[P1]]) 606; CHECK-NEXT: [[R:%.*]] = add i32 [[P0]], [[P1]] 607; CHECK-NEXT: ret i32 [[R]] 608; 609entry: 610 br i1 %b, label %if, label %then 611 612if: 613 br label %then 614 615then: 616 %p0 = phi i32 [ 42, %if ], [ %x, %entry ] 617 %p1 = phi i32 [ 17, %if ], [ %y, %entry ] 618 call void @use(i32 %p1) 619 %r = add i32 %p0, %p1 620 ret i32 %r 621} 622 623define i64 @or_notconst_incoming(i1 %b, i64 %x, i64 %y) { 624; CHECK-LABEL: @or_notconst_incoming( 625; CHECK-NEXT: entry: 626; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 627; CHECK: if: 628; CHECK-NEXT: br label [[THEN]] 629; CHECK: then: 630; CHECK-NEXT: [[P0:%.*]] = phi i64 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] 631; CHECK-NEXT: [[P1:%.*]] = phi i64 [ [[Y:%.*]], [[IF]] ], [ 43, [[ENTRY]] ] 632; CHECK-NEXT: [[R:%.*]] = or i64 [[P0]], [[P1]] 633; CHECK-NEXT: ret i64 [[R]] 634; 635entry: 636 br i1 %b, label %if, label %then 637 638if: 639 br label %then 640 641then: 642 %p0 = phi i64 [ 42, %if ], [ %x, %entry ] 643 %p1 = phi i64 [ %y, %if ], [ 43, %entry ] 644 %r = or i64 %p0, %p1 645 ret i64 %r 646} 647 648; The mul could be hoisted before the call that may not return 649; if we are ok with speculating a potentially expensive op. 650 651define i8 @mul_const_incoming0_speculatable(i1 %b, i8 %x, i8 %y) { 652; CHECK-LABEL: @mul_const_incoming0_speculatable( 653; CHECK-NEXT: entry: 654; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 655; CHECK: if: 656; CHECK-NEXT: br label [[THEN]] 657; CHECK: then: 658; CHECK-NEXT: [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ] 659; CHECK-NEXT: [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ] 660; CHECK-NEXT: call void @sideeffect() 661; CHECK-NEXT: [[R:%.*]] = mul i8 [[P0]], [[P1]] 662; CHECK-NEXT: ret i8 [[R]] 663; 664entry: 665 br i1 %b, label %if, label %then 666 667if: 668 br label %then 669 670then: 671 %p0 = phi i8 [ 42, %entry ], [ %x, %if ] 672 %p1 = phi i8 [ 17, %entry ], [ %y, %if ] 673 call void @sideeffect() 674 %r = mul i8 %p0, %p1 675 ret i8 %r 676} 677 678; The udiv should never be hoisted before the call that may not return. 679 680define i8 @udiv_const_incoming0_not_speculatable(i1 %b, i8 %x, i8 %y) { 681; CHECK-LABEL: @udiv_const_incoming0_not_speculatable( 682; CHECK-NEXT: entry: 683; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 684; CHECK: if: 685; CHECK-NEXT: br label [[THEN]] 686; CHECK: then: 687; CHECK-NEXT: [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ] 688; CHECK-NEXT: [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ] 689; CHECK-NEXT: call void @sideeffect() 690; CHECK-NEXT: [[R:%.*]] = udiv i8 [[P0]], [[P1]] 691; CHECK-NEXT: ret i8 [[R]] 692; 693entry: 694 br i1 %b, label %if, label %then 695 696if: 697 br label %then 698 699then: 700 %p0 = phi i8 [ 42, %entry ], [ %x, %if ] 701 %p1 = phi i8 [ 17, %entry ], [ %y, %if ] 702 call void @sideeffect() 703 %r = udiv i8 %p0, %p1 704 ret i8 %r 705} 706 707; TODO: It is ok to hoist the udiv even though it is not in the same block as the phis. 708 709define i8 @udiv_const_incoming0_different_block(i1 %b, i8 %x, i8 %y) { 710; CHECK-LABEL: @udiv_const_incoming0_different_block( 711; CHECK-NEXT: entry: 712; CHECK-NEXT: br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]] 713; CHECK: if: 714; CHECK-NEXT: br label [[THEN]] 715; CHECK: then: 716; CHECK-NEXT: [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ] 717; CHECK-NEXT: [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ] 718; CHECK-NEXT: br label [[END:%.*]] 719; CHECK: end: 720; CHECK-NEXT: [[R:%.*]] = udiv i8 [[P0]], [[P1]] 721; CHECK-NEXT: ret i8 [[R]] 722; 723entry: 724 br i1 %b, label %if, label %then 725 726if: 727 br label %then 728 729then: 730 %p0 = phi i8 [ 42, %entry ], [ %x, %if ] 731 %p1 = phi i8 [ 17, %entry ], [ %y, %if ] 732 br label %end 733 734end: 735 %r = udiv i8 %p0, %p1 736 ret i8 %r 737} 738 739define { i64, i32 } @ParseRetVal(i1 %b, ptr %x) { 740; CHECK-LABEL: @ParseRetVal( 741; CHECK-NEXT: entry: 742; CHECK-NEXT: br i1 [[B:%.*]], label [[T:%.*]], label [[F:%.*]] 743; CHECK: t: 744; CHECK-NEXT: [[T4:%.*]] = tail call { i64, i32 } [[X:%.*]]() 745; CHECK-NEXT: [[T5:%.*]] = extractvalue { i64, i32 } [[T4]], 0 746; CHECK-NEXT: [[T6:%.*]] = extractvalue { i64, i32 } [[T4]], 1 747; CHECK-NEXT: br label [[F]] 748; CHECK: f: 749; CHECK-NEXT: [[T16:%.*]] = phi i32 [ [[T6]], [[T]] ], [ 0, [[ENTRY:%.*]] ] 750; CHECK-NEXT: [[T19:%.*]] = phi i64 [ [[T5]], [[T]] ], [ 0, [[ENTRY]] ] 751; CHECK-NEXT: [[T20:%.*]] = insertvalue { i64, i32 } poison, i64 [[T19]], 0 752; CHECK-NEXT: [[T21:%.*]] = insertvalue { i64, i32 } [[T20]], i32 [[T16]], 1 753; CHECK-NEXT: ret { i64, i32 } [[T21]] 754; 755entry: 756 br i1 %b, label %t, label %f 757 758t: 759 %t4 = tail call { i64, i32 } %x() 760 %t5 = extractvalue { i64, i32 } %t4, 0 761 %t6 = extractvalue { i64, i32 } %t4, 1 762 %t7 = and i64 %t5, -4294967296 763 %t8 = and i64 %t5, 4294901760 764 %t9 = and i64 %t5, 65280 765 %t10 = and i64 %t5, 255 766 br label %f 767 768f: 769 %t12 = phi i64 [ %t10, %t ], [ 0, %entry ] 770 %t13 = phi i64 [ %t9, %t ], [ 0, %entry ] 771 %t14 = phi i64 [ %t8, %t ], [ 0, %entry ] 772 %t15 = phi i64 [ %t7, %t ], [ 0, %entry ] 773 %t16 = phi i32 [ %t6, %t ], [ 0, %entry ] 774 %t17 = or i64 %t13, %t12 775 %t18 = or i64 %t17, %t14 776 %t19 = or i64 %t18, %t15 777 %t20 = insertvalue { i64, i32 } poison, i64 %t19, 0 778 %t21 = insertvalue { i64, i32 } %t20, i32 %t16, 1 779 ret { i64, i32 } %t21 780} 781