1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=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, align 1 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 void @switch_nonzero_zext(i8 %s) { 282; CHECK-LABEL: @switch_nonzero_zext( 283; CHECK-NEXT: entry: 284; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[S:%.*]], 0 285; CHECK-NEXT: br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]] 286; CHECK: switch: 287; CHECK-NEXT: [[S_EXT:%.*]] = zext i8 [[S]] to i32 288; CHECK-NEXT: br label [[EXIT]] 289; CHECK: exit: 290; CHECK-NEXT: ret void 291; CHECK: unreachable: 292; CHECK-NEXT: ret void 293; 294entry: 295 %cmp = icmp ne i8 %s, 0 296 br i1 %cmp, label %switch, label %exit 297 298switch: 299 %s.ext = zext i8 %s to i32 300 switch i32 %s.ext, label %exit [ 301 i32 0, label %unreachable 302 i32 1, label %exit 303 i32 -1, label %exit 304 ] 305 306exit: 307 ret void 308 309unreachable: 310 ret void 311} 312 313define void @switch_assume_nonzero(i32 %s) { 314; CHECK-LABEL: @switch_assume_nonzero( 315; CHECK-NEXT: entry: 316; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[S:%.*]], 0 317; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 318; CHECK-NEXT: br label [[EXIT:%.*]] 319; CHECK: exit: 320; CHECK-NEXT: ret void 321; CHECK: unreachable: 322; CHECK-NEXT: ret void 323; 324entry: 325 %cmp = icmp ne i32 %s, 0 326 call void @llvm.assume(i1 %cmp) 327 switch i32 %s, label %exit [ 328 i32 0, label %unreachable 329 i32 1, label %exit 330 i32 -1, label %exit 331 ] 332 333exit: 334 ret void 335 336unreachable: 337 ret void 338} 339 340define void @switch_nonzero_phi(i1 %cond) { 341; CHECK-LABEL: @switch_nonzero_phi( 342; CHECK-NEXT: entry: 343; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 344; CHECK: if: 345; CHECK-NEXT: br label [[SWITCH:%.*]] 346; CHECK: else: 347; CHECK-NEXT: br label [[SWITCH]] 348; CHECK: switch: 349; CHECK-NEXT: [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ] 350; CHECK-NEXT: br label [[EXIT:%.*]] 351; CHECK: exit: 352; CHECK-NEXT: ret void 353; CHECK: unreachable: 354; CHECK-NEXT: ret void 355; 356entry: 357 br i1 %cond, label %if, label %else 358 359if: 360 br label %switch 361 362else: 363 br label %switch 364 365switch: 366 %s = phi i32 [ 1, %if ], [ -1, %else ] 367 switch i32 %s, label %exit [ 368 i32 0, label %unreachable 369 i32 1, label %exit 370 i32 -1, label %exit 371 ] 372 373exit: 374 ret void 375 376unreachable: 377 ret void 378} 379 380define i32 @switch_range(i32 %cond) { 381; CHECK-LABEL: @switch_range( 382; CHECK-NEXT: entry: 383; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3 384; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1 385; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [ 386; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] 387; CHECK-NEXT: i32 2, label [[EXIT2:%.*]] 388; CHECK-NEXT: i32 3, label [[EXIT1]] 389; CHECK-NEXT: ] 390; CHECK: exit1: 391; CHECK-NEXT: ret i32 1 392; CHECK: exit2: 393; CHECK-NEXT: ret i32 2 394; CHECK: unreachable: 395; CHECK-NEXT: ret i32 0 396; 397entry: 398 %s = urem i32 %cond, 3 399 %s1 = add i32 %s, 1 400 switch i32 %s1, label %unreachable [ 401 i32 1, label %exit1 402 i32 2, label %exit2 403 i32 3, label %exit1 404 ] 405 406exit1: 407 ret i32 1 408exit2: 409 ret i32 2 410unreachable: 411 ret i32 0 412} 413 414; If the cases do not cover the entire range of the 415; switch condition, we should not change the default. 416 417define i32 @switch_range_not_full(i32 %cond) { 418; CHECK-LABEL: @switch_range_not_full( 419; CHECK-NEXT: entry: 420; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3 421; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1 422; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [ 423; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] 424; CHECK-NEXT: i32 3, label [[EXIT2:%.*]] 425; CHECK-NEXT: ] 426; CHECK: exit1: 427; CHECK-NEXT: ret i32 1 428; CHECK: exit2: 429; CHECK-NEXT: ret i32 2 430; CHECK: unreachable: 431; CHECK-NEXT: ret i32 0 432; 433entry: 434 %s = urem i32 %cond, 3 435 %s1 = add i32 %s, 1 436 switch i32 %s1, label %unreachable [ 437 i32 1, label %exit1 438 i32 3, label %exit2 439 ] 440 441exit1: 442 ret i32 1 443exit2: 444 ret i32 2 445unreachable: 446 ret i32 0 447} 448 449; PR51531 450 451define i8 @switch_defaultdest_multipleuse(i8 %t0) { 452; CHECK-LABEL: @switch_defaultdest_multipleuse( 453; CHECK-NEXT: entry: 454; CHECK-NEXT: [[O:%.*]] = or i8 [[T0:%.*]], 1 455; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]] 456; CHECK-NEXT: switch i8 [[R]], label [[EXIT:%.*]] [ 457; CHECK-NEXT: i8 0, label [[EXIT]] 458; CHECK-NEXT: i8 1, label [[EXIT]] 459; CHECK-NEXT: ] 460; CHECK: exit: 461; CHECK-NEXT: ret i8 0 462; 463entry: 464 %o = or i8 %t0, 1 465 %r = srem i8 1, %o 466 switch i8 %r, label %exit [ 467 i8 0, label %exit 468 i8 1, label %exit 469 ] 470 471exit: 472 ret i8 0 473} 474 475define i1 @arg_attribute(i8* nonnull %a) { 476; CHECK-LABEL: @arg_attribute( 477; CHECK-NEXT: ret i1 false 478; 479 %cmp = icmp eq i8* %a, null 480 ret i1 %cmp 481} 482 483declare nonnull i8* @return_nonnull() 484define i1 @call_attribute() { 485; CHECK-LABEL: @call_attribute( 486; CHECK-NEXT: [[A:%.*]] = call i8* @return_nonnull() 487; CHECK-NEXT: ret i1 false 488; 489 %a = call i8* @return_nonnull() 490 %cmp = icmp eq i8* %a, null 491 ret i1 %cmp 492} 493 494define i1 @umin(i32 %a, i32 %b) { 495; CHECK-LABEL: @umin( 496; CHECK-NEXT: entry: 497; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 498; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 499; CHECK: a_guard: 500; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 501; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 502; CHECK: b_guard: 503; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ult i32 [[A]], [[B]] 504; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 505; CHECK-NEXT: ret i1 false 506; CHECK: out: 507; CHECK-NEXT: ret i1 false 508; 509entry: 510 %cmp = icmp ult i32 %a, 5 511 br i1 %cmp, label %a_guard, label %out 512 513a_guard: 514 %cmp2 = icmp ult i32 %b, 20 515 br i1 %cmp2, label %b_guard, label %out 516 517b_guard: 518 %sel_cmp = icmp ult i32 %a, %b 519 %min = select i1 %sel_cmp, i32 %a, i32 %b 520 %res = icmp eq i32 %min, 7 521 ret i1 %res 522out: 523 ret i1 false 524} 525 526define i1 @smin(i32 %a, i32 %b) { 527; CHECK-LABEL: @smin( 528; CHECK-NEXT: entry: 529; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 5 530; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 531; CHECK: a_guard: 532; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B:%.*]], 20 533; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 534; CHECK: b_guard: 535; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ule i32 [[A]], [[B]] 536; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 537; CHECK-NEXT: ret i1 false 538; CHECK: out: 539; CHECK-NEXT: ret i1 false 540; 541entry: 542 %cmp = icmp ult i32 %a, 5 543 br i1 %cmp, label %a_guard, label %out 544 545a_guard: 546 %cmp2 = icmp ult i32 %b, 20 547 br i1 %cmp2, label %b_guard, label %out 548 549b_guard: 550 %sel_cmp = icmp sle i32 %a, %b 551 %min = select i1 %sel_cmp, i32 %a, i32 %b 552 %res = icmp eq i32 %min, 7 553 ret i1 %res 554out: 555 ret i1 false 556} 557 558define i1 @smax(i32 %a, i32 %b) { 559; CHECK-LABEL: @smax( 560; CHECK-NEXT: entry: 561; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 562; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 563; CHECK: a_guard: 564; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 565; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 566; CHECK: b_guard: 567; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]] 568; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 569; CHECK-NEXT: ret i1 false 570; CHECK: out: 571; CHECK-NEXT: ret i1 false 572; 573entry: 574 %cmp = icmp sgt i32 %a, 5 575 br i1 %cmp, label %a_guard, label %out 576 577a_guard: 578 %cmp2 = icmp sgt i32 %b, 20 579 br i1 %cmp2, label %b_guard, label %out 580 581b_guard: 582 %sel_cmp = icmp sge i32 %a, %b 583 %max = select i1 %sel_cmp, i32 %a, i32 %b 584 %res = icmp eq i32 %max, 7 585 ret i1 %res 586out: 587 ret i1 false 588} 589 590define i1 @umax(i32 %a, i32 %b) { 591; CHECK-LABEL: @umax( 592; CHECK-NEXT: entry: 593; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5 594; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 595; CHECK: a_guard: 596; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B:%.*]], 20 597; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 598; CHECK: b_guard: 599; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp uge i32 [[A]], [[B]] 600; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 601; CHECK-NEXT: ret i1 false 602; CHECK: out: 603; CHECK-NEXT: ret i1 false 604; 605entry: 606 %cmp = icmp sgt i32 %a, 5 607 br i1 %cmp, label %a_guard, label %out 608 609a_guard: 610 %cmp2 = icmp sgt i32 %b, 20 611 br i1 %cmp2, label %b_guard, label %out 612 613b_guard: 614 %sel_cmp = icmp uge i32 %a, %b 615 %max = select i1 %sel_cmp, i32 %a, i32 %b 616 %res = icmp eq i32 %max, 7 617 ret i1 %res 618out: 619 ret i1 false 620} 621 622define i1 @umin_lhs_overdefined_rhs_const(i32 %a) { 623; CHECK-LABEL: @umin_lhs_overdefined_rhs_const( 624; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 42 625; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 42 626; CHECK-NEXT: ret i1 true 627; 628 %cmp = icmp ult i32 %a, 42 629 %sel = select i1 %cmp, i32 %a, i32 42 630 %cmp2 = icmp ule i32 %sel, 42 631 ret i1 %cmp2 632} 633 634define i1 @umin_rhs_overdefined_lhs_const(i32 %a) { 635; CHECK-LABEL: @umin_rhs_overdefined_lhs_const( 636; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[A:%.*]], 42 637; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[A]] 638; CHECK-NEXT: ret i1 true 639; 640 %cmp = icmp uge i32 %a, 42 641 %sel = select i1 %cmp, i32 42, i32 %a 642 %cmp2 = icmp ule i32 %sel, 42 643 ret i1 %cmp2 644} 645 646define i1 @umin_lhs_overdefined_rhs_range(i32 %a, i32 %b) { 647; CHECK-LABEL: @umin_lhs_overdefined_rhs_range( 648; CHECK-NEXT: [[ASSUME:%.*]] = icmp ult i32 [[B:%.*]], 42 649; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) 650; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B]] 651; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]] 652; CHECK-NEXT: ret i1 true 653; 654 %assume = icmp ult i32 %b, 42 655 call void @llvm.assume(i1 %assume) 656 %cmp = icmp ult i32 %a, %b 657 %sel = select i1 %cmp, i32 %a, i32 %b 658 %cmp2 = icmp ult i32 %sel, 42 659 ret i1 %cmp2 660} 661 662define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) { 663; CHECK-LABEL: @umin_rhs_overdefined_lhs_range( 664; CHECK-NEXT: [[ASSUME:%.*]] = icmp ult i32 [[B:%.*]], 42 665; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) 666; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[A:%.*]], [[B]] 667; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]] 668; CHECK-NEXT: ret i1 true 669; 670 %assume = icmp ult i32 %b, 42 671 call void @llvm.assume(i1 %assume) 672 %cmp = icmp uge i32 %a, %b 673 %sel = select i1 %cmp, i32 %b, i32 %a 674 %cmp2 = icmp ult i32 %sel, 42 675 ret i1 %cmp2 676} 677 678define i1 @clamp_low1(i32 %a) { 679; CHECK-LABEL: @clamp_low1( 680; CHECK-NEXT: entry: 681; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 682; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 683; CHECK: a_guard: 684; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 685; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 686; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 687; CHECK-NEXT: ret i1 false 688; CHECK: out: 689; CHECK-NEXT: ret i1 false 690; 691entry: 692 %cmp = icmp sge i32 %a, 5 693 br i1 %cmp, label %a_guard, label %out 694 695a_guard: 696 %sel_cmp = icmp eq i32 %a, 5 697 %add = add i32 %a, -1 698 %sel = select i1 %sel_cmp, i32 5, i32 %add 699 %res = icmp eq i32 %sel, 4 700 ret i1 %res 701out: 702 ret i1 false 703} 704 705define i1 @clamp_low2(i32 %a) { 706; CHECK-LABEL: @clamp_low2( 707; CHECK-NEXT: entry: 708; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 709; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 710; CHECK: a_guard: 711; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 712; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 713; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 714; CHECK-NEXT: ret i1 false 715; CHECK: out: 716; CHECK-NEXT: ret i1 false 717; 718entry: 719 %cmp = icmp sge i32 %a, 5 720 br i1 %cmp, label %a_guard, label %out 721 722a_guard: 723 %sel_cmp = icmp ne i32 %a, 5 724 %add = add i32 %a, -1 725 %sel = select i1 %sel_cmp, i32 %add, i32 5 726 %res = icmp eq i32 %sel, 4 727 ret i1 %res 728out: 729 ret i1 false 730} 731 732define i1 @clamp_low3(i32 %a) { 733; CHECK-LABEL: @clamp_low3( 734; CHECK-NEXT: entry: 735; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 736; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 737; CHECK: a_guard: 738; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ugt i32 [[A]], 5 739; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 740; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 741; CHECK-NEXT: ret i1 false 742; CHECK: out: 743; CHECK-NEXT: ret i1 false 744; 745entry: 746 %cmp = icmp sge i32 %a, 5 747 br i1 %cmp, label %a_guard, label %out 748 749a_guard: 750 %sel_cmp = icmp sgt i32 %a, 5 751 %add = add i32 %a, -1 752 %sel = select i1 %sel_cmp, i32 %add, i32 5 753 %res = icmp eq i32 %sel, 4 754 ret i1 %res 755out: 756 ret i1 false 757} 758 759define i1 @clamp_low4(i32 %a) { 760; CHECK-LABEL: @clamp_low4( 761; CHECK-NEXT: entry: 762; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 763; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 764; CHECK: a_guard: 765; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ule i32 [[A]], 5 766; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 767; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 768; CHECK-NEXT: ret i1 false 769; CHECK: out: 770; CHECK-NEXT: ret i1 false 771; 772entry: 773 %cmp = icmp sge i32 %a, 5 774 br i1 %cmp, label %a_guard, label %out 775 776a_guard: 777 %sel_cmp = icmp sle i32 %a, 5 778 %add = add i32 %a, -1 779 %sel = select i1 %sel_cmp, i32 5, i32 %add 780 %res = icmp eq i32 %sel, 4 781 ret i1 %res 782out: 783 ret i1 false 784} 785 786define i1 @clamp_high1(i32 %a) { 787; CHECK-LABEL: @clamp_high1( 788; CHECK-NEXT: entry: 789; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 790; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 791; CHECK: a_guard: 792; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 793; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 794; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 795; CHECK-NEXT: ret i1 false 796; CHECK: out: 797; CHECK-NEXT: ret i1 false 798; 799entry: 800 %cmp = icmp sle i32 %a, 5 801 br i1 %cmp, label %a_guard, label %out 802 803a_guard: 804 %sel_cmp = icmp eq i32 %a, 5 805 %add = add i32 %a, 1 806 %sel = select i1 %sel_cmp, i32 5, i32 %add 807 %res = icmp eq i32 %sel, 6 808 ret i1 %res 809out: 810 ret i1 false 811} 812 813define i1 @clamp_high2(i32 %a) { 814; CHECK-LABEL: @clamp_high2( 815; CHECK-NEXT: entry: 816; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 817; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 818; CHECK: a_guard: 819; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 820; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 821; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 822; CHECK-NEXT: ret i1 false 823; CHECK: out: 824; CHECK-NEXT: ret i1 false 825; 826entry: 827 %cmp = icmp sle i32 %a, 5 828 br i1 %cmp, label %a_guard, label %out 829 830a_guard: 831 %sel_cmp = icmp ne i32 %a, 5 832 %add = add i32 %a, 1 833 %sel = select i1 %sel_cmp, i32 %add, i32 5 834 %res = icmp eq i32 %sel, 6 835 ret i1 %res 836out: 837 ret i1 false 838} 839 840define i1 @clamp_high3(i32 %a) { 841; CHECK-LABEL: @clamp_high3( 842; CHECK-NEXT: entry: 843; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 844; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 845; CHECK: a_guard: 846; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp slt i32 [[A]], 5 847; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 848; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 849; CHECK-NEXT: ret i1 false 850; CHECK: out: 851; CHECK-NEXT: ret i1 false 852; 853entry: 854 %cmp = icmp sle i32 %a, 5 855 br i1 %cmp, label %a_guard, label %out 856 857a_guard: 858 %sel_cmp = icmp slt i32 %a, 5 859 %add = add i32 %a, 1 860 %sel = select i1 %sel_cmp, i32 %add, i32 5 861 %res = icmp eq i32 %sel, 6 862 ret i1 %res 863out: 864 ret i1 false 865} 866 867define i1 @clamp_high4(i32 %a) { 868; CHECK-LABEL: @clamp_high4( 869; CHECK-NEXT: entry: 870; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 871; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 872; CHECK: a_guard: 873; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], 5 874; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 875; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 876; CHECK-NEXT: ret i1 false 877; CHECK: out: 878; CHECK-NEXT: ret i1 false 879; 880entry: 881 %cmp = icmp sle i32 %a, 5 882 br i1 %cmp, label %a_guard, label %out 883 884a_guard: 885 %sel_cmp = icmp sge i32 %a, 5 886 %add = add i32 %a, 1 887 %sel = select i1 %sel_cmp, i32 5, i32 %add 888 %res = icmp eq i32 %sel, 6 889 ret i1 %res 890out: 891 ret i1 false 892} 893 894; Just showing arbitrary constants work, not really a clamp 895define i1 @not_clamp_high(i32 %a) { 896; CHECK-LABEL: @not_clamp_high( 897; CHECK-NEXT: entry: 898; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 899; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 900; CHECK: a_guard: 901; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 902; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 100 903; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 904; CHECK-NEXT: ret i1 false 905; CHECK: out: 906; CHECK-NEXT: ret i1 false 907; 908entry: 909 %cmp = icmp sle i32 %a, 5 910 br i1 %cmp, label %a_guard, label %out 911 912a_guard: 913 %sel_cmp = icmp ne i32 %a, 5 914 %add = add i32 %a, 100 915 %sel = select i1 %sel_cmp, i32 %add, i32 5 916 %res = icmp eq i32 %sel, 105 917 ret i1 %res 918out: 919 ret i1 false 920} 921 922define void @abs1(i32 %a, i1* %p) { 923; CHECK-LABEL: @abs1( 924; CHECK-NEXT: entry: 925; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10 926; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 927; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 928; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 929; CHECK: guard: 930; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 931; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 932; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]] 933; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 934; CHECK-NEXT: [[C2:%.*]] = icmp ult i32 [[ABS]], 19 935; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 936; CHECK-NEXT: store i1 true, i1* [[P]], align 1 937; CHECK-NEXT: [[C4:%.*]] = icmp uge i32 [[ABS]], 1 938; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 939; CHECK-NEXT: br label [[EXIT]] 940; CHECK: exit: 941; CHECK-NEXT: ret void 942; 943entry: 944 %cmp1 = icmp slt i32 %a, 10 945 %cmp2 = icmp sgt i32 %a, -20 946 %and = and i1 %cmp1, %cmp2 947 br i1 %and, label %guard, label %exit 948 949guard: 950 %sub = sub i32 0, %a 951 %cmp = icmp slt i32 %a, 0 952 %abs = select i1 %cmp, i32 %sub, i32 %a 953 %c1 = icmp slt i32 %abs, 20 954 store i1 %c1, i1* %p 955 %c2 = icmp slt i32 %abs, 19 956 store i1 %c2, i1* %p 957 %c3 = icmp sge i32 %abs, 0 958 store i1 %c3, i1* %p 959 %c4 = icmp sge i32 %abs, 1 960 store i1 %c4, i1* %p 961 br label %exit 962 963exit: 964 ret void 965} 966 967define void @abs2(i32 %a, i1* %p) { 968; CHECK-LABEL: @abs2( 969; CHECK-NEXT: entry: 970; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10 971; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 972; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 973; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 974; CHECK: guard: 975; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 976; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 0 977; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]] 978; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 979; CHECK-NEXT: [[C2:%.*]] = icmp ult i32 [[ABS]], 19 980; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 981; CHECK-NEXT: store i1 true, i1* [[P]], align 1 982; CHECK-NEXT: [[C4:%.*]] = icmp uge i32 [[ABS]], 1 983; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 984; CHECK-NEXT: br label [[EXIT]] 985; CHECK: exit: 986; CHECK-NEXT: ret void 987; 988entry: 989 %cmp1 = icmp slt i32 %a, 10 990 %cmp2 = icmp sgt i32 %a, -20 991 %and = and i1 %cmp1, %cmp2 992 br i1 %and, label %guard, label %exit 993 994guard: 995 %sub = sub i32 0, %a 996 %cmp = icmp sge i32 %a, 0 997 %abs = select i1 %cmp, i32 %a, i32 %sub 998 %c1 = icmp slt i32 %abs, 20 999 store i1 %c1, i1* %p 1000 %c2 = icmp slt i32 %abs, 19 1001 store i1 %c2, i1* %p 1002 %c3 = icmp sge i32 %abs, 0 1003 store i1 %c3, i1* %p 1004 %c4 = icmp sge i32 %abs, 1 1005 store i1 %c4, i1* %p 1006 br label %exit 1007 1008exit: 1009 ret void 1010} 1011 1012define void @nabs1(i32 %a, i1* %p) { 1013; CHECK-LABEL: @nabs1( 1014; CHECK-NEXT: entry: 1015; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10 1016; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1017; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1018; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1019; CHECK: guard: 1020; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1021; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 0 1022; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]] 1023; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 1024; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[NABS]], -19 1025; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1026; CHECK-NEXT: store i1 true, i1* [[P]], align 1 1027; CHECK-NEXT: [[C4:%.*]] = icmp sle i32 [[NABS]], -1 1028; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 1029; CHECK-NEXT: br label [[EXIT]] 1030; CHECK: exit: 1031; CHECK-NEXT: ret void 1032; 1033entry: 1034 %cmp1 = icmp slt i32 %a, 10 1035 %cmp2 = icmp sgt i32 %a, -20 1036 %and = and i1 %cmp1, %cmp2 1037 br i1 %and, label %guard, label %exit 1038 1039guard: 1040 %sub = sub i32 0, %a 1041 %cmp = icmp sgt i32 %a, 0 1042 %nabs = select i1 %cmp, i32 %sub, i32 %a 1043 %c1 = icmp sgt i32 %nabs, -20 1044 store i1 %c1, i1* %p 1045 %c2 = icmp sgt i32 %nabs, -19 1046 store i1 %c2, i1* %p 1047 %c3 = icmp sle i32 %nabs, 0 1048 store i1 %c3, i1* %p 1049 %c4 = icmp sle i32 %nabs, -1 1050 store i1 %c4, i1* %p 1051 br label %exit 1052 1053exit: 1054 ret void 1055} 1056 1057define void @nabs2(i32 %a, i1* %p) { 1058; CHECK-LABEL: @nabs2( 1059; CHECK-NEXT: entry: 1060; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], 10 1061; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1062; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1063; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1064; CHECK: guard: 1065; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1066; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 1067; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]] 1068; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 1069; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[NABS]], -19 1070; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1071; CHECK-NEXT: store i1 true, i1* [[P]], align 1 1072; CHECK-NEXT: [[C4:%.*]] = icmp sle i32 [[NABS]], -1 1073; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 1074; CHECK-NEXT: br label [[EXIT]] 1075; CHECK: exit: 1076; CHECK-NEXT: ret void 1077; 1078entry: 1079 %cmp1 = icmp slt i32 %a, 10 1080 %cmp2 = icmp sgt i32 %a, -20 1081 %and = and i1 %cmp1, %cmp2 1082 br i1 %and, label %guard, label %exit 1083 1084guard: 1085 %sub = sub i32 0, %a 1086 %cmp = icmp slt i32 %a, 0 1087 %nabs = select i1 %cmp, i32 %a, i32 %sub 1088 %c1 = icmp sgt i32 %nabs, -20 1089 store i1 %c1, i1* %p 1090 %c2 = icmp sgt i32 %nabs, -19 1091 store i1 %c2, i1* %p 1092 %c3 = icmp sle i32 %nabs, 0 1093 store i1 %c3, i1* %p 1094 %c4 = icmp sle i32 %nabs, -1 1095 store i1 %c4, i1* %p 1096 br label %exit 1097 1098exit: 1099 ret void 1100} 1101 1102define i1 @zext_unknown(i8 %a) { 1103; CHECK-LABEL: @zext_unknown( 1104; CHECK-NEXT: entry: 1105; CHECK-NEXT: [[A32:%.*]] = zext i8 [[A:%.*]] to i32 1106; CHECK-NEXT: ret i1 true 1107; 1108entry: 1109 %a32 = zext i8 %a to i32 1110 %cmp = icmp sle i32 %a32, 256 1111 ret i1 %cmp 1112} 1113 1114define i1 @trunc_unknown(i32 %a) { 1115; CHECK-LABEL: @trunc_unknown( 1116; CHECK-NEXT: entry: 1117; CHECK-NEXT: [[A8:%.*]] = trunc i32 [[A:%.*]] to i8 1118; CHECK-NEXT: [[A32:%.*]] = sext i8 [[A8]] to i32 1119; CHECK-NEXT: ret i1 true 1120; 1121entry: 1122 %a8 = trunc i32 %a to i8 1123 %a32 = sext i8 %a8 to i32 1124 %cmp = icmp sle i32 %a32, 128 1125 ret i1 %cmp 1126} 1127 1128define void @trunc_icmp_ule(i32 %x, i1* %p) { 1129; CHECK-LABEL: @trunc_icmp_ule( 1130; CHECK-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i8 1131; CHECK-NEXT: [[C:%.*]] = icmp uge i8 [[T]], 5 1132; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1133; CHECK: true: 1134; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 1135; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 5 1136; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1137; CHECK-NEXT: [[C3:%.*]] = icmp ule i32 [[X]], 5 1138; CHECK-NEXT: store i1 [[C3]], i1* [[P]], align 1 1139; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1140; CHECK-NEXT: ret void 1141; CHECK: false: 1142; CHECK-NEXT: [[C1_2:%.*]] = icmp uge i32 [[X]], 5 1143; CHECK-NEXT: store i1 [[C1_2]], i1* [[P]], align 1 1144; CHECK-NEXT: [[C2_2:%.*]] = icmp ugt i32 [[X]], 5 1145; CHECK-NEXT: store i1 [[C2_2]], i1* [[P]], align 1 1146; CHECK-NEXT: [[C3_2:%.*]] = icmp ule i32 [[X]], 5 1147; CHECK-NEXT: store i1 [[C3_2]], i1* [[P]], align 1 1148; CHECK-NEXT: [[C4_2:%.*]] = icmp ult i32 [[X]], 5 1149; CHECK-NEXT: store i1 [[C4_2]], i1* [[P]], align 1 1150; CHECK-NEXT: ret void 1151; 1152 %t = trunc i32 %x to i8 1153 %c = icmp uge i8 %t, 5 1154 br i1 %c, label %true, label %false 1155 1156true: 1157 %c1 = icmp uge i32 %x, 5 1158 store i1 %c1, i1* %p 1159 %c2 = icmp ugt i32 %x, 5 1160 store i1 %c2, i1* %p 1161 %c3 = icmp ule i32 %x, 5 1162 store i1 %c3, i1* %p 1163 %c4 = icmp ult i32 %x, 5 1164 store i1 %c4, i1* %p 1165 ret void 1166 1167false: 1168 %c1.2 = icmp uge i32 %x, 5 1169 store i1 %c1.2, i1* %p 1170 %c2.2 = icmp ugt i32 %x, 5 1171 store i1 %c2.2, i1* %p 1172 %c3.2 = icmp ule i32 %x, 5 1173 store i1 %c3.2, i1* %p 1174 %c4.2 = icmp ult i32 %x, 5 1175 store i1 %c4.2, i1* %p 1176 ret void 1177} 1178 1179define void @trunc_icmp_eq(i32 %x, i1* %p) { 1180; CHECK-LABEL: @trunc_icmp_eq( 1181; CHECK-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i8 1182; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[T]], 5 1183; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1184; CHECK: true: 1185; CHECK-NEXT: store i1 true, i1* [[P:%.*]], align 1 1186; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 5 1187; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1188; CHECK-NEXT: [[C3:%.*]] = icmp ule i32 [[X]], 5 1189; CHECK-NEXT: store i1 [[C3]], i1* [[P]], align 1 1190; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1191; CHECK-NEXT: ret void 1192; CHECK: false: 1193; CHECK-NEXT: [[C1_2:%.*]] = icmp uge i32 [[X]], 5 1194; CHECK-NEXT: store i1 [[C1_2]], i1* [[P]], align 1 1195; CHECK-NEXT: [[C2_2:%.*]] = icmp ugt i32 [[X]], 5 1196; CHECK-NEXT: store i1 [[C2_2]], i1* [[P]], align 1 1197; CHECK-NEXT: [[C3_2:%.*]] = icmp ule i32 [[X]], 5 1198; CHECK-NEXT: store i1 [[C3_2]], i1* [[P]], align 1 1199; CHECK-NEXT: [[C4_2:%.*]] = icmp ult i32 [[X]], 5 1200; CHECK-NEXT: store i1 [[C4_2]], i1* [[P]], align 1 1201; CHECK-NEXT: ret void 1202; 1203 %t = trunc i32 %x to i8 1204 %c = icmp eq i8 %t, 5 1205 br i1 %c, label %true, label %false 1206 1207true: 1208 %c1 = icmp uge i32 %x, 5 1209 store i1 %c1, i1* %p 1210 %c2 = icmp ugt i32 %x, 5 1211 store i1 %c2, i1* %p 1212 %c3 = icmp ule i32 %x, 5 1213 store i1 %c3, i1* %p 1214 %c4 = icmp ult i32 %x, 5 1215 store i1 %c4, i1* %p 1216 ret void 1217 1218false: 1219 %c1.2 = icmp uge i32 %x, 5 1220 store i1 %c1.2, i1* %p 1221 %c2.2 = icmp ugt i32 %x, 5 1222 store i1 %c2.2, i1* %p 1223 %c3.2 = icmp ule i32 %x, 5 1224 store i1 %c3.2, i1* %p 1225 %c4.2 = icmp ult i32 %x, 5 1226 store i1 %c4.2, i1* %p 1227 ret void 1228} 1229 1230; TODO: missed optimization 1231; Make sure we exercise non-integer inputs to unary operators (i.e. crash check). 1232define i1 @bitcast_unknown(float %a) { 1233; CHECK-LABEL: @bitcast_unknown( 1234; CHECK-NEXT: entry: 1235; CHECK-NEXT: [[A32:%.*]] = bitcast float [[A:%.*]] to i32 1236; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 1237; CHECK-NEXT: ret i1 [[CMP]] 1238; 1239entry: 1240 %a32 = bitcast float %a to i32 1241 %cmp = icmp sle i32 %a32, 128 1242 ret i1 %cmp 1243} 1244 1245define i1 @bitcast_unknown2(i8* %p) { 1246; CHECK-LABEL: @bitcast_unknown2( 1247; CHECK-NEXT: entry: 1248; CHECK-NEXT: [[P64:%.*]] = ptrtoint i8* [[P:%.*]] to i64 1249; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[P64]], 128 1250; CHECK-NEXT: ret i1 [[CMP]] 1251; 1252entry: 1253 %p64 = ptrtoint i8* %p to i64 1254 %cmp = icmp sle i64 %p64, 128 1255 ret i1 %cmp 1256} 1257 1258 1259define i1 @and_unknown(i32 %a) { 1260; CHECK-LABEL: @and_unknown( 1261; CHECK-NEXT: entry: 1262; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 128 1263; CHECK-NEXT: ret i1 true 1264; 1265entry: 1266 %and = and i32 %a, 128 1267 %cmp = icmp sle i32 %and, 128 1268 ret i1 %cmp 1269} 1270 1271define i1 @lshr_unknown(i32 %a) { 1272; CHECK-LABEL: @lshr_unknown( 1273; CHECK-NEXT: entry: 1274; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[A:%.*]], 30 1275; CHECK-NEXT: ret i1 true 1276; 1277entry: 1278 %and = lshr i32 %a, 30 1279 %cmp = icmp sle i32 %and, 128 1280 ret i1 %cmp 1281} 1282 1283define i1 @urem_unknown(i32 %a) { 1284; CHECK-LABEL: @urem_unknown( 1285; CHECK-NEXT: entry: 1286; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[A:%.*]], 30 1287; CHECK-NEXT: ret i1 true 1288; 1289entry: 1290 %urem = urem i32 %a, 30 1291 %cmp = icmp ult i32 %urem, 30 1292 ret i1 %cmp 1293} 1294 1295define i1 @srem_unknown(i32 %a) { 1296; CHECK-LABEL: @srem_unknown( 1297; CHECK-NEXT: entry: 1298; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[A:%.*]], 30 1299; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1300; CHECK: exit1: 1301; CHECK-NEXT: ret i1 true 1302; CHECK: exit2: 1303; CHECK-NEXT: ret i1 true 1304; 1305entry: 1306 %srem = srem i32 %a, 30 1307 %cmp1 = icmp slt i32 %srem, 30 1308 %cmp2 = icmp sgt i32 %srem, -30 1309 br i1 undef, label %exit1, label %exit2 1310exit1: 1311 ret i1 %cmp1 1312exit2: 1313 ret i1 %cmp2 1314} 1315 1316define i1 @sdiv_unknown(i32 %a) { 1317; CHECK-LABEL: @sdiv_unknown( 1318; CHECK-NEXT: entry: 1319; CHECK-NEXT: [[SREM:%.*]] = sdiv i32 [[A:%.*]], 123 1320; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1321; CHECK: exit1: 1322; CHECK-NEXT: ret i1 true 1323; CHECK: exit2: 1324; CHECK-NEXT: ret i1 true 1325; 1326entry: 1327 %srem = sdiv i32 %a, 123 1328 %cmp1 = icmp slt i32 %srem, 17459217 1329 %cmp2 = icmp sgt i32 %srem, -17459217 1330 br i1 undef, label %exit1, label %exit2 1331exit1: 1332 ret i1 %cmp1 1333exit2: 1334 ret i1 %cmp2 1335} 1336 1337define i1 @uadd_sat_unknown(i32 %a) { 1338; CHECK-LABEL: @uadd_sat_unknown( 1339; CHECK-NEXT: entry: 1340; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[A:%.*]], i32 100) 1341; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[VAL]], 100 1342; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1343; CHECK: exit1: 1344; CHECK-NEXT: ret i1 true 1345; CHECK: exit2: 1346; CHECK-NEXT: ret i1 [[CMP2]] 1347; 1348entry: 1349 %val = call i32 @llvm.uadd.sat.i32(i32 %a, i32 100) 1350 %cmp1 = icmp uge i32 %val, 100 1351 %cmp2 = icmp ugt i32 %val, 100 1352 br i1 undef, label %exit1, label %exit2 1353exit1: 1354 ret i1 %cmp1 1355exit2: 1356 ret i1 %cmp2 1357} 1358 1359define i1 @usub_sat_unknown(i32 %a) { 1360; CHECK-LABEL: @usub_sat_unknown( 1361; CHECK-NEXT: entry: 1362; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A:%.*]], i32 100) 1363; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[VAL]], -101 1364; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1365; CHECK: exit1: 1366; CHECK-NEXT: ret i1 true 1367; CHECK: exit2: 1368; CHECK-NEXT: ret i1 [[CMP2]] 1369; 1370entry: 1371 %val = call i32 @llvm.usub.sat.i32(i32 %a, i32 100) 1372 %cmp1 = icmp ule i32 %val, 4294967195 1373 %cmp2 = icmp ult i32 %val, 4294967195 1374 br i1 undef, label %exit1, label %exit2 1375exit1: 1376 ret i1 %cmp1 1377exit2: 1378 ret i1 %cmp2 1379} 1380 1381define i1 @sadd_sat_unknown(i32 %a) { 1382; CHECK-LABEL: @sadd_sat_unknown( 1383; CHECK-NEXT: entry: 1384; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A:%.*]], i32 100) 1385; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[VAL]], -2147483548 1386; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1387; CHECK: exit1: 1388; CHECK-NEXT: ret i1 true 1389; CHECK: exit2: 1390; CHECK-NEXT: ret i1 [[CMP2]] 1391; 1392entry: 1393 %val = call i32 @llvm.sadd.sat.i32(i32 %a, i32 100) 1394 %cmp1 = icmp sge i32 %val, -2147483548 1395 %cmp2 = icmp sgt i32 %val, -2147483548 1396 br i1 undef, label %exit1, label %exit2 1397exit1: 1398 ret i1 %cmp1 1399exit2: 1400 ret i1 %cmp2 1401} 1402 1403define i1 @ssub_sat_unknown(i32 %a) { 1404; CHECK-LABEL: @ssub_sat_unknown( 1405; CHECK-NEXT: entry: 1406; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 100) 1407; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[VAL]], 2147483547 1408; CHECK-NEXT: br i1 undef, label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1409; CHECK: exit1: 1410; CHECK-NEXT: ret i1 true 1411; CHECK: exit2: 1412; CHECK-NEXT: ret i1 [[CMP2]] 1413; 1414entry: 1415 %val = call i32 @llvm.ssub.sat.i32(i32 %a, i32 100) 1416 %cmp1 = icmp sle i32 %val, 2147483547 1417 %cmp2 = icmp slt i32 %val, 2147483547 1418 br i1 undef, label %exit1, label %exit2 1419exit1: 1420 ret i1 %cmp1 1421exit2: 1422 ret i1 %cmp2 1423} 1424 1425define void @select_and(i32 %a, i1* %p) { 1426; CHECK-LABEL: @select_and( 1427; CHECK-NEXT: entry: 1428; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10 1429; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1430; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false 1431; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1432; CHECK: guard: 1433; CHECK-NEXT: store i1 false, i1* [[P:%.*]], align 1 1434; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1435; CHECK-NEXT: br label [[EXIT]] 1436; CHECK: exit: 1437; CHECK-NEXT: ret void 1438; 1439entry: 1440 %cmp1 = icmp sgt i32 %a, -10 1441 %cmp2 = icmp slt i32 %a, 10 1442 %and = select i1 %cmp1, i1 %cmp2, i1 false 1443 br i1 %and, label %guard, label %exit 1444 1445guard: 1446 %c1 = icmp sgt i32 %a, 20 1447 store i1 %c1, i1* %p 1448 %c2 = icmp slt i32 %a, -20 1449 store i1 %c2, i1* %p 1450 br label %exit 1451 1452exit: 1453 ret void 1454} 1455 1456define void @select_and_wrong_const(i32 %a, i1* %p) { 1457; CHECK-LABEL: @select_and_wrong_const( 1458; CHECK-NEXT: entry: 1459; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10 1460; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1461; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true 1462; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1463; CHECK: guard: 1464; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1465; CHECK-NEXT: store i1 [[C1]], i1* [[P:%.*]], align 1 1466; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1467; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1468; CHECK-NEXT: br label [[EXIT]] 1469; CHECK: exit: 1470; CHECK-NEXT: ret void 1471; 1472entry: 1473 %cmp1 = icmp sgt i32 %a, -10 1474 %cmp2 = icmp slt i32 %a, 10 1475 %and = select i1 %cmp1, i1 %cmp2, i1 true 1476 br i1 %and, label %guard, label %exit 1477 1478guard: 1479 %c1 = icmp sgt i32 %a, 20 1480 store i1 %c1, i1* %p 1481 %c2 = icmp slt i32 %a, -20 1482 store i1 %c2, i1* %p 1483 br label %exit 1484 1485exit: 1486 ret void 1487} 1488 1489define void @select_and_wrong_operand(i32 %a, i1* %p) { 1490; CHECK-LABEL: @select_and_wrong_operand( 1491; CHECK-NEXT: entry: 1492; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -10 1493; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1494; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]] 1495; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1496; CHECK: guard: 1497; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1498; CHECK-NEXT: store i1 [[C1]], i1* [[P:%.*]], align 1 1499; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1500; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1501; CHECK-NEXT: br label [[EXIT]] 1502; CHECK: exit: 1503; CHECK-NEXT: ret void 1504; 1505entry: 1506 %cmp1 = icmp sgt i32 %a, -10 1507 %cmp2 = icmp slt i32 %a, 10 1508 %and = select i1 %cmp1, i1 false, i1 %cmp2 1509 br i1 %and, label %guard, label %exit 1510 1511guard: 1512 %c1 = icmp sgt i32 %a, 20 1513 store i1 %c1, i1* %p 1514 %c2 = icmp slt i32 %a, -20 1515 store i1 %c2, i1* %p 1516 br label %exit 1517 1518exit: 1519 ret void 1520} 1521 1522define void @select_or(i32 %a, i1* %p) { 1523; CHECK-LABEL: @select_or( 1524; CHECK-NEXT: entry: 1525; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10 1526; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1527; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] 1528; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1529; CHECK: guard: 1530; CHECK-NEXT: store i1 false, i1* [[P:%.*]], align 1 1531; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1532; CHECK-NEXT: br label [[EXIT]] 1533; CHECK: exit: 1534; CHECK-NEXT: ret void 1535; 1536entry: 1537 %cmp1 = icmp slt i32 %a, -10 1538 %cmp2 = icmp sgt i32 %a, 10 1539 %or = select i1 %cmp1, i1 true, i1 %cmp2 1540 br i1 %or, label %exit, label %guard 1541 1542guard: 1543 %c1 = icmp sgt i32 %a, 20 1544 store i1 %c1, i1* %p 1545 %c2 = icmp slt i32 %a, -20 1546 store i1 %c2, i1* %p 1547 br label %exit 1548 1549exit: 1550 ret void 1551} 1552 1553define void @select_or_wrong_const(i32 %a, i1* %p) { 1554; CHECK-LABEL: @select_or_wrong_const( 1555; CHECK-NEXT: entry: 1556; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10 1557; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1558; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]] 1559; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1560; CHECK: guard: 1561; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1562; CHECK-NEXT: store i1 [[C1]], i1* [[P:%.*]], align 1 1563; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1564; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1565; CHECK-NEXT: br label [[EXIT]] 1566; CHECK: exit: 1567; CHECK-NEXT: ret void 1568; 1569entry: 1570 %cmp1 = icmp slt i32 %a, -10 1571 %cmp2 = icmp sgt i32 %a, 10 1572 %or = select i1 %cmp1, i1 false, i1 %cmp2 1573 br i1 %or, label %exit, label %guard 1574 1575guard: 1576 %c1 = icmp sgt i32 %a, 20 1577 store i1 %c1, i1* %p 1578 %c2 = icmp slt i32 %a, -20 1579 store i1 %c2, i1* %p 1580 br label %exit 1581 1582exit: 1583 ret void 1584} 1585 1586define void @select_or_wrong_operand(i32 %a, i1* %p) { 1587; CHECK-LABEL: @select_or_wrong_operand( 1588; CHECK-NEXT: entry: 1589; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A:%.*]], -10 1590; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1591; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true 1592; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1593; CHECK: guard: 1594; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1595; CHECK-NEXT: store i1 [[C1]], i1* [[P:%.*]], align 1 1596; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1597; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1598; CHECK-NEXT: br label [[EXIT]] 1599; CHECK: exit: 1600; CHECK-NEXT: ret void 1601; 1602entry: 1603 %cmp1 = icmp slt i32 %a, -10 1604 %cmp2 = icmp sgt i32 %a, 10 1605 %or = select i1 %cmp1, i1 %cmp2, i1 true 1606 br i1 %or, label %exit, label %guard 1607 1608guard: 1609 %c1 = icmp sgt i32 %a, 20 1610 store i1 %c1, i1* %p 1611 %c2 = icmp slt i32 %a, -20 1612 store i1 %c2, i1* %p 1613 br label %exit 1614 1615exit: 1616 ret void 1617} 1618 1619define void @or_union(i32 %a, i1* %p) { 1620; CHECK-LABEL: @or_union( 1621; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10 1622; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 12 1623; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 1624; CHECK-NEXT: br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1625; CHECK: guard: 1626; CHECK-NEXT: store i1 false, i1* [[P:%.*]], align 1 1627; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[A]], 10 1628; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1629; CHECK-NEXT: [[C3:%.*]] = icmp eq i32 [[A]], 11 1630; CHECK-NEXT: store i1 [[C3]], i1* [[P]], align 1 1631; CHECK-NEXT: [[C4:%.*]] = icmp eq i32 [[A]], 12 1632; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 1633; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1634; CHECK-NEXT: br label [[EXIT]] 1635; CHECK: exit: 1636; CHECK-NEXT: ret void 1637; 1638 %cmp1 = icmp eq i32 %a, 10 1639 %cmp2 = icmp eq i32 %a, 12 1640 %or = or i1 %cmp1, %cmp2 1641 br i1 %or, label %guard, label %exit 1642 1643guard: 1644 %c1 = icmp eq i32 %a, 9 1645 store i1 %c1, i1* %p 1646 %c2 = icmp eq i32 %a, 10 1647 store i1 %c2, i1* %p 1648 %c3 = icmp eq i32 %a, 11 1649 store i1 %c3, i1* %p 1650 %c4 = icmp eq i32 %a, 12 1651 store i1 %c4, i1* %p 1652 %c5 = icmp eq i32 %a, 13 1653 store i1 %c5, i1* %p 1654 br label %exit 1655 1656exit: 1657 ret void 1658} 1659 1660define i1 @or_union_unknown_cond(i32 %a, i1 %c) { 1661; CHECK-LABEL: @or_union_unknown_cond( 1662; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 10 1663; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[C:%.*]] 1664; CHECK-NEXT: br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1665; CHECK: guard: 1666; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 10 1667; CHECK-NEXT: ret i1 [[CMP2]] 1668; CHECK: exit: 1669; CHECK-NEXT: ret i1 false 1670; 1671 %cmp1 = icmp eq i32 %a, 10 1672 %or = or i1 %cmp1, %c 1673 br i1 %or, label %guard, label %exit 1674 1675guard: 1676 %cmp2 = icmp eq i32 %a, 10 1677 ret i1 %cmp2 1678 1679exit: 1680 ret i1 false 1681} 1682 1683define void @and_union(i32 %a, i1* %p) { 1684; CHECK-LABEL: @and_union( 1685; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 10 1686; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[A]], 12 1687; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1688; CHECK-NEXT: br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1689; CHECK: guard: 1690; CHECK-NEXT: store i1 false, i1* [[P:%.*]], align 1 1691; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[A]], 10 1692; CHECK-NEXT: store i1 [[C2]], i1* [[P]], align 1 1693; CHECK-NEXT: [[C3:%.*]] = icmp eq i32 [[A]], 11 1694; CHECK-NEXT: store i1 [[C3]], i1* [[P]], align 1 1695; CHECK-NEXT: [[C4:%.*]] = icmp eq i32 [[A]], 12 1696; CHECK-NEXT: store i1 [[C4]], i1* [[P]], align 1 1697; CHECK-NEXT: store i1 false, i1* [[P]], align 1 1698; CHECK-NEXT: br label [[EXIT]] 1699; CHECK: exit: 1700; CHECK-NEXT: ret void 1701; 1702 %cmp1 = icmp ne i32 %a, 10 1703 %cmp2 = icmp ne i32 %a, 12 1704 %and = and i1 %cmp1, %cmp2 1705 br i1 %and, label %exit, label %guard 1706 1707guard: 1708 %c1 = icmp eq i32 %a, 9 1709 store i1 %c1, i1* %p 1710 %c2 = icmp eq i32 %a, 10 1711 store i1 %c2, i1* %p 1712 %c3 = icmp eq i32 %a, 11 1713 store i1 %c3, i1* %p 1714 %c4 = icmp eq i32 %a, 12 1715 store i1 %c4, i1* %p 1716 %c5 = icmp eq i32 %a, 13 1717 store i1 %c5, i1* %p 1718 br label %exit 1719 1720exit: 1721 ret void 1722} 1723 1724define i1 @and_union_unknown_cond(i32 %a, i1 %c) { 1725; CHECK-LABEL: @and_union_unknown_cond( 1726; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 10 1727; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[C:%.*]] 1728; CHECK-NEXT: br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1729; CHECK: guard: 1730; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 10 1731; CHECK-NEXT: ret i1 [[CMP2]] 1732; CHECK: exit: 1733; CHECK-NEXT: ret i1 false 1734; 1735 %cmp1 = icmp ne i32 %a, 10 1736 %and = and i1 %cmp1, %c 1737 br i1 %and, label %exit, label %guard 1738 1739guard: 1740 %cmp2 = icmp eq i32 %a, 10 1741 ret i1 %cmp2 1742 1743exit: 1744 ret i1 false 1745} 1746 1747define void @select_assume(i32 %a, i32 %b, i1 %c, i1* %p) { 1748; CHECK-LABEL: @select_assume( 1749; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[A:%.*]], 10 1750; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 1751; CHECK-NEXT: [[C2:%.*]] = icmp ult i32 [[B:%.*]], 20 1752; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 1753; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], i32 [[A]], i32 [[B]] 1754; CHECK-NEXT: [[C3:%.*]] = icmp ult i32 [[S]], 19 1755; CHECK-NEXT: store i1 [[C3]], i1* [[P:%.*]], align 1 1756; CHECK-NEXT: store i1 true, i1* [[P]], align 1 1757; CHECK-NEXT: ret void 1758; 1759 %c1 = icmp ult i32 %a, 10 1760 call void @llvm.assume(i1 %c1) 1761 %c2 = icmp ult i32 %b, 20 1762 call void @llvm.assume(i1 %c2) 1763 %s = select i1 %c, i32 %a, i32 %b 1764 %c3 = icmp ult i32 %s, 19 1765 store i1 %c3, i1* %p 1766 %c4 = icmp ult i32 %s, 20 1767 store i1 %c4, i1* %p 1768 ret void 1769} 1770 1771 1772declare i32 @llvm.uadd.sat.i32(i32, i32) 1773declare i32 @llvm.usub.sat.i32(i32, i32) 1774declare i32 @llvm.sadd.sat.i32(i32, i32) 1775declare i32 @llvm.ssub.sat.i32(i32, i32) 1776declare void @llvm.assume(i1) 1777