1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -correlated-propagation -S | FileCheck %s 3; PR2581 4 5define i32 @test1(i1 %C) { 6; CHECK-LABEL: @test1( 7; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[BODY:%.*]] 8; CHECK: body: 9; CHECK-NEXT: ret i32 11 10; CHECK: exit: 11; CHECK-NEXT: ret i32 10 12; 13 br i1 %C, label %exit, label %body 14 15body: ; preds = %0 16 %A = select i1 %C, i32 10, i32 11 17 ret i32 %A 18 19exit: ; preds = %0 20 ret i32 10 21} 22 23; PR4420 24declare i1 @ext() 25define i1 @test2() { 26; CHECK-LABEL: @test2( 27; CHECK-NEXT: entry: 28; CHECK-NEXT: [[COND:%.*]] = tail call i1 @ext() 29; CHECK-NEXT: br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]] 30; CHECK: bb1: 31; CHECK-NEXT: [[COND2:%.*]] = tail call i1 @ext() 32; CHECK-NEXT: br i1 [[COND2]], label [[BB3:%.*]], label [[BB2]] 33; CHECK: bb2: 34; CHECK-NEXT: ret i1 false 35; CHECK: bb3: 36; CHECK-NEXT: [[RES:%.*]] = tail call i1 @ext() 37; CHECK-NEXT: ret i1 [[RES]] 38; 39entry: 40 %cond = tail call i1 @ext() 41 br i1 %cond, label %bb1, label %bb2 42 43bb1: 44 %cond2 = tail call i1 @ext() 45 br i1 %cond2, label %bb3, label %bb2 46 47bb2: 48 %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] 49 ret i1 %cond_merge 50 51bb3: 52 %res = tail call i1 @ext() 53 ret i1 %res 54} 55 56; PR4855 57@gv = internal constant i8 7 58define i8 @test3(i8* %a) nounwind { 59; CHECK-LABEL: @test3( 60; CHECK-NEXT: entry: 61; CHECK-NEXT: [[COND:%.*]] = icmp eq i8* [[A:%.*]], @gv 62; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB:%.*]] 63; CHECK: bb: 64; CHECK-NEXT: ret i8 0 65; CHECK: bb2: 66; CHECK-NEXT: [[SHOULD_BE_CONST:%.*]] = load i8, i8* @gv 67; CHECK-NEXT: ret i8 [[SHOULD_BE_CONST]] 68; 69entry: 70 %cond = icmp eq i8* %a, @gv 71 br i1 %cond, label %bb2, label %bb 72 73bb: 74 ret i8 0 75 76bb2: 77 %should_be_const = load i8, i8* %a 78 ret i8 %should_be_const 79} 80 81; PR1757 82define i32 @test4(i32) { 83; CHECK-LABEL: @test4( 84; CHECK-NEXT: EntryBlock: 85; CHECK-NEXT: [[DOTDEMORGAN:%.*]] = icmp sgt i32 [[TMP0:%.*]], 2 86; CHECK-NEXT: br i1 [[DOTDEMORGAN]], label [[GREATERTHANTWO:%.*]], label [[LESSTHANOREQUALTOTWO:%.*]] 87; CHECK: GreaterThanTwo: 88; CHECK-NEXT: br i1 false, label [[IMPOSSIBLE:%.*]], label [[NOTTWOANDGREATERTHANTWO:%.*]] 89; CHECK: NotTwoAndGreaterThanTwo: 90; CHECK-NEXT: ret i32 2 91; CHECK: Impossible: 92; CHECK-NEXT: ret i32 1 93; CHECK: LessThanOrEqualToTwo: 94; CHECK-NEXT: ret i32 0 95; 96EntryBlock: 97 %.demorgan = icmp sgt i32 %0, 2 98 br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo 99 100GreaterThanTwo: 101 icmp eq i32 %0, 2 102 br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo 103 104NotTwoAndGreaterThanTwo: 105 ret i32 2 106 107Impossible: 108 ret i32 1 109 110LessThanOrEqualToTwo: 111 ret i32 0 112} 113 114declare i32* @f(i32*) 115define void @test5(i32* %x, i32* %y) { 116; CHECK-LABEL: @test5( 117; CHECK-NEXT: entry: 118; CHECK-NEXT: [[PRE:%.*]] = icmp eq i32* [[X:%.*]], null 119; CHECK-NEXT: br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]] 120; CHECK: loop: 121; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ] 122; CHECK-NEXT: [[F]] = tail call i32* @f(i32* [[PHI]]) 123; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32* [[F]], [[Y:%.*]] 124; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32* [[F]], i32* null 125; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[SEL]], null 126; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN]], label [[LOOP]] 127; CHECK: return: 128; CHECK-NEXT: ret void 129; 130entry: 131 %pre = icmp eq i32* %x, null 132 br i1 %pre, label %return, label %loop 133 134loop: 135 %phi = phi i32* [ %sel, %loop ], [ %x, %entry ] 136 %f = tail call i32* @f(i32* %phi) 137 %cmp1 = icmp ne i32* %f, %y 138 %sel = select i1 %cmp1, i32* %f, i32* null 139 %cmp2 = icmp eq i32* %sel, null 140 br i1 %cmp2, label %return, label %loop 141 142return: 143 ret void 144} 145 146define i32 @switch1(i32 %s) { 147; CHECK-LABEL: @switch1( 148; CHECK-NEXT: entry: 149; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[S:%.*]], 0 150; CHECK-NEXT: br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]] 151; CHECK: negative: 152; CHECK-NEXT: switch i32 [[S]], label [[OUT]] [ 153; CHECK-NEXT: i32 -2, label [[NEXT:%.*]] 154; CHECK-NEXT: i32 -1, label [[NEXT]] 155; CHECK-NEXT: ] 156; CHECK: out: 157; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ] 158; CHECK-NEXT: ret i32 [[P]] 159; CHECK: next: 160; CHECK-NEXT: ret i32 0 161; 162entry: 163 %cmp = icmp slt i32 %s, 0 164 br i1 %cmp, label %negative, label %out 165 166negative: 167 switch i32 %s, label %out [ 168 i32 0, label %out 169 i32 1, label %out 170 i32 -1, label %next 171 i32 -2, label %next 172 i32 2, label %out 173 i32 3, label %out 174 ] 175 176out: 177 %p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ] 178 ret i32 %p 179 180next: 181 %q = phi i32 [ 0, %negative ], [ 0, %negative ] 182 ret i32 %q 183} 184 185define i32 @switch2(i32 %s) { 186; CHECK-LABEL: @switch2( 187; CHECK-NEXT: entry: 188; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0 189; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] 190; CHECK: positive: 191; CHECK-NEXT: br label [[OUT]] 192; CHECK: out: 193; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] 194; CHECK-NEXT: ret i32 [[P]] 195; CHECK: next: 196; CHECK-NEXT: ret i32 0 197; 198entry: 199 %cmp = icmp sgt i32 %s, 0 200 br i1 %cmp, label %positive, label %out 201 202positive: 203 switch i32 %s, label %out [ 204 i32 0, label %out 205 i32 -1, label %next 206 i32 -2, label %next 207 ] 208 209out: 210 %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] 211 ret i32 %p 212 213next: 214 %q = phi i32 [ 0, %positive ], [ 0, %positive ] 215 ret i32 %q 216} 217 218define i32 @switch3(i32 %s) { 219; CHECK-LABEL: @switch3( 220; CHECK-NEXT: entry: 221; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S:%.*]], 0 222; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] 223; CHECK: positive: 224; CHECK-NEXT: br label [[OUT]] 225; CHECK: out: 226; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] 227; CHECK-NEXT: ret i32 [[P]] 228; CHECK: next: 229; CHECK-NEXT: ret i32 0 230; 231entry: 232 %cmp = icmp sgt i32 %s, 0 233 br i1 %cmp, label %positive, label %out 234 235positive: 236 switch i32 %s, label %out [ 237 i32 -1, label %out 238 i32 -2, label %next 239 i32 -3, label %next 240 ] 241 242out: 243 %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] 244 ret i32 %p 245 246next: 247 %q = phi i32 [ 0, %positive ], [ 0, %positive ] 248 ret i32 %q 249} 250 251define void @switch4(i32 %s) { 252; CHECK-LABEL: @switch4( 253; CHECK-NEXT: entry: 254; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[S:%.*]], 0 255; CHECK-NEXT: br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]] 256; CHECK: zero: 257; CHECK-NEXT: br label [[NEXT:%.*]] 258; CHECK: out: 259; CHECK-NEXT: ret void 260; CHECK: next: 261; CHECK-NEXT: ret void 262; 263entry: 264 %cmp = icmp eq i32 %s, 0 265 br i1 %cmp, label %zero, label %out 266 267zero: 268 switch i32 %s, label %out [ 269 i32 0, label %next 270 i32 1, label %out 271 i32 -1, label %out 272 ] 273 274out: 275 ret void 276 277next: 278 ret void 279} 280 281define i1 @arg_attribute(i8* nonnull %a) { 282; CHECK-LABEL: @arg_attribute( 283; CHECK-NEXT: br label [[EXIT:%.*]] 284; CHECK: exit: 285; CHECK-NEXT: ret i1 false 286; 287 %cmp = icmp eq i8* %a, null 288 br label %exit 289 290exit: 291 ret i1 %cmp 292} 293 294declare nonnull i8* @return_nonnull() 295define i1 @call_attribute() { 296; CHECK-LABEL: @call_attribute( 297; CHECK-NEXT: [[A:%.*]] = call i8* @return_nonnull() 298; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[A]], null 299; CHECK-NEXT: br label [[EXIT:%.*]] 300; CHECK: exit: 301; CHECK-NEXT: ret i1 false 302; 303 %a = call i8* @return_nonnull() 304 %cmp = icmp eq i8* %a, null 305 br label %exit 306 307exit: 308 ret i1 %cmp 309} 310 311define i1 @umin(i32 %a, i32 %b) { 312; CHECK-LABEL: @umin( 313; CHECK-NEXT: entry: 314; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 315; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 316; CHECK: a_guard: 317; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 318; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 319; CHECK: b_guard: 320; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]] 321; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 322; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7 323; CHECK-NEXT: br label [[NEXT:%.*]] 324; CHECK: next: 325; CHECK-NEXT: ret i1 false 326; CHECK: out: 327; CHECK-NEXT: ret i1 false 328; 329entry: 330 %cmp = icmp ult i32 %a, 5 331 br i1 %cmp, label %a_guard, label %out 332 333a_guard: 334 %cmp2 = icmp ult i32 %b, 20 335 br i1 %cmp2, label %b_guard, label %out 336 337b_guard: 338 %sel_cmp = icmp ult i32 %a, %b 339 %min = select i1 %sel_cmp, i32 %a, i32 %b 340 %res = icmp eq i32 %min, 7 341 br label %next 342next: 343 ret i1 %res 344out: 345 ret i1 false 346} 347 348define i1 @smin(i32 %a, i32 %b) { 349; CHECK-LABEL: @smin( 350; CHECK-NEXT: entry: 351; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 352; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 353; CHECK: a_guard: 354; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 355; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 356; CHECK: b_guard: 357; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sle i32 [[A]], [[B]] 358; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 359; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MIN]], 7 360; CHECK-NEXT: br label [[NEXT:%.*]] 361; CHECK: next: 362; CHECK-NEXT: ret i1 false 363; CHECK: out: 364; CHECK-NEXT: ret i1 false 365; 366entry: 367 %cmp = icmp ult i32 %a, 5 368 br i1 %cmp, label %a_guard, label %out 369 370a_guard: 371 %cmp2 = icmp ult i32 %b, 20 372 br i1 %cmp2, label %b_guard, label %out 373 374b_guard: 375 %sel_cmp = icmp sle i32 %a, %b 376 %min = select i1 %sel_cmp, i32 %a, i32 %b 377 %res = icmp eq i32 %min, 7 378 br label %next 379next: 380 ret i1 %res 381out: 382 ret i1 false 383} 384 385define i1 @smax(i32 %a, i32 %b) { 386; CHECK-LABEL: @smax( 387; CHECK-NEXT: entry: 388; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 389; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 390; CHECK: a_guard: 391; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 392; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 393; CHECK: b_guard: 394; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], [[B]] 395; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 396; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7 397; CHECK-NEXT: br label [[NEXT:%.*]] 398; CHECK: next: 399; CHECK-NEXT: ret i1 false 400; CHECK: out: 401; CHECK-NEXT: ret i1 false 402; 403entry: 404 %cmp = icmp sgt i32 %a, 5 405 br i1 %cmp, label %a_guard, label %out 406 407a_guard: 408 %cmp2 = icmp sgt i32 %b, 20 409 br i1 %cmp2, label %b_guard, label %out 410 411b_guard: 412 %sel_cmp = icmp sge i32 %a, %b 413 %max = select i1 %sel_cmp, i32 %a, i32 %b 414 %res = icmp eq i32 %max, 7 415 br label %next 416next: 417 ret i1 %res 418out: 419 ret i1 false 420} 421 422define i1 @umax(i32 %a, i32 %b) { 423; CHECK-LABEL: @umax( 424; CHECK-NEXT: entry: 425; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 426; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 427; CHECK: a_guard: 428; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 429; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 430; CHECK: b_guard: 431; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]] 432; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 433; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[MAX]], 7 434; CHECK-NEXT: br label [[NEXT:%.*]] 435; CHECK: next: 436; CHECK-NEXT: ret i1 false 437; CHECK: out: 438; CHECK-NEXT: ret i1 false 439; 440entry: 441 %cmp = icmp sgt i32 %a, 5 442 br i1 %cmp, label %a_guard, label %out 443 444a_guard: 445 %cmp2 = icmp sgt i32 %b, 20 446 br i1 %cmp2, label %b_guard, label %out 447 448b_guard: 449 %sel_cmp = icmp uge i32 %a, %b 450 %max = select i1 %sel_cmp, i32 %a, i32 %b 451 %res = icmp eq i32 %max, 7 452 br label %next 453next: 454 ret i1 %res 455out: 456 ret i1 false 457} 458 459define i1 @clamp_low1(i32 %a) { 460; CHECK-LABEL: @clamp_low1( 461; CHECK-NEXT: entry: 462; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 463; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 464; CHECK: a_guard: 465; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 466; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], -1 467; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]] 468; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4 469; CHECK-NEXT: br label [[NEXT:%.*]] 470; CHECK: next: 471; CHECK-NEXT: ret i1 false 472; CHECK: out: 473; CHECK-NEXT: ret i1 false 474; 475entry: 476 %cmp = icmp sge i32 %a, 5 477 br i1 %cmp, label %a_guard, label %out 478 479a_guard: 480 %sel_cmp = icmp eq i32 %a, 5 481 %add = add i32 %a, -1 482 %sel = select i1 %sel_cmp, i32 5, i32 %a 483 %res = icmp eq i32 %sel, 4 484 br label %next 485next: 486 ret i1 %res 487out: 488 ret i1 false 489} 490 491define i1 @clamp_low2(i32 %a) { 492; CHECK-LABEL: @clamp_low2( 493; CHECK-NEXT: entry: 494; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 495; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 496; CHECK: a_guard: 497; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 498; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], -1 499; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 500; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4 501; CHECK-NEXT: br label [[NEXT:%.*]] 502; CHECK: next: 503; CHECK-NEXT: ret i1 false 504; CHECK: out: 505; CHECK-NEXT: ret i1 false 506; 507entry: 508 %cmp = icmp sge i32 %a, 5 509 br i1 %cmp, label %a_guard, label %out 510 511a_guard: 512 %sel_cmp = icmp ne i32 %a, 5 513 %add = add i32 %a, -1 514 %sel = select i1 %sel_cmp, i32 %a, i32 5 515 %res = icmp eq i32 %sel, 4 516 br label %next 517next: 518 ret i1 %res 519out: 520 ret i1 false 521} 522 523define i1 @clamp_high1(i32 %a) { 524; CHECK-LABEL: @clamp_high1( 525; CHECK-NEXT: entry: 526; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 527; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 528; CHECK: a_guard: 529; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 530; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 531; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[A]] 532; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6 533; CHECK-NEXT: br label [[NEXT:%.*]] 534; CHECK: next: 535; CHECK-NEXT: ret i1 false 536; CHECK: out: 537; CHECK-NEXT: ret i1 false 538; 539entry: 540 %cmp = icmp sle i32 %a, 5 541 br i1 %cmp, label %a_guard, label %out 542 543a_guard: 544 %sel_cmp = icmp eq i32 %a, 5 545 %add = add i32 %a, 1 546 %sel = select i1 %sel_cmp, i32 5, i32 %a 547 %res = icmp eq i32 %sel, 6 548 br label %next 549next: 550 ret i1 %res 551out: 552 ret i1 false 553} 554 555define i1 @clamp_high2(i32 %a) { 556; CHECK-LABEL: @clamp_high2( 557; CHECK-NEXT: entry: 558; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 559; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 560; CHECK: a_guard: 561; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 562; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 1 563; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 564; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6 565; CHECK-NEXT: br label [[NEXT:%.*]] 566; CHECK: next: 567; CHECK-NEXT: ret i1 false 568; CHECK: out: 569; CHECK-NEXT: ret i1 false 570; 571entry: 572 %cmp = icmp sle i32 %a, 5 573 br i1 %cmp, label %a_guard, label %out 574 575a_guard: 576 %sel_cmp = icmp ne i32 %a, 5 577 %add = add i32 %a, 1 578 %sel = select i1 %sel_cmp, i32 %a, i32 5 579 %res = icmp eq i32 %sel, 6 580 br label %next 581next: 582 ret i1 %res 583out: 584 ret i1 false 585} 586 587; Just showing arbitrary constants work, not really a clamp 588define i1 @clamp_high3(i32 %a) { 589; CHECK-LABEL: @clamp_high3( 590; CHECK-NEXT: entry: 591; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 592; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 593; CHECK: a_guard: 594; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 595; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 100 596; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 5 597; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 105 598; CHECK-NEXT: br label [[NEXT:%.*]] 599; CHECK: next: 600; CHECK-NEXT: ret i1 false 601; CHECK: out: 602; CHECK-NEXT: ret i1 false 603; 604entry: 605 %cmp = icmp sle i32 %a, 5 606 br i1 %cmp, label %a_guard, label %out 607 608a_guard: 609 %sel_cmp = icmp ne i32 %a, 5 610 %add = add i32 %a, 100 611 %sel = select i1 %sel_cmp, i32 %a, i32 5 612 %res = icmp eq i32 %sel, 105 613 br label %next 614next: 615 ret i1 %res 616out: 617 ret i1 false 618} 619 620define i1 @zext_unknown(i8 %a) { 621; CHECK-LABEL: @zext_unknown( 622; CHECK-NEXT: entry: 623; CHECK-NEXT: [[A32:%.*]] = zext i8 [[A:%.*]] to i32 624; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 256 625; CHECK-NEXT: br label [[EXIT:%.*]] 626; CHECK: exit: 627; CHECK-NEXT: ret i1 true 628; 629entry: 630 %a32 = zext i8 %a to i32 631 %cmp = icmp sle i32 %a32, 256 632 br label %exit 633exit: 634 ret i1 %cmp 635} 636 637define i1 @trunc_unknown(i32 %a) { 638; CHECK-LABEL: @trunc_unknown( 639; CHECK-NEXT: entry: 640; CHECK-NEXT: [[A8:%.*]] = trunc i32 [[A:%.*]] to i8 641; CHECK-NEXT: [[A32:%.*]] = sext i8 [[A8]] to i32 642; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 643; CHECK-NEXT: br label [[EXIT:%.*]] 644; CHECK: exit: 645; CHECK-NEXT: ret i1 true 646; 647entry: 648 %a8 = trunc i32 %a to i8 649 %a32 = sext i8 %a8 to i32 650 %cmp = icmp sle i32 %a32, 128 651 br label %exit 652exit: 653 ret i1 %cmp 654} 655 656; TODO: missed optimization 657; Make sure we exercise non-integer inputs to unary operators (i.e. crash check). 658define i1 @bitcast_unknown(float %a) { 659; CHECK-LABEL: @bitcast_unknown( 660; CHECK-NEXT: entry: 661; CHECK-NEXT: [[A32:%.*]] = bitcast float [[A:%.*]] to i32 662; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 663; CHECK-NEXT: br label [[EXIT:%.*]] 664; CHECK: exit: 665; CHECK-NEXT: ret i1 [[CMP]] 666; 667entry: 668 %a32 = bitcast float %a to i32 669 %cmp = icmp sle i32 %a32, 128 670 br label %exit 671exit: 672 ret i1 %cmp 673} 674 675define i1 @bitcast_unknown2(i8* %p) { 676; CHECK-LABEL: @bitcast_unknown2( 677; CHECK-NEXT: entry: 678; CHECK-NEXT: [[P64:%.*]] = ptrtoint i8* [[P:%.*]] to i64 679; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[P64]], 128 680; CHECK-NEXT: br label [[EXIT:%.*]] 681; CHECK: exit: 682; CHECK-NEXT: ret i1 [[CMP]] 683; 684entry: 685 %p64 = ptrtoint i8* %p to i64 686 %cmp = icmp sle i64 %p64, 128 687 br label %exit 688exit: 689 ret i1 %cmp 690} 691 692 693define i1 @and_unknown(i32 %a) { 694; CHECK-LABEL: @and_unknown( 695; CHECK-NEXT: entry: 696; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 128 697; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128 698; CHECK-NEXT: br label [[EXIT:%.*]] 699; CHECK: exit: 700; CHECK-NEXT: ret i1 true 701; 702entry: 703 %and = and i32 %a, 128 704 %cmp = icmp sle i32 %and, 128 705 br label %exit 706exit: 707 ret i1 %cmp 708} 709 710define i1 @lshr_unknown(i32 %a) { 711; CHECK-LABEL: @lshr_unknown( 712; CHECK-NEXT: entry: 713; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[A:%.*]], 30 714; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[AND]], 128 715; CHECK-NEXT: br label [[EXIT:%.*]] 716; CHECK: exit: 717; CHECK-NEXT: ret i1 true 718; 719entry: 720 %and = lshr i32 %a, 30 721 %cmp = icmp sle i32 %and, 128 722 br label %exit 723exit: 724 ret i1 %cmp 725} 726