1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s 3; PR2581 4 5define i32 @test1(i1 %C) { 6; CHECK-LABEL: define range(i32 10, 12) i32 @test1 7; CHECK-SAME: (i1 [[C:%.*]]) { 8; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[BODY:%.*]] 9; CHECK: body: 10; CHECK-NEXT: ret i32 11 11; CHECK: exit: 12; CHECK-NEXT: ret i32 10 13; 14 br i1 %C, label %exit, label %body 15 16body: ; preds = %0 17 %A = select i1 %C, i32 10, i32 11 18 ret i32 %A 19 20exit: ; preds = %0 21 ret i32 10 22} 23 24; PR4420 25declare i1 @ext() 26define i1 @test2() { 27; CHECK-LABEL: define i1 @test2() { 28; CHECK-NEXT: entry: 29; CHECK-NEXT: [[COND:%.*]] = tail call i1 @ext() 30; CHECK-NEXT: br i1 [[COND]], label [[BB1:%.*]], label [[BB2:%.*]] 31; CHECK: bb1: 32; CHECK-NEXT: [[COND2:%.*]] = tail call i1 @ext() 33; CHECK-NEXT: br i1 [[COND2]], label [[BB3:%.*]], label [[BB2]] 34; CHECK: bb2: 35; CHECK-NEXT: ret i1 false 36; CHECK: bb3: 37; CHECK-NEXT: [[RES:%.*]] = tail call i1 @ext() 38; CHECK-NEXT: ret i1 [[RES]] 39; 40entry: 41 %cond = tail call i1 @ext() 42 br i1 %cond, label %bb1, label %bb2 43 44bb1: 45 %cond2 = tail call i1 @ext() 46 br i1 %cond2, label %bb3, label %bb2 47 48bb2: 49 %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] 50 ret i1 %cond_merge 51 52bb3: 53 %res = tail call i1 @ext() 54 ret i1 %res 55} 56 57; PR4855 58@gv = internal constant i8 7 59define i8 @test3(ptr %a) nounwind { 60; CHECK-LABEL: define i8 @test3 61; CHECK-SAME: (ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] { 62; CHECK-NEXT: entry: 63; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[A]], @gv 64; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB:%.*]] 65; CHECK: bb: 66; CHECK-NEXT: ret i8 0 67; CHECK: bb2: 68; CHECK-NEXT: [[SHOULD_BE_CONST:%.*]] = load i8, ptr [[A]], align 1 69; CHECK-NEXT: ret i8 [[SHOULD_BE_CONST]] 70; 71entry: 72 %cond = icmp eq ptr %a, @gv 73 br i1 %cond, label %bb2, label %bb 74 75bb: 76 ret i8 0 77 78bb2: 79 %should_be_const = load i8, ptr %a 80 ret i8 %should_be_const 81} 82 83; PR1757 84define i32 @test4(i32) { 85; CHECK-LABEL: define range(i32 0, 3) i32 @test4 86; CHECK-SAME: (i32 [[TMP0:%.*]]) { 87; CHECK-NEXT: EntryBlock: 88; CHECK-NEXT: [[DOTDEMORGAN:%.*]] = icmp sgt i32 [[TMP0]], 2 89; CHECK-NEXT: br i1 [[DOTDEMORGAN]], label [[GREATERTHANTWO:%.*]], label [[LESSTHANOREQUALTOTWO:%.*]] 90; CHECK: GreaterThanTwo: 91; CHECK-NEXT: br i1 false, label [[IMPOSSIBLE:%.*]], label [[NOTTWOANDGREATERTHANTWO:%.*]] 92; CHECK: NotTwoAndGreaterThanTwo: 93; CHECK-NEXT: ret i32 2 94; CHECK: Impossible: 95; CHECK-NEXT: ret i32 1 96; CHECK: LessThanOrEqualToTwo: 97; CHECK-NEXT: ret i32 0 98; 99EntryBlock: 100 %.demorgan = icmp sgt i32 %0, 2 101 br i1 %.demorgan, label %GreaterThanTwo, label %LessThanOrEqualToTwo 102 103GreaterThanTwo: 104 icmp eq i32 %0, 2 105 br i1 %1, label %Impossible, label %NotTwoAndGreaterThanTwo 106 107NotTwoAndGreaterThanTwo: 108 ret i32 2 109 110Impossible: 111 ret i32 1 112 113LessThanOrEqualToTwo: 114 ret i32 0 115} 116 117declare ptr @f(ptr) 118define void @test5(ptr %x, ptr %y) { 119; CHECK-LABEL: define void @test5 120; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) { 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[PRE:%.*]] = icmp eq ptr [[X]], null 123; CHECK-NEXT: br i1 [[PRE]], label [[RETURN:%.*]], label [[LOOP:%.*]] 124; CHECK: loop: 125; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ] 126; CHECK-NEXT: [[F]] = tail call ptr @f(ptr [[PHI]]) 127; CHECK-NEXT: [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y]] 128; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null 129; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[SEL]], null 130; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN]], label [[LOOP]] 131; CHECK: return: 132; CHECK-NEXT: ret void 133; 134entry: 135 %pre = icmp eq ptr %x, null 136 br i1 %pre, label %return, label %loop 137 138loop: 139 %phi = phi ptr [ %sel, %loop ], [ %x, %entry ] 140 %f = tail call ptr @f(ptr %phi) 141 %cmp1 = icmp ne ptr %f, %y 142 %sel = select i1 %cmp1, ptr %f, ptr null 143 %cmp2 = icmp eq ptr %sel, null 144 br i1 %cmp2, label %return, label %loop 145 146return: 147 ret void 148} 149 150; "false" case for CorrelatedValuePropagation 151define void @loop1(ptr %x, ptr %y) { 152; CHECK-LABEL: define void @loop1 153; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) { 154; CHECK-NEXT: entry: 155; CHECK-NEXT: br label [[LOOP:%.*]] 156; CHECK: loop: 157; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ] 158; CHECK-NEXT: [[F]] = tail call ptr @f(ptr [[PHI]]) 159; CHECK-NEXT: [[CMP1:%.*]] = icmp ne ptr [[F]], [[Y]] 160; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], ptr [[F]], ptr null 161; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[SEL]], null 162; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]] 163; CHECK: return: 164; CHECK-NEXT: ret void 165; 166entry: 167 br label %loop 168 169loop: 170 %phi = phi ptr [ %sel, %loop ], [ %x, %entry ] 171 %f = tail call ptr @f(ptr %phi) 172 %cmp1 = icmp ne ptr %f, %y 173 %sel = select i1 %cmp1, ptr %f, ptr null 174 %cmp2 = icmp eq ptr %sel, null 175 br i1 %cmp2, label %return, label %loop 176 177return: 178 ret void 179} 180 181; "true" case for CorrelatedValuePropagation 182define void @loop2(ptr %x, ptr %y) { 183; CHECK-LABEL: define void @loop2 184; CHECK-SAME: (ptr [[X:%.*]], ptr [[Y:%.*]]) { 185; CHECK-NEXT: entry: 186; CHECK-NEXT: br label [[LOOP:%.*]] 187; CHECK: loop: 188; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[F:%.*]], [[LOOP]] ], [ [[X]], [[ENTRY:%.*]] ] 189; CHECK-NEXT: [[F]] = tail call ptr @f(ptr [[PHI]]) 190; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[F]], [[Y]] 191; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], ptr null, ptr [[F]] 192; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[SEL]], null 193; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]] 194; CHECK: return: 195; CHECK-NEXT: ret void 196; 197entry: 198 br label %loop 199 200loop: 201 %phi = phi ptr [ %sel, %loop ], [ %x, %entry ] 202 %f = tail call ptr @f(ptr %phi) 203 %cmp1 = icmp eq ptr %f, %y 204 %sel = select i1 %cmp1, ptr null, ptr %f 205 %cmp2 = icmp eq ptr %sel, null 206 br i1 %cmp2, label %return, label %loop 207 208return: 209 ret void 210} 211 212define i32 @switch1(i32 %s) { 213; CHECK-LABEL: define range(i32 -1, 2) i32 @switch1 214; CHECK-SAME: (i32 [[S:%.*]]) { 215; CHECK-NEXT: entry: 216; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[S]], 0 217; CHECK-NEXT: br i1 [[CMP]], label [[NEGATIVE:%.*]], label [[OUT:%.*]] 218; CHECK: negative: 219; CHECK-NEXT: switch i32 [[S]], label [[OUT]] [ 220; CHECK-NEXT: i32 -2, label [[NEXT:%.*]] 221; CHECK-NEXT: i32 -1, label [[NEXT]] 222; CHECK-NEXT: ] 223; CHECK: out: 224; CHECK-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ -1, [[NEGATIVE]] ] 225; CHECK-NEXT: ret i32 [[P]] 226; CHECK: next: 227; CHECK-NEXT: ret i32 0 228; 229entry: 230 %cmp = icmp slt i32 %s, 0 231 br i1 %cmp, label %negative, label %out 232 233negative: 234 switch i32 %s, label %out [ 235 i32 0, label %out 236 i32 1, label %out 237 i32 -1, label %next 238 i32 -2, label %next 239 i32 2, label %out 240 i32 3, label %out 241 ] 242 243out: 244 %p = phi i32 [ 1, %entry ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ], [ -1, %negative ] 245 ret i32 %p 246 247next: 248 %q = phi i32 [ 0, %negative ], [ 0, %negative ] 249 ret i32 %q 250} 251 252define i32 @switch2(i32 %s) { 253; CHECK-LABEL: define range(i32 -1, 2) i32 @switch2 254; CHECK-SAME: (i32 [[S:%.*]]) { 255; CHECK-NEXT: entry: 256; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S]], 0 257; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] 258; CHECK: positive: 259; CHECK-NEXT: br label [[OUT]] 260; CHECK: out: 261; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] 262; CHECK-NEXT: ret i32 [[P]] 263; CHECK: next: 264; CHECK-NEXT: ret i32 0 265; 266entry: 267 %cmp = icmp sgt i32 %s, 0 268 br i1 %cmp, label %positive, label %out 269 270positive: 271 switch i32 %s, label %out [ 272 i32 0, label %out 273 i32 -1, label %next 274 i32 -2, label %next 275 ] 276 277out: 278 %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] 279 ret i32 %p 280 281next: 282 %q = phi i32 [ 0, %positive ], [ 0, %positive ] 283 ret i32 %q 284} 285 286define i32 @switch3(i32 %s) { 287; CHECK-LABEL: define range(i32 -1, 2) i32 @switch3 288; CHECK-SAME: (i32 [[S:%.*]]) { 289; CHECK-NEXT: entry: 290; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[S]], 0 291; CHECK-NEXT: br i1 [[CMP]], label [[POSITIVE:%.*]], label [[OUT:%.*]] 292; CHECK: positive: 293; CHECK-NEXT: br label [[OUT]] 294; CHECK: out: 295; CHECK-NEXT: [[P:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 1, [[POSITIVE]] ] 296; CHECK-NEXT: ret i32 [[P]] 297; CHECK: next: 298; CHECK-NEXT: ret i32 0 299; 300entry: 301 %cmp = icmp sgt i32 %s, 0 302 br i1 %cmp, label %positive, label %out 303 304positive: 305 switch i32 %s, label %out [ 306 i32 -1, label %out 307 i32 -2, label %next 308 i32 -3, label %next 309 ] 310 311out: 312 %p = phi i32 [ -1, %entry ], [ 1, %positive ], [ 1, %positive ] 313 ret i32 %p 314 315next: 316 %q = phi i32 [ 0, %positive ], [ 0, %positive ] 317 ret i32 %q 318} 319 320define void @switch4(i32 %s) { 321; CHECK-LABEL: define void @switch4 322; CHECK-SAME: (i32 [[S:%.*]]) { 323; CHECK-NEXT: entry: 324; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[S]], 0 325; CHECK-NEXT: br i1 [[CMP]], label [[ZERO:%.*]], label [[OUT:%.*]] 326; CHECK: zero: 327; CHECK-NEXT: br label [[NEXT:%.*]] 328; CHECK: out: 329; CHECK-NEXT: ret void 330; CHECK: next: 331; CHECK-NEXT: ret void 332; 333entry: 334 %cmp = icmp eq i32 %s, 0 335 br i1 %cmp, label %zero, label %out 336 337zero: 338 switch i32 %s, label %out [ 339 i32 0, label %next 340 i32 1, label %out 341 i32 -1, label %out 342 ] 343 344out: 345 ret void 346 347next: 348 ret void 349} 350 351define void @switch_nonzero_zext(i8 %s) { 352; CHECK-LABEL: define void @switch_nonzero_zext 353; CHECK-SAME: (i8 [[S:%.*]]) { 354; CHECK-NEXT: entry: 355; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[S]], 0 356; CHECK-NEXT: br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]] 357; CHECK: switch: 358; CHECK-NEXT: [[S_EXT:%.*]] = zext i8 [[S]] to i32 359; CHECK-NEXT: br label [[EXIT]] 360; CHECK: exit: 361; CHECK-NEXT: ret void 362; CHECK: unreachable: 363; CHECK-NEXT: ret void 364; 365entry: 366 %cmp = icmp ne i8 %s, 0 367 br i1 %cmp, label %switch, label %exit 368 369switch: 370 %s.ext = zext i8 %s to i32 371 switch i32 %s.ext, label %exit [ 372 i32 0, label %unreachable 373 i32 1, label %exit 374 i32 -1, label %exit 375 ] 376 377exit: 378 ret void 379 380unreachable: 381 ret void 382} 383 384define void @switch_assume_nonzero(i32 %s) { 385; CHECK-LABEL: define void @switch_assume_nonzero 386; CHECK-SAME: (i32 [[S:%.*]]) { 387; CHECK-NEXT: entry: 388; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[S]], 0 389; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) 390; CHECK-NEXT: br label [[EXIT:%.*]] 391; CHECK: exit: 392; CHECK-NEXT: ret void 393; CHECK: unreachable: 394; CHECK-NEXT: ret void 395; 396entry: 397 %cmp = icmp ne i32 %s, 0 398 call void @llvm.assume(i1 %cmp) 399 switch i32 %s, label %exit [ 400 i32 0, label %unreachable 401 i32 1, label %exit 402 i32 -1, label %exit 403 ] 404 405exit: 406 ret void 407 408unreachable: 409 ret void 410} 411 412define void @switch_nonzero_phi(i1 %cond) { 413; CHECK-LABEL: define void @switch_nonzero_phi 414; CHECK-SAME: (i1 [[COND:%.*]]) { 415; CHECK-NEXT: entry: 416; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[ELSE:%.*]] 417; CHECK: if: 418; CHECK-NEXT: br label [[SWITCH:%.*]] 419; CHECK: else: 420; CHECK-NEXT: br label [[SWITCH]] 421; CHECK: switch: 422; CHECK-NEXT: [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ] 423; CHECK-NEXT: br label [[EXIT:%.*]] 424; CHECK: exit: 425; CHECK-NEXT: ret void 426; CHECK: unreachable: 427; CHECK-NEXT: ret void 428; 429entry: 430 br i1 %cond, label %if, label %else 431 432if: 433 br label %switch 434 435else: 436 br label %switch 437 438switch: 439 %s = phi i32 [ 1, %if ], [ -1, %else ] 440 switch i32 %s, label %exit [ 441 i32 0, label %unreachable 442 i32 1, label %exit 443 i32 -1, label %exit 444 ] 445 446exit: 447 ret void 448 449unreachable: 450 ret void 451} 452 453define i32 @switch_range(i32 %cond) { 454; CHECK-LABEL: define range(i32 1, 3) i32 @switch_range 455; CHECK-SAME: (i32 [[COND:%.*]]) { 456; CHECK-NEXT: entry: 457; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND]], 3 458; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1 459; CHECK-NEXT: switch i32 [[S1]], label [[DEFAULT_UNREACHABLE:%.*]] [ 460; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] 461; CHECK-NEXT: i32 2, label [[EXIT2:%.*]] 462; CHECK-NEXT: i32 3, label [[EXIT1]] 463; CHECK-NEXT: ] 464; CHECK: exit1: 465; CHECK-NEXT: ret i32 1 466; CHECK: exit2: 467; CHECK-NEXT: ret i32 2 468; CHECK: default.unreachable: 469; CHECK-NEXT: unreachable 470; CHECK: unreachable: 471; CHECK-NEXT: ret i32 0 472; 473entry: 474 %s = urem i32 %cond, 3 475 %s1 = add i32 %s, 1 476 switch i32 %s1, label %unreachable [ 477 i32 1, label %exit1 478 i32 2, label %exit2 479 i32 3, label %exit1 480 ] 481 482exit1: 483 ret i32 1 484exit2: 485 ret i32 2 486unreachable: 487 ret i32 0 488} 489 490; If the cases do not cover the entire range of the 491; switch condition, we should not change the default. 492 493define i32 @switch_range_not_full(i32 %cond) { 494; CHECK-LABEL: define range(i32 0, 3) i32 @switch_range_not_full 495; CHECK-SAME: (i32 [[COND:%.*]]) { 496; CHECK-NEXT: entry: 497; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND]], 3 498; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1 499; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [ 500; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] 501; CHECK-NEXT: i32 3, label [[EXIT2:%.*]] 502; CHECK-NEXT: ] 503; CHECK: exit1: 504; CHECK-NEXT: ret i32 1 505; CHECK: exit2: 506; CHECK-NEXT: ret i32 2 507; CHECK: unreachable: 508; CHECK-NEXT: ret i32 0 509; 510entry: 511 %s = urem i32 %cond, 3 512 %s1 = add i32 %s, 1 513 switch i32 %s1, label %unreachable [ 514 i32 1, label %exit1 515 i32 3, label %exit2 516 ] 517 518exit1: 519 ret i32 1 520exit2: 521 ret i32 2 522unreachable: 523 ret i32 0 524} 525 526; PR51531 527 528define i8 @switch_defaultdest_multipleuse(i8 %t0) { 529; CHECK-LABEL: define i8 @switch_defaultdest_multipleuse 530; CHECK-SAME: (i8 [[T0:%.*]]) { 531; CHECK-NEXT: entry: 532; CHECK-NEXT: [[O:%.*]] = or i8 [[T0]], 1 533; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]] 534; CHECK-NEXT: br label [[EXIT:%.*]] 535; CHECK: default.unreachable: 536; CHECK-NEXT: unreachable 537; CHECK: exit: 538; CHECK-NEXT: ret i8 0 539; 540entry: 541 %o = or i8 %t0, 1 542 %r = srem i8 1, %o 543 switch i8 %r, label %exit [ 544 i8 0, label %exit 545 i8 1, label %exit 546 ] 547 548exit: 549 ret i8 0 550} 551 552define i1 @arg_attribute(ptr nonnull %a) { 553; CHECK-LABEL: define i1 @arg_attribute 554; CHECK-SAME: (ptr nonnull [[A:%.*]]) { 555; CHECK-NEXT: ret i1 false 556; 557 %cmp = icmp eq ptr %a, null 558 ret i1 %cmp 559} 560 561declare nonnull ptr @return_nonnull() 562define i1 @call_attribute() { 563; CHECK-LABEL: define i1 @call_attribute() { 564; CHECK-NEXT: [[A:%.*]] = call ptr @return_nonnull() 565; CHECK-NEXT: ret i1 false 566; 567 %a = call ptr @return_nonnull() 568 %cmp = icmp eq ptr %a, null 569 ret i1 %cmp 570} 571 572define i1 @umin(i32 %a, i32 %b) { 573; CHECK-LABEL: define i1 @umin 574; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 575; CHECK-NEXT: entry: 576; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 5 577; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 578; CHECK: a_guard: 579; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B]], 20 580; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 581; CHECK: b_guard: 582; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign ult i32 [[A]], [[B]] 583; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 584; CHECK-NEXT: ret i1 false 585; CHECK: out: 586; CHECK-NEXT: ret i1 false 587; 588entry: 589 %cmp = icmp ult i32 %a, 5 590 br i1 %cmp, label %a_guard, label %out 591 592a_guard: 593 %cmp2 = icmp ult i32 %b, 20 594 br i1 %cmp2, label %b_guard, label %out 595 596b_guard: 597 %sel_cmp = icmp ult i32 %a, %b 598 %min = select i1 %sel_cmp, i32 %a, i32 %b 599 %res = icmp eq i32 %min, 7 600 ret i1 %res 601out: 602 ret i1 false 603} 604 605define i1 @smin(i32 %a, i32 %b) { 606; CHECK-LABEL: define i1 @smin 607; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 608; CHECK-NEXT: entry: 609; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 5 610; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 611; CHECK: a_guard: 612; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[B]], 20 613; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 614; CHECK: b_guard: 615; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign ule i32 [[A]], [[B]] 616; CHECK-NEXT: [[MIN:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 617; CHECK-NEXT: ret i1 false 618; CHECK: out: 619; CHECK-NEXT: ret i1 false 620; 621entry: 622 %cmp = icmp ult i32 %a, 5 623 br i1 %cmp, label %a_guard, label %out 624 625a_guard: 626 %cmp2 = icmp ult i32 %b, 20 627 br i1 %cmp2, label %b_guard, label %out 628 629b_guard: 630 %sel_cmp = icmp sle i32 %a, %b 631 %min = select i1 %sel_cmp, i32 %a, i32 %b 632 %res = icmp eq i32 %min, 7 633 ret i1 %res 634out: 635 ret i1 false 636} 637 638define i1 @smax(i32 %a, i32 %b) { 639; CHECK-LABEL: define i1 @smax 640; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 641; CHECK-NEXT: entry: 642; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5 643; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 644; CHECK: a_guard: 645; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B]], 20 646; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 647; CHECK: b_guard: 648; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign uge i32 [[A]], [[B]] 649; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 650; CHECK-NEXT: ret i1 false 651; CHECK: out: 652; CHECK-NEXT: ret i1 false 653; 654entry: 655 %cmp = icmp sgt i32 %a, 5 656 br i1 %cmp, label %a_guard, label %out 657 658a_guard: 659 %cmp2 = icmp sgt i32 %b, 20 660 br i1 %cmp2, label %b_guard, label %out 661 662b_guard: 663 %sel_cmp = icmp sge i32 %a, %b 664 %max = select i1 %sel_cmp, i32 %a, i32 %b 665 %res = icmp eq i32 %max, 7 666 ret i1 %res 667out: 668 ret i1 false 669} 670 671define i1 @umax(i32 %a, i32 %b) { 672; CHECK-LABEL: define i1 @umax 673; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 674; CHECK-NEXT: entry: 675; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5 676; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 677; CHECK: a_guard: 678; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[B]], 20 679; CHECK-NEXT: br i1 [[CMP2]], label [[B_GUARD:%.*]], label [[OUT]] 680; CHECK: b_guard: 681; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign uge i32 [[A]], [[B]] 682; CHECK-NEXT: [[MAX:%.*]] = select i1 [[SEL_CMP]], i32 [[A]], i32 [[B]] 683; CHECK-NEXT: ret i1 false 684; CHECK: out: 685; CHECK-NEXT: ret i1 false 686; 687entry: 688 %cmp = icmp sgt i32 %a, 5 689 br i1 %cmp, label %a_guard, label %out 690 691a_guard: 692 %cmp2 = icmp sgt i32 %b, 20 693 br i1 %cmp2, label %b_guard, label %out 694 695b_guard: 696 %sel_cmp = icmp uge i32 %a, %b 697 %max = select i1 %sel_cmp, i32 %a, i32 %b 698 %res = icmp eq i32 %max, 7 699 ret i1 %res 700out: 701 ret i1 false 702} 703 704define i1 @umin_lhs_overdefined_rhs_const(i32 %a) { 705; CHECK-LABEL: define i1 @umin_lhs_overdefined_rhs_const 706; CHECK-SAME: (i32 [[A:%.*]]) { 707; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], 42 708; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 42 709; CHECK-NEXT: ret i1 true 710; 711 %cmp = icmp ult i32 %a, 42 712 %sel = select i1 %cmp, i32 %a, i32 42 713 %cmp2 = icmp ule i32 %sel, 42 714 ret i1 %cmp2 715} 716 717define i1 @umin_rhs_overdefined_lhs_const(i32 %a) { 718; CHECK-LABEL: define i1 @umin_rhs_overdefined_lhs_const 719; CHECK-SAME: (i32 [[A:%.*]]) { 720; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[A]], 42 721; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 42, i32 [[A]] 722; CHECK-NEXT: ret i1 true 723; 724 %cmp = icmp uge i32 %a, 42 725 %sel = select i1 %cmp, i32 42, i32 %a 726 %cmp2 = icmp ule i32 %sel, 42 727 ret i1 %cmp2 728} 729 730define i1 @umin_lhs_overdefined_rhs_range(i32 %a, i32 %b) { 731; CHECK-LABEL: define i1 @umin_lhs_overdefined_rhs_range 732; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 733; CHECK-NEXT: [[ASSUME:%.*]] = icmp ult i32 [[B]], 42 734; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) 735; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A]], [[B]] 736; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]] 737; CHECK-NEXT: ret i1 true 738; 739 %assume = icmp ult i32 %b, 42 740 call void @llvm.assume(i1 %assume) 741 %cmp = icmp ult i32 %a, %b 742 %sel = select i1 %cmp, i32 %a, i32 %b 743 %cmp2 = icmp ult i32 %sel, 42 744 ret i1 %cmp2 745} 746 747define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) { 748; CHECK-LABEL: define i1 @umin_rhs_overdefined_lhs_range 749; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 750; CHECK-NEXT: [[ASSUME:%.*]] = icmp ult i32 [[B]], 42 751; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) 752; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[A]], [[B]] 753; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]] 754; CHECK-NEXT: ret i1 true 755; 756 %assume = icmp ult i32 %b, 42 757 call void @llvm.assume(i1 %assume) 758 %cmp = icmp uge i32 %a, %b 759 %sel = select i1 %cmp, i32 %b, i32 %a 760 %cmp2 = icmp ult i32 %sel, 42 761 ret i1 %cmp2 762} 763 764define i1 @clamp_low1(i32 noundef %a) { 765; CHECK-LABEL: define i1 @clamp_low1 766; CHECK-SAME: (i32 noundef [[A:%.*]]) { 767; CHECK-NEXT: entry: 768; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 5 769; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 770; CHECK: a_guard: 771; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 772; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 773; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 774; CHECK-NEXT: ret i1 false 775; CHECK: out: 776; CHECK-NEXT: ret i1 false 777; 778entry: 779 %cmp = icmp sge i32 %a, 5 780 br i1 %cmp, label %a_guard, label %out 781 782a_guard: 783 %sel_cmp = icmp eq i32 %a, 5 784 %add = add i32 %a, -1 785 %sel = select i1 %sel_cmp, i32 5, i32 %add 786 %res = icmp eq i32 %sel, 4 787 ret i1 %res 788out: 789 ret i1 false 790} 791 792define i1 @clamp_low2(i32 noundef %a) { 793; CHECK-LABEL: define i1 @clamp_low2 794; CHECK-SAME: (i32 noundef [[A:%.*]]) { 795; CHECK-NEXT: entry: 796; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 5 797; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 798; CHECK: a_guard: 799; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 800; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 801; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 802; CHECK-NEXT: ret i1 false 803; CHECK: out: 804; CHECK-NEXT: ret i1 false 805; 806entry: 807 %cmp = icmp sge i32 %a, 5 808 br i1 %cmp, label %a_guard, label %out 809 810a_guard: 811 %sel_cmp = icmp ne i32 %a, 5 812 %add = add i32 %a, -1 813 %sel = select i1 %sel_cmp, i32 %add, i32 5 814 %res = icmp eq i32 %sel, 4 815 ret i1 %res 816out: 817 ret i1 false 818} 819 820define i1 @clamp_low3(i32 noundef %a) { 821; CHECK-LABEL: define i1 @clamp_low3 822; CHECK-SAME: (i32 noundef [[A:%.*]]) { 823; CHECK-NEXT: entry: 824; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 5 825; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 826; CHECK: a_guard: 827; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign ugt i32 [[A]], 5 828; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 829; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 830; CHECK-NEXT: ret i1 false 831; CHECK: out: 832; CHECK-NEXT: ret i1 false 833; 834entry: 835 %cmp = icmp sge i32 %a, 5 836 br i1 %cmp, label %a_guard, label %out 837 838a_guard: 839 %sel_cmp = icmp sgt i32 %a, 5 840 %add = add i32 %a, -1 841 %sel = select i1 %sel_cmp, i32 %add, i32 5 842 %res = icmp eq i32 %sel, 4 843 ret i1 %res 844out: 845 ret i1 false 846} 847 848define i1 @clamp_low4(i32 noundef %a) { 849; CHECK-LABEL: define i1 @clamp_low4 850; CHECK-SAME: (i32 noundef [[A:%.*]]) { 851; CHECK-NEXT: entry: 852; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 5 853; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 854; CHECK: a_guard: 855; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp samesign ule i32 [[A]], 5 856; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1 857; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 858; CHECK-NEXT: ret i1 false 859; CHECK: out: 860; CHECK-NEXT: ret i1 false 861; 862entry: 863 %cmp = icmp sge i32 %a, 5 864 br i1 %cmp, label %a_guard, label %out 865 866a_guard: 867 %sel_cmp = icmp sle i32 %a, 5 868 %add = add i32 %a, -1 869 %sel = select i1 %sel_cmp, i32 5, i32 %add 870 %res = icmp eq i32 %sel, 4 871 ret i1 %res 872out: 873 ret i1 false 874} 875 876define i1 @clamp_high1(i32 noundef %a) { 877; CHECK-LABEL: define i1 @clamp_high1 878; CHECK-SAME: (i32 noundef [[A:%.*]]) { 879; CHECK-NEXT: entry: 880; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 881; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 882; CHECK: a_guard: 883; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 884; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 885; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 886; CHECK-NEXT: ret i1 false 887; CHECK: out: 888; CHECK-NEXT: ret i1 false 889; 890entry: 891 %cmp = icmp sle i32 %a, 5 892 br i1 %cmp, label %a_guard, label %out 893 894a_guard: 895 %sel_cmp = icmp eq i32 %a, 5 896 %add = add i32 %a, 1 897 %sel = select i1 %sel_cmp, i32 5, i32 %add 898 %res = icmp eq i32 %sel, 6 899 ret i1 %res 900out: 901 ret i1 false 902} 903 904define i1 @clamp_high1_or(i32 noundef %a) { 905; CHECK-LABEL: define i1 @clamp_high1_or 906; CHECK-SAME: (i32 noundef [[A:%.*]]) { 907; CHECK-NEXT: entry: 908; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 909; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 910; CHECK: a_guard: 911; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 912; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[A]], 1 913; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 914; CHECK-NEXT: ret i1 false 915; CHECK: out: 916; CHECK-NEXT: ret i1 false 917; 918entry: 919 %cmp = icmp sle i32 %a, 5 920 br i1 %cmp, label %a_guard, label %out 921 922a_guard: 923 %sel_cmp = icmp eq i32 %a, 5 924 %add = or disjoint i32 %a, 1 925 %sel = select i1 %sel_cmp, i32 5, i32 %add 926 %res = icmp eq i32 %sel, 6 927 ret i1 %res 928out: 929 ret i1 false 930} 931 932define i1 @clamp_high2(i32 noundef %a) { 933; CHECK-LABEL: define i1 @clamp_high2 934; CHECK-SAME: (i32 noundef [[A:%.*]]) { 935; CHECK-NEXT: entry: 936; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 937; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 938; CHECK: a_guard: 939; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 940; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 941; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 942; CHECK-NEXT: ret i1 false 943; CHECK: out: 944; CHECK-NEXT: ret i1 false 945; 946entry: 947 %cmp = icmp sle i32 %a, 5 948 br i1 %cmp, label %a_guard, label %out 949 950a_guard: 951 %sel_cmp = icmp ne i32 %a, 5 952 %add = add i32 %a, 1 953 %sel = select i1 %sel_cmp, i32 %add, i32 5 954 %res = icmp eq i32 %sel, 6 955 ret i1 %res 956out: 957 ret i1 false 958} 959 960 961define i1 @clamp_high2_or_disjoint(i32 noundef %a) { 962; CHECK-LABEL: define i1 @clamp_high2_or_disjoint 963; CHECK-SAME: (i32 noundef [[A:%.*]]) { 964; CHECK-NEXT: entry: 965; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 966; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 967; CHECK: a_guard: 968; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 969; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[A]], 1 970; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 971; CHECK-NEXT: ret i1 false 972; CHECK: out: 973; CHECK-NEXT: ret i1 false 974; 975entry: 976 %cmp = icmp sle i32 %a, 5 977 br i1 %cmp, label %a_guard, label %out 978 979a_guard: 980 %sel_cmp = icmp ne i32 %a, 5 981 %add = or disjoint i32 %a, 1 982 %sel = select i1 %sel_cmp, i32 %add, i32 5 983 %res = icmp eq i32 %sel, 6 984 ret i1 %res 985out: 986 ret i1 false 987} 988 989 990define i1 @clamp_high3(i32 noundef %a) { 991; CHECK-LABEL: define i1 @clamp_high3 992; CHECK-SAME: (i32 noundef [[A:%.*]]) { 993; CHECK-NEXT: entry: 994; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 995; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 996; CHECK: a_guard: 997; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp slt i32 [[A]], 5 998; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 999; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 1000; CHECK-NEXT: ret i1 false 1001; CHECK: out: 1002; CHECK-NEXT: ret i1 false 1003; 1004entry: 1005 %cmp = icmp sle i32 %a, 5 1006 br i1 %cmp, label %a_guard, label %out 1007 1008a_guard: 1009 %sel_cmp = icmp slt i32 %a, 5 1010 %add = add i32 %a, 1 1011 %sel = select i1 %sel_cmp, i32 %add, i32 5 1012 %res = icmp eq i32 %sel, 6 1013 ret i1 %res 1014out: 1015 ret i1 false 1016} 1017 1018define i1 @clamp_high4(i32 noundef %a) { 1019; CHECK-LABEL: define i1 @clamp_high4 1020; CHECK-SAME: (i32 noundef [[A:%.*]]) { 1021; CHECK-NEXT: entry: 1022; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 1023; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 1024; CHECK: a_guard: 1025; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], 5 1026; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1 1027; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] 1028; CHECK-NEXT: ret i1 false 1029; CHECK: out: 1030; CHECK-NEXT: ret i1 false 1031; 1032entry: 1033 %cmp = icmp sle i32 %a, 5 1034 br i1 %cmp, label %a_guard, label %out 1035 1036a_guard: 1037 %sel_cmp = icmp sge i32 %a, 5 1038 %add = add i32 %a, 1 1039 %sel = select i1 %sel_cmp, i32 5, i32 %add 1040 %res = icmp eq i32 %sel, 6 1041 ret i1 %res 1042out: 1043 ret i1 false 1044} 1045 1046; Just showing arbitrary constants work, not really a clamp 1047define i1 @not_clamp_high(i32 noundef %a) { 1048; CHECK-LABEL: define i1 @not_clamp_high 1049; CHECK-SAME: (i32 noundef [[A:%.*]]) { 1050; CHECK-NEXT: entry: 1051; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A]], 5 1052; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] 1053; CHECK: a_guard: 1054; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 1055; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 100 1056; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 1057; CHECK-NEXT: ret i1 false 1058; CHECK: out: 1059; CHECK-NEXT: ret i1 false 1060; 1061entry: 1062 %cmp = icmp sle i32 %a, 5 1063 br i1 %cmp, label %a_guard, label %out 1064 1065a_guard: 1066 %sel_cmp = icmp ne i32 %a, 5 1067 %add = add i32 %a, 100 1068 %sel = select i1 %sel_cmp, i32 %add, i32 5 1069 %res = icmp eq i32 %sel, 105 1070 ret i1 %res 1071out: 1072 ret i1 false 1073} 1074 1075define void @abs1(i32 %a, ptr %p) { 1076; CHECK-LABEL: define void @abs1 1077; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1078; CHECK-NEXT: entry: 1079; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 10 1080; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1081; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1082; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1083; CHECK: guard: 1084; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1085; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 1086; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]] 1087; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1088; CHECK-NEXT: [[C2:%.*]] = icmp samesign ult i32 [[ABS]], 19 1089; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1090; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1091; CHECK-NEXT: [[C4:%.*]] = icmp samesign uge i32 [[ABS]], 1 1092; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1093; CHECK-NEXT: br label [[EXIT]] 1094; CHECK: exit: 1095; CHECK-NEXT: ret void 1096; 1097entry: 1098 %cmp1 = icmp slt i32 %a, 10 1099 %cmp2 = icmp sgt i32 %a, -20 1100 %and = and i1 %cmp1, %cmp2 1101 br i1 %and, label %guard, label %exit 1102 1103guard: 1104 %sub = sub i32 0, %a 1105 %cmp = icmp slt i32 %a, 0 1106 %abs = select i1 %cmp, i32 %sub, i32 %a 1107 %c1 = icmp slt i32 %abs, 20 1108 store i1 %c1, ptr %p 1109 %c2 = icmp slt i32 %abs, 19 1110 store i1 %c2, ptr %p 1111 %c3 = icmp sge i32 %abs, 0 1112 store i1 %c3, ptr %p 1113 %c4 = icmp sge i32 %abs, 1 1114 store i1 %c4, ptr %p 1115 br label %exit 1116 1117exit: 1118 ret void 1119} 1120 1121define void @abs2(i32 %a, ptr %p) { 1122; CHECK-LABEL: define void @abs2 1123; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1124; CHECK-NEXT: entry: 1125; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 10 1126; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1127; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1128; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1129; CHECK: guard: 1130; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1131; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A]], 0 1132; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]] 1133; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1134; CHECK-NEXT: [[C2:%.*]] = icmp samesign ult i32 [[ABS]], 19 1135; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1136; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1137; CHECK-NEXT: [[C4:%.*]] = icmp samesign uge i32 [[ABS]], 1 1138; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1139; CHECK-NEXT: br label [[EXIT]] 1140; CHECK: exit: 1141; CHECK-NEXT: ret void 1142; 1143entry: 1144 %cmp1 = icmp slt i32 %a, 10 1145 %cmp2 = icmp sgt i32 %a, -20 1146 %and = and i1 %cmp1, %cmp2 1147 br i1 %and, label %guard, label %exit 1148 1149guard: 1150 %sub = sub i32 0, %a 1151 %cmp = icmp sge i32 %a, 0 1152 %abs = select i1 %cmp, i32 %a, i32 %sub 1153 %c1 = icmp slt i32 %abs, 20 1154 store i1 %c1, ptr %p 1155 %c2 = icmp slt i32 %abs, 19 1156 store i1 %c2, ptr %p 1157 %c3 = icmp sge i32 %abs, 0 1158 store i1 %c3, ptr %p 1159 %c4 = icmp sge i32 %abs, 1 1160 store i1 %c4, ptr %p 1161 br label %exit 1162 1163exit: 1164 ret void 1165} 1166 1167define void @nabs1(i32 %a, ptr %p) { 1168; CHECK-LABEL: define void @nabs1 1169; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1170; CHECK-NEXT: entry: 1171; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 10 1172; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1173; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1174; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1175; CHECK: guard: 1176; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1177; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 0 1178; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[A]] 1179; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1180; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[NABS]], -19 1181; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1182; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1183; CHECK-NEXT: [[C4:%.*]] = icmp sle i32 [[NABS]], -1 1184; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1185; CHECK-NEXT: br label [[EXIT]] 1186; CHECK: exit: 1187; CHECK-NEXT: ret void 1188; 1189entry: 1190 %cmp1 = icmp slt i32 %a, 10 1191 %cmp2 = icmp sgt i32 %a, -20 1192 %and = and i1 %cmp1, %cmp2 1193 br i1 %and, label %guard, label %exit 1194 1195guard: 1196 %sub = sub i32 0, %a 1197 %cmp = icmp sgt i32 %a, 0 1198 %nabs = select i1 %cmp, i32 %sub, i32 %a 1199 %c1 = icmp sgt i32 %nabs, -20 1200 store i1 %c1, ptr %p 1201 %c2 = icmp sgt i32 %nabs, -19 1202 store i1 %c2, ptr %p 1203 %c3 = icmp sle i32 %nabs, 0 1204 store i1 %c3, ptr %p 1205 %c4 = icmp sle i32 %nabs, -1 1206 store i1 %c4, ptr %p 1207 br label %exit 1208 1209exit: 1210 ret void 1211} 1212 1213define void @nabs2(i32 %a, ptr %p) { 1214; CHECK-LABEL: define void @nabs2 1215; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1216; CHECK-NEXT: entry: 1217; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 10 1218; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], -20 1219; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1220; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1221; CHECK: guard: 1222; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[A]] 1223; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 1224; CHECK-NEXT: [[NABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[SUB]] 1225; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1226; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[NABS]], -19 1227; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1228; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1229; CHECK-NEXT: [[C4:%.*]] = icmp sle i32 [[NABS]], -1 1230; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1231; CHECK-NEXT: br label [[EXIT]] 1232; CHECK: exit: 1233; CHECK-NEXT: ret void 1234; 1235entry: 1236 %cmp1 = icmp slt i32 %a, 10 1237 %cmp2 = icmp sgt i32 %a, -20 1238 %and = and i1 %cmp1, %cmp2 1239 br i1 %and, label %guard, label %exit 1240 1241guard: 1242 %sub = sub i32 0, %a 1243 %cmp = icmp slt i32 %a, 0 1244 %nabs = select i1 %cmp, i32 %a, i32 %sub 1245 %c1 = icmp sgt i32 %nabs, -20 1246 store i1 %c1, ptr %p 1247 %c2 = icmp sgt i32 %nabs, -19 1248 store i1 %c2, ptr %p 1249 %c3 = icmp sle i32 %nabs, 0 1250 store i1 %c3, ptr %p 1251 %c4 = icmp sle i32 %nabs, -1 1252 store i1 %c4, ptr %p 1253 br label %exit 1254 1255exit: 1256 ret void 1257} 1258 1259define i1 @zext_unknown(i8 %a) { 1260; CHECK-LABEL: define i1 @zext_unknown 1261; CHECK-SAME: (i8 [[A:%.*]]) { 1262; CHECK-NEXT: entry: 1263; CHECK-NEXT: [[A32:%.*]] = zext i8 [[A]] to i32 1264; CHECK-NEXT: ret i1 true 1265; 1266entry: 1267 %a32 = zext i8 %a to i32 1268 %cmp = icmp sle i32 %a32, 256 1269 ret i1 %cmp 1270} 1271 1272define i1 @trunc_unknown(i32 %a) { 1273; CHECK-LABEL: define i1 @trunc_unknown 1274; CHECK-SAME: (i32 [[A:%.*]]) { 1275; CHECK-NEXT: entry: 1276; CHECK-NEXT: [[A8:%.*]] = trunc i32 [[A]] to i8 1277; CHECK-NEXT: [[A32:%.*]] = sext i8 [[A8]] to i32 1278; CHECK-NEXT: ret i1 true 1279; 1280entry: 1281 %a8 = trunc i32 %a to i8 1282 %a32 = sext i8 %a8 to i32 1283 %cmp = icmp sle i32 %a32, 128 1284 ret i1 %cmp 1285} 1286 1287define void @trunc_icmp_ule(i32 %x, ptr %p) { 1288; CHECK-LABEL: define void @trunc_icmp_ule 1289; CHECK-SAME: (i32 [[X:%.*]], ptr [[P:%.*]]) { 1290; CHECK-NEXT: [[T:%.*]] = trunc i32 [[X]] to i8 1291; CHECK-NEXT: [[C:%.*]] = icmp uge i8 [[T]], 5 1292; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1293; CHECK: true: 1294; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1295; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 5 1296; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1297; CHECK-NEXT: [[C3:%.*]] = icmp ule i32 [[X]], 5 1298; CHECK-NEXT: store i1 [[C3]], ptr [[P]], align 1 1299; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1300; CHECK-NEXT: ret void 1301; CHECK: false: 1302; CHECK-NEXT: [[C1_2:%.*]] = icmp uge i32 [[X]], 5 1303; CHECK-NEXT: store i1 [[C1_2]], ptr [[P]], align 1 1304; CHECK-NEXT: [[C2_2:%.*]] = icmp ugt i32 [[X]], 5 1305; CHECK-NEXT: store i1 [[C2_2]], ptr [[P]], align 1 1306; CHECK-NEXT: [[C3_2:%.*]] = icmp ule i32 [[X]], 5 1307; CHECK-NEXT: store i1 [[C3_2]], ptr [[P]], align 1 1308; CHECK-NEXT: [[C4_2:%.*]] = icmp ult i32 [[X]], 5 1309; CHECK-NEXT: store i1 [[C4_2]], ptr [[P]], align 1 1310; CHECK-NEXT: ret void 1311; 1312 %t = trunc i32 %x to i8 1313 %c = icmp uge i8 %t, 5 1314 br i1 %c, label %true, label %false 1315 1316true: 1317 %c1 = icmp uge i32 %x, 5 1318 store i1 %c1, ptr %p 1319 %c2 = icmp ugt i32 %x, 5 1320 store i1 %c2, ptr %p 1321 %c3 = icmp ule i32 %x, 5 1322 store i1 %c3, ptr %p 1323 %c4 = icmp ult i32 %x, 5 1324 store i1 %c4, ptr %p 1325 ret void 1326 1327false: 1328 %c1.2 = icmp uge i32 %x, 5 1329 store i1 %c1.2, ptr %p 1330 %c2.2 = icmp ugt i32 %x, 5 1331 store i1 %c2.2, ptr %p 1332 %c3.2 = icmp ule i32 %x, 5 1333 store i1 %c3.2, ptr %p 1334 %c4.2 = icmp ult i32 %x, 5 1335 store i1 %c4.2, ptr %p 1336 ret void 1337} 1338 1339define void @trunc_icmp_eq(i32 %x, ptr %p) { 1340; CHECK-LABEL: define void @trunc_icmp_eq 1341; CHECK-SAME: (i32 [[X:%.*]], ptr [[P:%.*]]) { 1342; CHECK-NEXT: [[T:%.*]] = trunc i32 [[X]] to i8 1343; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[T]], 5 1344; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 1345; CHECK: true: 1346; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1347; CHECK-NEXT: [[C2:%.*]] = icmp ugt i32 [[X]], 5 1348; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1349; CHECK-NEXT: [[C3:%.*]] = icmp ule i32 [[X]], 5 1350; CHECK-NEXT: store i1 [[C3]], ptr [[P]], align 1 1351; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1352; CHECK-NEXT: ret void 1353; CHECK: false: 1354; CHECK-NEXT: [[C1_2:%.*]] = icmp uge i32 [[X]], 5 1355; CHECK-NEXT: store i1 [[C1_2]], ptr [[P]], align 1 1356; CHECK-NEXT: [[C2_2:%.*]] = icmp ugt i32 [[X]], 5 1357; CHECK-NEXT: store i1 [[C2_2]], ptr [[P]], align 1 1358; CHECK-NEXT: [[C3_2:%.*]] = icmp ule i32 [[X]], 5 1359; CHECK-NEXT: store i1 [[C3_2]], ptr [[P]], align 1 1360; CHECK-NEXT: [[C4_2:%.*]] = icmp ult i32 [[X]], 5 1361; CHECK-NEXT: store i1 [[C4_2]], ptr [[P]], align 1 1362; CHECK-NEXT: ret void 1363; 1364 %t = trunc i32 %x to i8 1365 %c = icmp eq i8 %t, 5 1366 br i1 %c, label %true, label %false 1367 1368true: 1369 %c1 = icmp uge i32 %x, 5 1370 store i1 %c1, ptr %p 1371 %c2 = icmp ugt i32 %x, 5 1372 store i1 %c2, ptr %p 1373 %c3 = icmp ule i32 %x, 5 1374 store i1 %c3, ptr %p 1375 %c4 = icmp ult i32 %x, 5 1376 store i1 %c4, ptr %p 1377 ret void 1378 1379false: 1380 %c1.2 = icmp uge i32 %x, 5 1381 store i1 %c1.2, ptr %p 1382 %c2.2 = icmp ugt i32 %x, 5 1383 store i1 %c2.2, ptr %p 1384 %c3.2 = icmp ule i32 %x, 5 1385 store i1 %c3.2, ptr %p 1386 %c4.2 = icmp ult i32 %x, 5 1387 store i1 %c4.2, ptr %p 1388 ret void 1389} 1390 1391; TODO: missed optimization 1392; Make sure we exercise non-integer inputs to unary operators (i.e. crash check). 1393define i1 @bitcast_unknown(float %a) { 1394; CHECK-LABEL: define i1 @bitcast_unknown 1395; CHECK-SAME: (float [[A:%.*]]) { 1396; CHECK-NEXT: entry: 1397; CHECK-NEXT: [[A32:%.*]] = bitcast float [[A]] to i32 1398; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A32]], 128 1399; CHECK-NEXT: ret i1 [[CMP]] 1400; 1401entry: 1402 %a32 = bitcast float %a to i32 1403 %cmp = icmp sle i32 %a32, 128 1404 ret i1 %cmp 1405} 1406 1407define i1 @bitcast_unknown2(ptr %p) { 1408; CHECK-LABEL: define i1 @bitcast_unknown2 1409; CHECK-SAME: (ptr [[P:%.*]]) { 1410; CHECK-NEXT: entry: 1411; CHECK-NEXT: [[P64:%.*]] = ptrtoint ptr [[P]] to i64 1412; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[P64]], 128 1413; CHECK-NEXT: ret i1 [[CMP]] 1414; 1415entry: 1416 %p64 = ptrtoint ptr %p to i64 1417 %cmp = icmp sle i64 %p64, 128 1418 ret i1 %cmp 1419} 1420 1421 1422define i1 @and_unknown(i32 %a) { 1423; CHECK-LABEL: define i1 @and_unknown 1424; CHECK-SAME: (i32 [[A:%.*]]) { 1425; CHECK-NEXT: entry: 1426; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], 128 1427; CHECK-NEXT: ret i1 true 1428; 1429entry: 1430 %and = and i32 %a, 128 1431 %cmp = icmp sle i32 %and, 128 1432 ret i1 %cmp 1433} 1434 1435define i1 @lshr_unknown(i32 %a) { 1436; CHECK-LABEL: define i1 @lshr_unknown 1437; CHECK-SAME: (i32 [[A:%.*]]) { 1438; CHECK-NEXT: entry: 1439; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[A]], 30 1440; CHECK-NEXT: ret i1 true 1441; 1442entry: 1443 %and = lshr i32 %a, 30 1444 %cmp = icmp sle i32 %and, 128 1445 ret i1 %cmp 1446} 1447 1448define i1 @urem_unknown(i32 %a) { 1449; CHECK-LABEL: define i1 @urem_unknown 1450; CHECK-SAME: (i32 [[A:%.*]]) { 1451; CHECK-NEXT: entry: 1452; CHECK-NEXT: [[UREM:%.*]] = urem i32 [[A]], 30 1453; CHECK-NEXT: ret i1 true 1454; 1455entry: 1456 %urem = urem i32 %a, 30 1457 %cmp = icmp ult i32 %urem, 30 1458 ret i1 %cmp 1459} 1460 1461define i1 @srem_unknown(i32 %a, i1 %arg) { 1462; CHECK-LABEL: define i1 @srem_unknown 1463; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1464; CHECK-NEXT: entry: 1465; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[A]], 30 1466; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1467; CHECK: exit1: 1468; CHECK-NEXT: ret i1 true 1469; CHECK: exit2: 1470; CHECK-NEXT: ret i1 true 1471; 1472entry: 1473 %srem = srem i32 %a, 30 1474 %cmp1 = icmp slt i32 %srem, 30 1475 %cmp2 = icmp sgt i32 %srem, -30 1476 br i1 %arg, label %exit1, label %exit2 1477exit1: 1478 ret i1 %cmp1 1479exit2: 1480 ret i1 %cmp2 1481} 1482 1483define i1 @sdiv_unknown(i32 %a, i1 %arg) { 1484; CHECK-LABEL: define i1 @sdiv_unknown 1485; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1486; CHECK-NEXT: entry: 1487; CHECK-NEXT: [[SREM:%.*]] = sdiv i32 [[A]], 123 1488; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1489; CHECK: exit1: 1490; CHECK-NEXT: ret i1 true 1491; CHECK: exit2: 1492; CHECK-NEXT: ret i1 true 1493; 1494entry: 1495 %srem = sdiv i32 %a, 123 1496 %cmp1 = icmp slt i32 %srem, 17459217 1497 %cmp2 = icmp sgt i32 %srem, -17459217 1498 br i1 %arg, label %exit1, label %exit2 1499exit1: 1500 ret i1 %cmp1 1501exit2: 1502 ret i1 %cmp2 1503} 1504 1505define i1 @uadd_sat_unknown(i32 %a, i1 %arg) { 1506; CHECK-LABEL: define i1 @uadd_sat_unknown 1507; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1508; CHECK-NEXT: entry: 1509; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[A]], i32 100) 1510; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[VAL]], 100 1511; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1512; CHECK: exit1: 1513; CHECK-NEXT: ret i1 true 1514; CHECK: exit2: 1515; CHECK-NEXT: ret i1 [[CMP2]] 1516; 1517entry: 1518 %val = call i32 @llvm.uadd.sat.i32(i32 %a, i32 100) 1519 %cmp1 = icmp uge i32 %val, 100 1520 %cmp2 = icmp ugt i32 %val, 100 1521 br i1 %arg, label %exit1, label %exit2 1522exit1: 1523 ret i1 %cmp1 1524exit2: 1525 ret i1 %cmp2 1526} 1527 1528define i1 @usub_sat_unknown(i32 %a, i1 %arg) { 1529; CHECK-LABEL: define i1 @usub_sat_unknown 1530; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1531; CHECK-NEXT: entry: 1532; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[A]], i32 100) 1533; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[VAL]], -101 1534; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1535; CHECK: exit1: 1536; CHECK-NEXT: ret i1 true 1537; CHECK: exit2: 1538; CHECK-NEXT: ret i1 [[CMP2]] 1539; 1540entry: 1541 %val = call i32 @llvm.usub.sat.i32(i32 %a, i32 100) 1542 %cmp1 = icmp ule i32 %val, 4294967195 1543 %cmp2 = icmp ult i32 %val, 4294967195 1544 br i1 %arg, label %exit1, label %exit2 1545exit1: 1546 ret i1 %cmp1 1547exit2: 1548 ret i1 %cmp2 1549} 1550 1551define i1 @sadd_sat_unknown(i32 %a, i1 %arg) { 1552; CHECK-LABEL: define i1 @sadd_sat_unknown 1553; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1554; CHECK-NEXT: entry: 1555; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[A]], i32 100) 1556; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[VAL]], -2147483548 1557; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1558; CHECK: exit1: 1559; CHECK-NEXT: ret i1 true 1560; CHECK: exit2: 1561; CHECK-NEXT: ret i1 [[CMP2]] 1562; 1563entry: 1564 %val = call i32 @llvm.sadd.sat.i32(i32 %a, i32 100) 1565 %cmp1 = icmp sge i32 %val, -2147483548 1566 %cmp2 = icmp sgt i32 %val, -2147483548 1567 br i1 %arg, label %exit1, label %exit2 1568exit1: 1569 ret i1 %cmp1 1570exit2: 1571 ret i1 %cmp2 1572} 1573 1574define i1 @ssub_sat_unknown(i32 %a, i1 %arg) { 1575; CHECK-LABEL: define i1 @ssub_sat_unknown 1576; CHECK-SAME: (i32 [[A:%.*]], i1 [[ARG:%.*]]) { 1577; CHECK-NEXT: entry: 1578; CHECK-NEXT: [[VAL:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A]], i32 100) 1579; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[VAL]], 2147483547 1580; CHECK-NEXT: br i1 [[ARG]], label [[EXIT1:%.*]], label [[EXIT2:%.*]] 1581; CHECK: exit1: 1582; CHECK-NEXT: ret i1 true 1583; CHECK: exit2: 1584; CHECK-NEXT: ret i1 [[CMP2]] 1585; 1586entry: 1587 %val = call i32 @llvm.ssub.sat.i32(i32 %a, i32 100) 1588 %cmp1 = icmp sle i32 %val, 2147483547 1589 %cmp2 = icmp slt i32 %val, 2147483547 1590 br i1 %arg, label %exit1, label %exit2 1591exit1: 1592 ret i1 %cmp1 1593exit2: 1594 ret i1 %cmp2 1595} 1596 1597define void @select_and(i32 %a, ptr %p) { 1598; CHECK-LABEL: define void @select_and 1599; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1600; CHECK-NEXT: entry: 1601; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], -10 1602; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1603; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false 1604; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1605; CHECK: guard: 1606; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1607; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1608; CHECK-NEXT: br label [[EXIT]] 1609; CHECK: exit: 1610; CHECK-NEXT: ret void 1611; 1612entry: 1613 %cmp1 = icmp sgt i32 %a, -10 1614 %cmp2 = icmp slt i32 %a, 10 1615 %and = select i1 %cmp1, i1 %cmp2, i1 false 1616 br i1 %and, label %guard, label %exit 1617 1618guard: 1619 %c1 = icmp sgt i32 %a, 20 1620 store i1 %c1, ptr %p 1621 %c2 = icmp slt i32 %a, -20 1622 store i1 %c2, ptr %p 1623 br label %exit 1624 1625exit: 1626 ret void 1627} 1628 1629define void @select_and_wrong_const(i32 %a, ptr %p) { 1630; CHECK-LABEL: define void @select_and_wrong_const 1631; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1632; CHECK-NEXT: entry: 1633; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], -10 1634; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1635; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true 1636; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1637; CHECK: guard: 1638; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1639; CHECK-NEXT: store i1 [[C1]], ptr [[P]], align 1 1640; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1641; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1642; CHECK-NEXT: br label [[EXIT]] 1643; CHECK: exit: 1644; CHECK-NEXT: ret void 1645; 1646entry: 1647 %cmp1 = icmp sgt i32 %a, -10 1648 %cmp2 = icmp slt i32 %a, 10 1649 %and = select i1 %cmp1, i1 %cmp2, i1 true 1650 br i1 %and, label %guard, label %exit 1651 1652guard: 1653 %c1 = icmp sgt i32 %a, 20 1654 store i1 %c1, ptr %p 1655 %c2 = icmp slt i32 %a, -20 1656 store i1 %c2, ptr %p 1657 br label %exit 1658 1659exit: 1660 ret void 1661} 1662 1663define void @select_and_wrong_operand(i32 %a, ptr %p) { 1664; CHECK-LABEL: define void @select_and_wrong_operand 1665; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1666; CHECK-NEXT: entry: 1667; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], -10 1668; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 10 1669; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]] 1670; CHECK-NEXT: br i1 [[AND]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1671; CHECK: guard: 1672; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1673; CHECK-NEXT: store i1 [[C1]], ptr [[P]], align 1 1674; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1675; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1676; CHECK-NEXT: br label [[EXIT]] 1677; CHECK: exit: 1678; CHECK-NEXT: ret void 1679; 1680entry: 1681 %cmp1 = icmp sgt i32 %a, -10 1682 %cmp2 = icmp slt i32 %a, 10 1683 %and = select i1 %cmp1, i1 false, i1 %cmp2 1684 br i1 %and, label %guard, label %exit 1685 1686guard: 1687 %c1 = icmp sgt i32 %a, 20 1688 store i1 %c1, ptr %p 1689 %c2 = icmp slt i32 %a, -20 1690 store i1 %c2, ptr %p 1691 br label %exit 1692 1693exit: 1694 ret void 1695} 1696 1697define void @select_or(i32 %a, ptr %p) { 1698; CHECK-LABEL: define void @select_or 1699; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1700; CHECK-NEXT: entry: 1701; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], -10 1702; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1703; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] 1704; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1705; CHECK: guard: 1706; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1707; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1708; CHECK-NEXT: br label [[EXIT]] 1709; CHECK: exit: 1710; CHECK-NEXT: ret void 1711; 1712entry: 1713 %cmp1 = icmp slt i32 %a, -10 1714 %cmp2 = icmp sgt i32 %a, 10 1715 %or = select i1 %cmp1, i1 true, i1 %cmp2 1716 br i1 %or, label %exit, label %guard 1717 1718guard: 1719 %c1 = icmp sgt i32 %a, 20 1720 store i1 %c1, ptr %p 1721 %c2 = icmp slt i32 %a, -20 1722 store i1 %c2, ptr %p 1723 br label %exit 1724 1725exit: 1726 ret void 1727} 1728 1729define void @select_or_wrong_const(i32 %a, ptr %p) { 1730; CHECK-LABEL: define void @select_or_wrong_const 1731; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1732; CHECK-NEXT: entry: 1733; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], -10 1734; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1735; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 false, i1 [[CMP2]] 1736; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1737; CHECK: guard: 1738; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1739; CHECK-NEXT: store i1 [[C1]], ptr [[P]], align 1 1740; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1741; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1742; CHECK-NEXT: br label [[EXIT]] 1743; CHECK: exit: 1744; CHECK-NEXT: ret void 1745; 1746entry: 1747 %cmp1 = icmp slt i32 %a, -10 1748 %cmp2 = icmp sgt i32 %a, 10 1749 %or = select i1 %cmp1, i1 false, i1 %cmp2 1750 br i1 %or, label %exit, label %guard 1751 1752guard: 1753 %c1 = icmp sgt i32 %a, 20 1754 store i1 %c1, ptr %p 1755 %c2 = icmp slt i32 %a, -20 1756 store i1 %c2, ptr %p 1757 br label %exit 1758 1759exit: 1760 ret void 1761} 1762 1763define void @select_or_wrong_operand(i32 %a, ptr %p) { 1764; CHECK-LABEL: define void @select_or_wrong_operand 1765; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1766; CHECK-NEXT: entry: 1767; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], -10 1768; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[A]], 10 1769; CHECK-NEXT: [[OR:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 true 1770; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1771; CHECK: guard: 1772; CHECK-NEXT: [[C1:%.*]] = icmp sgt i32 [[A]], 20 1773; CHECK-NEXT: store i1 [[C1]], ptr [[P]], align 1 1774; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[A]], -20 1775; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1776; CHECK-NEXT: br label [[EXIT]] 1777; CHECK: exit: 1778; CHECK-NEXT: ret void 1779; 1780entry: 1781 %cmp1 = icmp slt i32 %a, -10 1782 %cmp2 = icmp sgt i32 %a, 10 1783 %or = select i1 %cmp1, i1 %cmp2, i1 true 1784 br i1 %or, label %exit, label %guard 1785 1786guard: 1787 %c1 = icmp sgt i32 %a, 20 1788 store i1 %c1, ptr %p 1789 %c2 = icmp slt i32 %a, -20 1790 store i1 %c2, ptr %p 1791 br label %exit 1792 1793exit: 1794 ret void 1795} 1796 1797define void @or_union(i32 %a, ptr %p) { 1798; CHECK-LABEL: define void @or_union 1799; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1800; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A]], 10 1801; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 12 1802; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 1803; CHECK-NEXT: br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1804; CHECK: guard: 1805; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1806; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[A]], 10 1807; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1808; CHECK-NEXT: [[C3:%.*]] = icmp eq i32 [[A]], 11 1809; CHECK-NEXT: store i1 [[C3]], ptr [[P]], align 1 1810; CHECK-NEXT: [[C4:%.*]] = icmp eq i32 [[A]], 12 1811; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1812; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1813; CHECK-NEXT: br label [[EXIT]] 1814; CHECK: exit: 1815; CHECK-NEXT: ret void 1816; 1817 %cmp1 = icmp eq i32 %a, 10 1818 %cmp2 = icmp eq i32 %a, 12 1819 %or = or i1 %cmp1, %cmp2 1820 br i1 %or, label %guard, label %exit 1821 1822guard: 1823 %c1 = icmp eq i32 %a, 9 1824 store i1 %c1, ptr %p 1825 %c2 = icmp eq i32 %a, 10 1826 store i1 %c2, ptr %p 1827 %c3 = icmp eq i32 %a, 11 1828 store i1 %c3, ptr %p 1829 %c4 = icmp eq i32 %a, 12 1830 store i1 %c4, ptr %p 1831 %c5 = icmp eq i32 %a, 13 1832 store i1 %c5, ptr %p 1833 br label %exit 1834 1835exit: 1836 ret void 1837} 1838 1839define i1 @or_union_unknown_cond(i32 %a, i1 %c) { 1840; CHECK-LABEL: define i1 @or_union_unknown_cond 1841; CHECK-SAME: (i32 [[A:%.*]], i1 [[C:%.*]]) { 1842; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A]], 10 1843; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[C]] 1844; CHECK-NEXT: br i1 [[OR]], label [[GUARD:%.*]], label [[EXIT:%.*]] 1845; CHECK: guard: 1846; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 10 1847; CHECK-NEXT: ret i1 [[CMP2]] 1848; CHECK: exit: 1849; CHECK-NEXT: ret i1 false 1850; 1851 %cmp1 = icmp eq i32 %a, 10 1852 %or = or i1 %cmp1, %c 1853 br i1 %or, label %guard, label %exit 1854 1855guard: 1856 %cmp2 = icmp eq i32 %a, 10 1857 ret i1 %cmp2 1858 1859exit: 1860 ret i1 false 1861} 1862 1863define void @and_union(i32 %a, ptr %p) { 1864; CHECK-LABEL: define void @and_union 1865; CHECK-SAME: (i32 [[A:%.*]], ptr [[P:%.*]]) { 1866; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A]], 10 1867; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[A]], 12 1868; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 1869; CHECK-NEXT: br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1870; CHECK: guard: 1871; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1872; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[A]], 10 1873; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1874; CHECK-NEXT: [[C3:%.*]] = icmp eq i32 [[A]], 11 1875; CHECK-NEXT: store i1 [[C3]], ptr [[P]], align 1 1876; CHECK-NEXT: [[C4:%.*]] = icmp eq i32 [[A]], 12 1877; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1878; CHECK-NEXT: store i1 false, ptr [[P]], align 1 1879; CHECK-NEXT: br label [[EXIT]] 1880; CHECK: exit: 1881; CHECK-NEXT: ret void 1882; 1883 %cmp1 = icmp ne i32 %a, 10 1884 %cmp2 = icmp ne i32 %a, 12 1885 %and = and i1 %cmp1, %cmp2 1886 br i1 %and, label %exit, label %guard 1887 1888guard: 1889 %c1 = icmp eq i32 %a, 9 1890 store i1 %c1, ptr %p 1891 %c2 = icmp eq i32 %a, 10 1892 store i1 %c2, ptr %p 1893 %c3 = icmp eq i32 %a, 11 1894 store i1 %c3, ptr %p 1895 %c4 = icmp eq i32 %a, 12 1896 store i1 %c4, ptr %p 1897 %c5 = icmp eq i32 %a, 13 1898 store i1 %c5, ptr %p 1899 br label %exit 1900 1901exit: 1902 ret void 1903} 1904 1905define i1 @and_union_unknown_cond(i32 %a, i1 %c) { 1906; CHECK-LABEL: define i1 @and_union_unknown_cond 1907; CHECK-SAME: (i32 [[A:%.*]], i1 [[C:%.*]]) { 1908; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A]], 10 1909; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[C]] 1910; CHECK-NEXT: br i1 [[AND]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1911; CHECK: guard: 1912; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[A]], 10 1913; CHECK-NEXT: ret i1 [[CMP2]] 1914; CHECK: exit: 1915; CHECK-NEXT: ret i1 false 1916; 1917 %cmp1 = icmp ne i32 %a, 10 1918 %and = and i1 %cmp1, %c 1919 br i1 %and, label %exit, label %guard 1920 1921guard: 1922 %cmp2 = icmp eq i32 %a, 10 1923 ret i1 %cmp2 1924 1925exit: 1926 ret i1 false 1927} 1928 1929define void @select_assume(i32 %a, i32 %b, i1 %c, ptr %p) { 1930; CHECK-LABEL: define void @select_assume 1931; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i1 [[C:%.*]], ptr [[P:%.*]]) { 1932; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[A]], 10 1933; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 1934; CHECK-NEXT: [[C2:%.*]] = icmp ult i32 [[B]], 20 1935; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 1936; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]] 1937; CHECK-NEXT: [[C3:%.*]] = icmp samesign ult i32 [[S]], 19 1938; CHECK-NEXT: store i1 [[C3]], ptr [[P]], align 1 1939; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1940; CHECK-NEXT: ret void 1941; 1942 %c1 = icmp ult i32 %a, 10 1943 call void @llvm.assume(i1 %c1) 1944 %c2 = icmp ult i32 %b, 20 1945 call void @llvm.assume(i1 %c2) 1946 %s = select i1 %c, i32 %a, i32 %b 1947 %c3 = icmp ult i32 %s, 19 1948 store i1 %c3, ptr %p 1949 %c4 = icmp ult i32 %s, 20 1950 store i1 %c4, ptr %p 1951 ret void 1952} 1953 1954define void @xor(i8 %a, ptr %p) { 1955; CHECK-LABEL: define void @xor 1956; CHECK-SAME: (i8 [[A:%.*]], ptr [[P:%.*]]) { 1957; CHECK-NEXT: [[A_MASK:%.*]] = and i8 [[A]], 15 1958; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[A_MASK]], -86 1959; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1960; CHECK-NEXT: [[C2:%.*]] = icmp samesign ugt i8 [[XOR]], -96 1961; CHECK-NEXT: store i1 [[C2]], ptr [[P]], align 1 1962; CHECK-NEXT: store i1 true, ptr [[P]], align 1 1963; CHECK-NEXT: [[C4:%.*]] = icmp samesign ult i8 [[XOR]], -81 1964; CHECK-NEXT: store i1 [[C4]], ptr [[P]], align 1 1965; CHECK-NEXT: ret void 1966; 1967 %a.mask = and i8 %a, 15 ; 0b0000???? 1968 %xor = xor i8 %a.mask, 170 ; ^ 0b10101010 == 0b1010???? 1969 %c1 = icmp uge i8 %xor, 160 1970 store i1 %c1, ptr %p 1971 %c2 = icmp ugt i8 %xor, 160 1972 store i1 %c2, ptr %p 1973 %c3 = icmp ule i8 %xor, 175 1974 store i1 %c3, ptr %p 1975 %c4 = icmp ult i8 %xor, 175 1976 store i1 %c4, ptr %p 1977 ret void 1978} 1979 1980define i1 @xor_neg_cond(i32 %a) { 1981; CHECK-LABEL: define i1 @xor_neg_cond 1982; CHECK-SAME: (i32 [[A:%.*]]) { 1983; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A]], 10 1984; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[CMP1]], true 1985; CHECK-NEXT: br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 1986; CHECK: guard: 1987; CHECK-NEXT: ret i1 true 1988; CHECK: exit: 1989; CHECK-NEXT: ret i1 false 1990; 1991 %cmp1 = icmp eq i32 %a, 10 1992 %xor = xor i1 %cmp1, true 1993 br i1 %xor, label %exit, label %guard 1994 1995guard: 1996 %cmp2 = icmp eq i32 %a, 10 1997 ret i1 %cmp2 1998 1999exit: 2000 ret i1 false 2001} 2002 2003define i1 @xor_approx(i32 %a) { 2004; CHECK-LABEL: define i1 @xor_approx 2005; CHECK-SAME: (i32 [[A:%.*]]) { 2006; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A]], 2 2007; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[A]], 5 2008; CHECK-NEXT: [[CMP3:%.*]] = icmp ugt i32 [[A]], 7 2009; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[A]], 9 2010; CHECK-NEXT: [[AND1:%.*]] = and i1 [[CMP1]], [[CMP2]] 2011; CHECK-NEXT: [[AND2:%.*]] = and i1 [[CMP3]], [[CMP4]] 2012; CHECK-NEXT: [[OR:%.*]] = or i1 [[AND1]], [[AND2]] 2013; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[OR]], true 2014; CHECK-NEXT: br i1 [[XOR]], label [[EXIT:%.*]], label [[GUARD:%.*]] 2015; CHECK: guard: 2016; CHECK-NEXT: [[CMP5:%.*]] = icmp eq i32 [[A]], 6 2017; CHECK-NEXT: ret i1 [[CMP5]] 2018; CHECK: exit: 2019; CHECK-NEXT: ret i1 false 2020; 2021 %cmp1 = icmp ugt i32 %a, 2 2022 %cmp2 = icmp ult i32 %a, 5 2023 %cmp3 = icmp ugt i32 %a, 7 2024 %cmp4 = icmp ult i32 %a, 9 2025 %and1 = and i1 %cmp1, %cmp2 2026 %and2 = and i1 %cmp3, %cmp4 2027 %or = or i1 %and1, %and2 2028 %xor = xor i1 %or, true 2029 br i1 %xor, label %exit, label %guard 2030 2031guard: 2032 %cmp5 = icmp eq i32 %a, 6 2033 ret i1 %cmp5 2034 2035exit: 2036 ret i1 false 2037} 2038 2039define i1 @binop_eval_order(i32 %x) { 2040; CHECK-LABEL: define i1 @binop_eval_order 2041; CHECK-SAME: (i32 [[X:%.*]]) { 2042; CHECK-NEXT: [[A:%.*]] = add nuw nsw i32 [[X]], 1 2043; CHECK-NEXT: [[B:%.*]] = add nuw nsw i32 [[A]], 1 2044; CHECK-NEXT: [[C:%.*]] = add nuw nsw i32 [[A]], [[B]] 2045; CHECK-NEXT: ret i1 true 2046; 2047 %a = add nuw nsw i32 %x, 1 2048 %b = add nuw nsw i32 %a, 1 2049 %c = add nuw nsw i32 %a, %b 2050 %d = icmp ugt i32 %c, 2 2051 ret i1 %d 2052} 2053 2054define range(i32 0, 1024) i32 @range_larger(i8 %x) { 2055; CHECK-LABEL: define range(i32 0, 256) i32 @range_larger 2056; CHECK-SAME: (i8 [[X:%.*]]) { 2057; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X]] to i32 2058; CHECK-NEXT: ret i32 [[ZEXT]] 2059; 2060 %zext = zext i8 %x to i32 2061 ret i32 %zext 2062} 2063 2064define range(i32 0, 128) i32 @range_smaller(i8 %x) { 2065; CHECK-LABEL: define range(i32 0, 128) i32 @range_smaller 2066; CHECK-SAME: (i8 [[X:%.*]]) { 2067; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X]] to i32 2068; CHECK-NEXT: ret i32 [[ZEXT]] 2069; 2070 %zext = zext i8 %x to i32 2071 ret i32 %zext 2072} 2073 2074define range(i32 128, 512) i32 @range_intersect(i8 %x) { 2075; CHECK-LABEL: define range(i32 128, 256) i32 @range_intersect 2076; CHECK-SAME: (i8 [[X:%.*]]) { 2077; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X]] to i32 2078; CHECK-NEXT: ret i32 [[ZEXT]] 2079; 2080 %zext = zext i8 %x to i32 2081 ret i32 %zext 2082} 2083 2084define range(i32 512, 1024) i32 @range_non_overlapping(i8 %x) { 2085; CHECK-LABEL: define range(i32 512, 1024) i32 @range_non_overlapping 2086; CHECK-SAME: (i8 [[X:%.*]]) { 2087; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X]] to i32 2088; CHECK-NEXT: ret i32 [[ZEXT]] 2089; 2090 %zext = zext i8 %x to i32 2091 ret i32 %zext 2092} 2093 2094declare i32 @llvm.uadd.sat.i32(i32, i32) 2095declare i32 @llvm.usub.sat.i32(i32, i32) 2096declare i32 @llvm.sadd.sat.i32(i32, i32) 2097declare i32 @llvm.ssub.sat.i32(i32, i32) 2098declare void @llvm.assume(i1) 2099