1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=indvars -S < %s -indvars-predicate-loops=0 | FileCheck %s 3 4; A collection of tests which domonstrate cases where we can use properties 5; of the loop (i.e. single exit, finite, mustprogress) to optimize conditions 6; and extends we couldn't otherwise handle. 7 8target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 9 10define void @slt_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 11; CHECK-LABEL: @slt_constant_rhs( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 14; CHECK-NEXT: br label [[FOR_BODY:%.*]] 15; CHECK: for.body: 16; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 17; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 18; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 19; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 20; CHECK: for.end: 21; CHECK-NEXT: ret void 22; 23entry: 24 br label %for.body 25 26for.body: ; preds = %entry, %for.body 27 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 28 %iv.next = add i8 %iv, 1 29 %zext = zext i8 %iv.next to i16 30 %cmp = icmp slt i16 %zext, 254 31 br i1 %cmp, label %for.body, label %for.end 32 33for.end: ; preds = %for.body, %entry 34 ret void 35} 36 37;; Range logic doesn't depend on must execute 38define void @slt_constant_rhs_maythrow(i16 %n.raw, i8 %start) mustprogress { 39; CHECK-LABEL: @slt_constant_rhs_maythrow( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 42; CHECK-NEXT: br label [[FOR_BODY:%.*]] 43; CHECK: for.body: 44; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 45; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 46; CHECK-NEXT: call void @unknown() 47; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 48; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 49; CHECK: for.end: 50; CHECK-NEXT: ret void 51; 52entry: 53 br label %for.body 54 55for.body: ; preds = %entry, %for.body 56 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 57 %iv.next = add i8 %iv, 1 58 call void @unknown() 59 %zext = zext i8 %iv.next to i16 60 %cmp = icmp slt i16 %zext, 254 61 br i1 %cmp, label %for.body, label %for.end 62 63for.end: ; preds = %for.body, %entry 64 ret void 65} 66 67;; Range logic doesn't depend on must execute 68define void @slt_constant_rhs_multiexit(i16 %n.raw, i8 %start, i1 %c) mustprogress { 69; CHECK-LABEL: @slt_constant_rhs_multiexit( 70; CHECK-NEXT: entry: 71; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 72; CHECK-NEXT: br label [[FOR_BODY:%.*]] 73; CHECK: for.body: 74; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 75; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 76; CHECK-NEXT: br i1 [[C:%.*]], label [[LATCH]], label [[FOR_END:%.*]] 77; CHECK: latch: 78; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 79; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]] 80; CHECK: for.end: 81; CHECK-NEXT: ret void 82; 83entry: 84 br label %for.body 85 86for.body: ; preds = %entry, %for.body 87 %iv = phi i8 [ %iv.next, %latch ], [ %start, %entry ] 88 %iv.next = add i8 %iv, 1 89 br i1 %c, label %latch, label %for.end 90 91latch: 92 %zext = zext i8 %iv.next to i16 93 %cmp = icmp slt i16 %zext, 254 94 br i1 %cmp, label %for.body, label %for.end 95 96for.end: ; preds = %for.body, %entry 97 ret void 98} 99 100define void @slt_non_constant_rhs(i16 %n) mustprogress { 101; CHECK-LABEL: @slt_non_constant_rhs( 102; CHECK-NEXT: entry: 103; CHECK-NEXT: br label [[FOR_BODY:%.*]] 104; CHECK: for.body: 105; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 106; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 107; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 108; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]] 109; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 110; CHECK: for.end: 111; CHECK-NEXT: ret void 112; 113entry: 114 br label %for.body 115 116for.body: ; preds = %entry, %for.body 117 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 118 %iv.next = add i8 %iv, 1 119 %zext = zext i8 %iv.next to i16 120 %cmp = icmp slt i16 %zext, %n 121 br i1 %cmp, label %for.body, label %for.end 122 123for.end: ; preds = %for.body, %entry 124 ret void 125} 126 127; Case where we could prove this using range facts, but not must exit reasoning 128define void @slt_non_constant_rhs_no_mustprogress(i16 %n.raw) { 129; CHECK-LABEL: @slt_non_constant_rhs_no_mustprogress( 130; CHECK-NEXT: entry: 131; CHECK-NEXT: [[N:%.*]] = and i16 [[N_RAW:%.*]], 255 132; CHECK-NEXT: [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1) 133; CHECK-NEXT: br label [[FOR_BODY:%.*]] 134; CHECK: for.body: 135; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 136; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1 137; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]] 138; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]] 139; CHECK: for.end: 140; CHECK-NEXT: ret void 141; 142entry: 143 %n = and i16 %n.raw, 255 144 br label %for.body 145 146for.body: ; preds = %entry, %for.body 147 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 148 %iv.next = add i8 %iv, 1 149 %zext = zext i8 %iv.next to i16 150 %cmp = icmp slt i16 %zext, %n 151 br i1 %cmp, label %for.body, label %for.end 152 153for.end: ; preds = %for.body, %entry 154 ret void 155} 156 157; Fact holds for exiting branch, but not for earlier use 158; We could recognize the unreachable loop here, but don't currently. Its 159; also not terribly interesting, because EarlyCSE will fold condition. 160define void @slt_neg_multiple_use(i8 %start) mustprogress { 161; CHECK-LABEL: @slt_neg_multiple_use( 162; CHECK-NEXT: entry: 163; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16 164; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], 254 165; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] 166; CHECK: for.body.preheader: 167; CHECK-NEXT: br label [[FOR_BODY:%.*]] 168; CHECK: for.body: 169; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 170; CHECK: for.end.loopexit: 171; CHECK-NEXT: br label [[FOR_END]] 172; CHECK: for.end: 173; CHECK-NEXT: ret void 174; 175entry: 176 %zext = zext i8 %start to i16 177 %cmp = icmp slt i16 %zext, 254 178 br i1 %cmp, label %for.body, label %for.end 179 180for.body: ; preds = %entry, %for.body 181 br i1 %cmp, label %for.body, label %for.end 182 183for.end: ; preds = %for.body, %entry 184 ret void 185} 186 187define void @slt_neg_multiple_use2(i8 %start, i16 %n) mustprogress { 188; CHECK-LABEL: @slt_neg_multiple_use2( 189; CHECK-NEXT: entry: 190; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[START:%.*]] to i16 191; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]] 192; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] 193; CHECK: for.body.preheader: 194; CHECK-NEXT: br label [[FOR_BODY:%.*]] 195; CHECK: for.body: 196; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 197; CHECK: for.end.loopexit: 198; CHECK-NEXT: br label [[FOR_END]] 199; CHECK: for.end: 200; CHECK-NEXT: ret void 201; 202entry: 203 %zext = zext i8 %start to i16 204 %cmp = icmp slt i16 %zext, %n 205 br i1 %cmp, label %for.body, label %for.end 206 207for.body: ; preds = %entry, %for.body 208 br i1 %cmp, label %for.body, label %for.end 209 210for.end: ; preds = %for.body, %entry 211 ret void 212} 213 214@G = external global i8 215 216; Negative case where the loop could be infinite and make progress 217define void @slt_neg_well_defined_infinite(i16 %n) mustprogress { 218; CHECK-LABEL: @slt_neg_well_defined_infinite( 219; CHECK-NEXT: entry: 220; CHECK-NEXT: br label [[FOR_BODY:%.*]] 221; CHECK: for.body: 222; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 223; CHECK-NEXT: store volatile i8 [[IV]], ptr @G, align 1 224; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 225; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 226; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]] 227; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 228; CHECK: for.end: 229; CHECK-NEXT: ret void 230; 231entry: 232 br label %for.body 233 234for.body: ; preds = %entry, %for.body 235 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 236 store volatile i8 %iv, ptr @G 237 %iv.next = add i8 %iv, 1 238 %zext = zext i8 %iv.next to i16 239 %cmp = icmp slt i16 %zext, %n 240 br i1 %cmp, label %for.body, label %for.end 241 242for.end: ; preds = %for.body, %entry 243 ret void 244} 245 246; Negative case with no mustprogress rsltuirement 247define void @slt_neg_no_mustprogress(i16 %n) { 248; CHECK-LABEL: @slt_neg_no_mustprogress( 249; CHECK-NEXT: entry: 250; CHECK-NEXT: br label [[FOR_BODY:%.*]] 251; CHECK: for.body: 252; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 253; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 254; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 255; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]] 256; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 257; CHECK: for.end: 258; CHECK-NEXT: ret void 259; 260entry: 261 br label %for.body 262 263for.body: ; preds = %entry, %for.body 264 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 265 %iv.next = add i8 %iv, 1 266 %zext = zext i8 %iv.next to i16 267 %cmp = icmp slt i16 %zext, %n 268 br i1 %cmp, label %for.body, label %for.end 269 270for.end: ; preds = %for.body, %entry 271 ret void 272} 273 274declare void @unknown() 275 276define void @slt_neg_abnormal_exit(i16 %n) mustprogress { 277; CHECK-LABEL: @slt_neg_abnormal_exit( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: br label [[FOR_BODY:%.*]] 280; CHECK: for.body: 281; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 282; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 283; CHECK-NEXT: call void @unknown() 284; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 285; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[ZEXT]], [[N:%.*]] 286; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 287; CHECK: for.end: 288; CHECK-NEXT: ret void 289; 290entry: 291 br label %for.body 292 293for.body: ; preds = %entry, %for.body 294 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 295 %iv.next = add i8 %iv, 1 296 call void @unknown() 297 %zext = zext i8 %iv.next to i16 298 %cmp = icmp slt i16 %zext, %n 299 br i1 %cmp, label %for.body, label %for.end 300 301for.end: ; preds = %for.body, %entry 302 ret void 303} 304 305; For the other comparison flavors, we only bother to repeat the positive 306; tests since the negative variants are mostly the same. 307 308define void @ne_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 309; CHECK-LABEL: @ne_constant_rhs( 310; CHECK-NEXT: entry: 311; CHECK-NEXT: br label [[FOR_BODY:%.*]] 312; CHECK: for.body: 313; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 314; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 315; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 316; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[ZEXT]], 254 317; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 318; CHECK: for.end: 319; CHECK-NEXT: ret void 320; 321entry: 322 br label %for.body 323 324for.body: ; preds = %entry, %for.body 325 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 326 %iv.next = add i8 %iv, 1 327 %zext = zext i8 %iv.next to i16 328 %cmp = icmp ne i16 %zext, 254 329 br i1 %cmp, label %for.body, label %for.end 330 331for.end: ; preds = %for.body, %entry 332 ret void 333} 334 335define void @ne_non_constant_rhs(i16 %n) mustprogress { 336; CHECK-LABEL: @ne_non_constant_rhs( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: br label [[FOR_BODY:%.*]] 339; CHECK: for.body: 340; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 341; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 342; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 343; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[ZEXT]], [[N:%.*]] 344; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 345; CHECK: for.end: 346; CHECK-NEXT: ret void 347; 348entry: 349 br label %for.body 350 351for.body: ; preds = %entry, %for.body 352 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 353 %iv.next = add i8 %iv, 1 354 %zext = zext i8 %iv.next to i16 355 %cmp = icmp ne i16 %zext, %n 356 br i1 %cmp, label %for.body, label %for.end 357 358for.end: ; preds = %for.body, %entry 359 ret void 360} 361 362define void @eq_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 363; CHECK-LABEL: @eq_constant_rhs( 364; CHECK-NEXT: entry: 365; CHECK-NEXT: br label [[FOR_BODY:%.*]] 366; CHECK: for.body: 367; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 368; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 369; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 370; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[ZEXT]], 254 371; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 372; CHECK: for.end: 373; CHECK-NEXT: ret void 374; 375entry: 376 br label %for.body 377 378for.body: ; preds = %entry, %for.body 379 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 380 %iv.next = add i8 %iv, 1 381 %zext = zext i8 %iv.next to i16 382 %cmp = icmp eq i16 %zext, 254 383 br i1 %cmp, label %for.body, label %for.end 384 385for.end: ; preds = %for.body, %entry 386 ret void 387} 388 389define void @eq_non_constant_rhs(i16 %n) mustprogress { 390; CHECK-LABEL: @eq_non_constant_rhs( 391; CHECK-NEXT: entry: 392; CHECK-NEXT: br label [[FOR_BODY:%.*]] 393; CHECK: for.body: 394; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 395; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 396; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 397; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[ZEXT]], [[N:%.*]] 398; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 399; CHECK: for.end: 400; CHECK-NEXT: ret void 401; 402entry: 403 br label %for.body 404 405for.body: ; preds = %entry, %for.body 406 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 407 %iv.next = add i8 %iv, 1 408 %zext = zext i8 %iv.next to i16 409 %cmp = icmp eq i16 %zext, %n 410 br i1 %cmp, label %for.body, label %for.end 411 412for.end: ; preds = %for.body, %entry 413 ret void 414} 415 416define void @sgt_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 417; CHECK-LABEL: @sgt_constant_rhs( 418; CHECK-NEXT: entry: 419; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 420; CHECK-NEXT: br label [[FOR_BODY:%.*]] 421; CHECK: for.body: 422; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 423; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 424; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]] 425; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 426; CHECK: for.end: 427; CHECK-NEXT: ret void 428; 429entry: 430 br label %for.body 431 432for.body: ; preds = %entry, %for.body 433 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 434 %iv.next = add i8 %iv, 1 435 %zext = zext i8 %iv.next to i16 436 %cmp = icmp sgt i16 %zext, 254 437 br i1 %cmp, label %for.body, label %for.end 438 439for.end: ; preds = %for.body, %entry 440 ret void 441} 442 443define void @sgt_non_constant_rhs(i16 %n) mustprogress { 444; CHECK-LABEL: @sgt_non_constant_rhs( 445; CHECK-NEXT: entry: 446; CHECK-NEXT: br label [[FOR_BODY:%.*]] 447; CHECK: for.body: 448; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 449; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 450; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 451; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[ZEXT]], [[N:%.*]] 452; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 453; CHECK: for.end: 454; CHECK-NEXT: ret void 455; 456entry: 457 br label %for.body 458 459for.body: ; preds = %entry, %for.body 460 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 461 %iv.next = add i8 %iv, 1 462 %zext = zext i8 %iv.next to i16 463 %cmp = icmp sgt i16 %zext, %n 464 br i1 %cmp, label %for.body, label %for.end 465 466for.end: ; preds = %for.body, %entry 467 ret void 468} 469 470define void @sle_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 471; CHECK-LABEL: @sle_constant_rhs( 472; CHECK-NEXT: entry: 473; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 474; CHECK-NEXT: br label [[FOR_BODY:%.*]] 475; CHECK: for.body: 476; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 477; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 478; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]] 479; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 480; CHECK: for.end: 481; CHECK-NEXT: ret void 482; 483entry: 484 br label %for.body 485 486for.body: ; preds = %entry, %for.body 487 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 488 %iv.next = add i8 %iv, 1 489 %zext = zext i8 %iv.next to i16 490 %cmp = icmp sle i16 %zext, 254 491 br i1 %cmp, label %for.body, label %for.end 492 493for.end: ; preds = %for.body, %entry 494 ret void 495} 496 497define void @sle_non_constant_rhs(i16 %n) mustprogress { 498; CHECK-LABEL: @sle_non_constant_rhs( 499; CHECK-NEXT: entry: 500; CHECK-NEXT: br label [[FOR_BODY:%.*]] 501; CHECK: for.body: 502; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 503; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 504; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 505; CHECK-NEXT: [[CMP:%.*]] = icmp sle i16 [[ZEXT]], [[N:%.*]] 506; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 507; CHECK: for.end: 508; CHECK-NEXT: ret void 509; 510entry: 511 br label %for.body 512 513for.body: ; preds = %entry, %for.body 514 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 515 %iv.next = add i8 %iv, 1 516 %zext = zext i8 %iv.next to i16 517 %cmp = icmp sle i16 %zext, %n 518 br i1 %cmp, label %for.body, label %for.end 519 520for.end: ; preds = %for.body, %entry 521 ret void 522} 523 524define void @sge_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 525; CHECK-LABEL: @sge_constant_rhs( 526; CHECK-NEXT: entry: 527; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 528; CHECK-NEXT: br label [[FOR_BODY:%.*]] 529; CHECK: for.body: 530; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 531; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 532; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]] 533; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 534; CHECK: for.end: 535; CHECK-NEXT: ret void 536; 537entry: 538 br label %for.body 539 540for.body: ; preds = %entry, %for.body 541 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 542 %iv.next = add i8 %iv, 1 543 %zext = zext i8 %iv.next to i16 544 %cmp = icmp sge i16 %zext, 254 545 br i1 %cmp, label %for.body, label %for.end 546 547for.end: ; preds = %for.body, %entry 548 ret void 549} 550 551define void @sge_non_constant_rhs(i16 %n) mustprogress { 552; CHECK-LABEL: @sge_non_constant_rhs( 553; CHECK-NEXT: entry: 554; CHECK-NEXT: br label [[FOR_BODY:%.*]] 555; CHECK: for.body: 556; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 557; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 558; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 559; CHECK-NEXT: [[CMP:%.*]] = icmp sge i16 [[ZEXT]], [[N:%.*]] 560; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 561; CHECK: for.end: 562; CHECK-NEXT: ret void 563; 564entry: 565 br label %for.body 566 567for.body: ; preds = %entry, %for.body 568 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 569 %iv.next = add i8 %iv, 1 570 %zext = zext i8 %iv.next to i16 571 %cmp = icmp sge i16 %zext, %n 572 br i1 %cmp, label %for.body, label %for.end 573 574for.end: ; preds = %for.body, %entry 575 ret void 576} 577 578define void @ult_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 579; CHECK-LABEL: @ult_constant_rhs( 580; CHECK-NEXT: entry: 581; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 582; CHECK-NEXT: br label [[FOR_BODY:%.*]] 583; CHECK: for.body: 584; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 585; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 586; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 587; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 588; CHECK: for.end: 589; CHECK-NEXT: ret void 590; 591entry: 592 br label %for.body 593 594for.body: ; preds = %entry, %for.body 595 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 596 %iv.next = add i8 %iv, 1 597 %zext = zext i8 %iv.next to i16 598 %cmp = icmp ult i16 %zext, 254 599 br i1 %cmp, label %for.body, label %for.end 600 601for.end: ; preds = %for.body, %entry 602 ret void 603} 604 605define void @ult_non_constant_rhs(i16 %n) mustprogress { 606; CHECK-LABEL: @ult_non_constant_rhs( 607; CHECK-NEXT: entry: 608; CHECK-NEXT: br label [[FOR_BODY:%.*]] 609; CHECK: for.body: 610; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 611; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 612; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 613; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[ZEXT]], [[N:%.*]] 614; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 615; CHECK: for.end: 616; CHECK-NEXT: ret void 617; 618entry: 619 br label %for.body 620 621for.body: ; preds = %entry, %for.body 622 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 623 %iv.next = add i8 %iv, 1 624 %zext = zext i8 %iv.next to i16 625 %cmp = icmp ult i16 %zext, %n 626 br i1 %cmp, label %for.body, label %for.end 627 628for.end: ; preds = %for.body, %entry 629 ret void 630} 631 632define void @ugt_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 633; CHECK-LABEL: @ugt_constant_rhs( 634; CHECK-NEXT: entry: 635; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 636; CHECK-NEXT: br label [[FOR_BODY:%.*]] 637; CHECK: for.body: 638; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 639; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 640; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[IV_NEXT]], [[TMP0]] 641; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 642; CHECK: for.end: 643; CHECK-NEXT: ret void 644; 645entry: 646 br label %for.body 647 648for.body: ; preds = %entry, %for.body 649 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 650 %iv.next = add i8 %iv, 1 651 %zext = zext i8 %iv.next to i16 652 %cmp = icmp ugt i16 %zext, 254 653 br i1 %cmp, label %for.body, label %for.end 654 655for.end: ; preds = %for.body, %entry 656 ret void 657} 658 659define void @ugt_neg_non_loop(i16 %n.raw, i8 %start) mustprogress { 660; CHECK-LABEL: @ugt_neg_non_loop( 661; CHECK-NEXT: entry: 662; CHECK-NEXT: br label [[FOR_BODY:%.*]] 663; CHECK: for.body: 664; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 665; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 666; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 667; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], -2 668; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 669; CHECK: for.end: 670; CHECK-NEXT: ret void 671; 672entry: 673 br label %for.body 674 675for.body: ; preds = %entry, %for.body 676 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 677 %iv.next = add i8 %iv, 1 678 %zext = zext i8 %iv.next to i16 679 %cmp = icmp ugt i16 %zext, -2 680 br i1 %cmp, label %for.body, label %for.end 681 682for.end: ; preds = %for.body, %entry 683 ret void 684} 685 686define void @ugt_non_constant_rhs(i16 %n) mustprogress { 687; CHECK-LABEL: @ugt_non_constant_rhs( 688; CHECK-NEXT: entry: 689; CHECK-NEXT: br label [[FOR_BODY:%.*]] 690; CHECK: for.body: 691; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 692; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 693; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 694; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[ZEXT]], [[N:%.*]] 695; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 696; CHECK: for.end: 697; CHECK-NEXT: ret void 698; 699entry: 700 br label %for.body 701 702for.body: ; preds = %entry, %for.body 703 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 704 %iv.next = add i8 %iv, 1 705 %zext = zext i8 %iv.next to i16 706 %cmp = icmp ugt i16 %zext, %n 707 br i1 %cmp, label %for.body, label %for.end 708 709for.end: ; preds = %for.body, %entry 710 ret void 711} 712 713define void @ule_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 714; CHECK-LABEL: @ule_constant_rhs( 715; CHECK-NEXT: entry: 716; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 717; CHECK-NEXT: br label [[FOR_BODY:%.*]] 718; CHECK: for.body: 719; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 720; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 721; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[IV_NEXT]], [[TMP0]] 722; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 723; CHECK: for.end: 724; CHECK-NEXT: ret void 725; 726entry: 727 br label %for.body 728 729for.body: ; preds = %entry, %for.body 730 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 731 %iv.next = add i8 %iv, 1 732 %zext = zext i8 %iv.next to i16 733 %cmp = icmp ule i16 %zext, 254 734 br i1 %cmp, label %for.body, label %for.end 735 736for.end: ; preds = %for.body, %entry 737 ret void 738} 739 740define void @ule_non_constant_rhs(i16 %n) mustprogress { 741; CHECK-LABEL: @ule_non_constant_rhs( 742; CHECK-NEXT: entry: 743; CHECK-NEXT: br label [[FOR_BODY:%.*]] 744; CHECK: for.body: 745; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 746; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 747; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 748; CHECK-NEXT: [[CMP:%.*]] = icmp ule i16 [[ZEXT]], [[N:%.*]] 749; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 750; CHECK: for.end: 751; CHECK-NEXT: ret void 752; 753entry: 754 br label %for.body 755 756for.body: ; preds = %entry, %for.body 757 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 758 %iv.next = add i8 %iv, 1 759 %zext = zext i8 %iv.next to i16 760 %cmp = icmp ule i16 %zext, %n 761 br i1 %cmp, label %for.body, label %for.end 762 763for.end: ; preds = %for.body, %entry 764 ret void 765} 766 767define void @uge_constant_rhs(i16 %n.raw, i8 %start) mustprogress { 768; CHECK-LABEL: @uge_constant_rhs( 769; CHECK-NEXT: entry: 770; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 771; CHECK-NEXT: br label [[FOR_BODY:%.*]] 772; CHECK: for.body: 773; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 774; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 775; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[IV_NEXT]], [[TMP0]] 776; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 777; CHECK: for.end: 778; CHECK-NEXT: ret void 779; 780entry: 781 br label %for.body 782 783for.body: ; preds = %entry, %for.body 784 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 785 %iv.next = add i8 %iv, 1 786 %zext = zext i8 %iv.next to i16 787 %cmp = icmp uge i16 %zext, 254 788 br i1 %cmp, label %for.body, label %for.end 789 790for.end: ; preds = %for.body, %entry 791 ret void 792} 793 794define void @uge_non_constant_rhs(i16 %n) mustprogress { 795; CHECK-LABEL: @uge_non_constant_rhs( 796; CHECK-NEXT: entry: 797; CHECK-NEXT: br label [[FOR_BODY:%.*]] 798; CHECK: for.body: 799; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 800; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 801; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 802; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[ZEXT]], [[N:%.*]] 803; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 804; CHECK: for.end: 805; CHECK-NEXT: ret void 806; 807entry: 808 br label %for.body 809 810for.body: ; preds = %entry, %for.body 811 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 812 %iv.next = add i8 %iv, 1 813 %zext = zext i8 %iv.next to i16 814 %cmp = icmp uge i16 %zext, %n 815 br i1 %cmp, label %for.body, label %for.end 816 817for.end: ; preds = %for.body, %entry 818 ret void 819} 820 821; Show that these transformatios also work with inverted operands 822; We only both to do this with slt/ult, but it applies to all predicates. 823 824define void @slt_constant_lhs(i16 %n.raw, i8 %start) mustprogress { 825; CHECK-LABEL: @slt_constant_lhs( 826; CHECK-NEXT: entry: 827; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 828; CHECK-NEXT: br label [[FOR_BODY:%.*]] 829; CHECK: for.body: 830; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 831; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 832; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]] 833; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 834; CHECK: for.end: 835; CHECK-NEXT: ret void 836; 837entry: 838 br label %for.body 839 840for.body: ; preds = %entry, %for.body 841 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 842 %iv.next = add i8 %iv, 1 843 %zext = zext i8 %iv.next to i16 844 %cmp = icmp slt i16 254, %zext 845 br i1 %cmp, label %for.body, label %for.end 846 847for.end: ; preds = %for.body, %entry 848 ret void 849} 850 851define void @slt_non_constant_lhs(i16 %n) mustprogress { 852; CHECK-LABEL: @slt_non_constant_lhs( 853; CHECK-NEXT: entry: 854; CHECK-NEXT: br label [[FOR_BODY:%.*]] 855; CHECK: for.body: 856; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 857; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 858; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 859; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[N:%.*]], [[ZEXT]] 860; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 861; CHECK: for.end: 862; CHECK-NEXT: ret void 863; 864entry: 865 br label %for.body 866 867for.body: ; preds = %entry, %for.body 868 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 869 %iv.next = add i8 %iv, 1 870 %zext = zext i8 %iv.next to i16 871 %cmp = icmp slt i16 %n, %zext 872 br i1 %cmp, label %for.body, label %for.end 873 874for.end: ; preds = %for.body, %entry 875 ret void 876} 877 878define void @ult_constant_lhs(i16 %n.raw, i8 %start) mustprogress { 879; CHECK-LABEL: @ult_constant_lhs( 880; CHECK-NEXT: entry: 881; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 882; CHECK-NEXT: br label [[FOR_BODY:%.*]] 883; CHECK: for.body: 884; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 885; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 886; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], [[IV_NEXT]] 887; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 888; CHECK: for.end: 889; CHECK-NEXT: ret void 890; 891entry: 892 br label %for.body 893 894for.body: ; preds = %entry, %for.body 895 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 896 %iv.next = add i8 %iv, 1 897 %zext = zext i8 %iv.next to i16 898 %cmp = icmp ult i16 254, %zext 899 br i1 %cmp, label %for.body, label %for.end 900 901for.end: ; preds = %for.body, %entry 902 ret void 903} 904 905define void @ult_non_constant_lhs(i16 %n) mustprogress { 906; CHECK-LABEL: @ult_non_constant_lhs( 907; CHECK-NEXT: entry: 908; CHECK-NEXT: br label [[FOR_BODY:%.*]] 909; CHECK: for.body: 910; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 911; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 912; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[IV_NEXT]] to i16 913; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[N:%.*]], [[ZEXT]] 914; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 915; CHECK: for.end: 916; CHECK-NEXT: ret void 917; 918entry: 919 br label %for.body 920 921for.body: ; preds = %entry, %for.body 922 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 923 %iv.next = add i8 %iv, 1 924 %zext = zext i8 %iv.next to i16 925 %cmp = icmp ult i16 %n, %zext 926 br i1 %cmp, label %for.body, label %for.end 927 928for.end: ; preds = %for.body, %entry 929 ret void 930} 931 932define i16 @ult_multiuse_profit(i16 %n.raw, i8 %start) mustprogress { 933; CHECK-LABEL: @ult_multiuse_profit( 934; CHECK-NEXT: entry: 935; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[START:%.*]], 1 936; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i16 937; CHECK-NEXT: [[TMP2:%.*]] = trunc i16 254 to i8 938; CHECK-NEXT: br label [[FOR_BODY:%.*]] 939; CHECK: for.body: 940; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START]], [[ENTRY:%.*]] ] 941; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 942; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP2]] 943; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 944; CHECK: for.end: 945; CHECK-NEXT: [[UMAX:%.*]] = call i16 @llvm.umax.i16(i16 [[TMP1]], i16 254) 946; CHECK-NEXT: ret i16 [[UMAX]] 947; 948entry: 949 br label %for.body 950 951for.body: ; preds = %entry, %for.body 952 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 953 %iv.next = add i8 %iv, 1 954 %zext = zext i8 %iv.next to i16 955 %cmp = icmp ult i16 %zext, 254 956 br i1 %cmp, label %for.body, label %for.end 957 958for.end: ; preds = %for.body, %entry 959 ret i16 %zext 960} 961 962define i16 @ult_multiuse_profit2(i16 %n.raw, i8 %start) mustprogress { 963; CHECK-LABEL: @ult_multiuse_profit2( 964; CHECK-NEXT: entry: 965; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 254 to i8 966; CHECK-NEXT: br label [[FOR_BODY:%.*]] 967; CHECK: for.body: 968; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[START:%.*]], [[ENTRY:%.*]] ] 969; CHECK-NEXT: [[IV2:%.*]] = phi i16 [ [[ZEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY]] ] 970; CHECK-NEXT: [[IV_NEXT]] = add i8 [[IV]], 1 971; CHECK-NEXT: [[ZEXT]] = zext i8 [[IV_NEXT]] to i16 972; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 973; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 974; CHECK: for.end: 975; CHECK-NEXT: [[IV2_LCSSA:%.*]] = phi i16 [ [[IV2]], [[FOR_BODY]] ] 976; CHECK-NEXT: ret i16 [[IV2_LCSSA]] 977; 978entry: 979 br label %for.body 980 981for.body: ; preds = %entry, %for.body 982 %iv = phi i8 [ %iv.next, %for.body ], [ %start, %entry ] 983 %iv2 = phi i16 [%zext, %for.body], [0, %entry] 984 %iv.next = add i8 %iv, 1 985 %zext = zext i8 %iv.next to i16 986 %cmp = icmp ult i16 %zext, 254 987 br i1 %cmp, label %for.body, label %for.end 988 989for.end: ; preds = %for.body, %entry 990 ret i16 %iv2 991} 992 993define void @slt_restricted_rhs(i16 %n.raw) mustprogress { 994; CHECK-LABEL: @slt_restricted_rhs( 995; CHECK-NEXT: entry: 996; CHECK-NEXT: [[N:%.*]] = and i16 [[N_RAW:%.*]], 255 997; CHECK-NEXT: [[SMAX:%.*]] = call i16 @llvm.smax.i16(i16 [[N]], i16 1) 998; CHECK-NEXT: br label [[FOR_BODY:%.*]] 999; CHECK: for.body: 1000; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i16 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ] 1001; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i16 [[INDVARS_IV]], 1 1002; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i16 [[INDVARS_IV_NEXT]], [[SMAX]] 1003; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]] 1004; CHECK: for.end: 1005; CHECK-NEXT: ret void 1006; 1007entry: 1008 %n = and i16 %n.raw, 255 1009 br label %for.body 1010 1011for.body: ; preds = %entry, %for.body 1012 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 1013 %iv.next = add i8 %iv, 1 1014 %zext = zext i8 %iv.next to i16 1015 %cmp = icmp slt i16 %zext, %n 1016 br i1 %cmp, label %for.body, label %for.end 1017 1018for.end: ; preds = %for.body, %entry 1019 ret void 1020} 1021 1022define void @slt_guarded_rhs(i16 %n) mustprogress { 1023; CHECK-LABEL: @slt_guarded_rhs( 1024; CHECK-NEXT: entry: 1025; CHECK-NEXT: [[IN_RANGE:%.*]] = icmp ult i16 [[N:%.*]], 256 1026; CHECK-NEXT: br i1 [[IN_RANGE]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] 1027; CHECK: for.body.preheader: 1028; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[N]] to i8 1029; CHECK-NEXT: br label [[FOR_BODY:%.*]] 1030; CHECK: for.body: 1031; CHECK-NEXT: [[IV:%.*]] = phi i8 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] 1032; CHECK-NEXT: [[IV_NEXT]] = add nuw i8 [[IV]], 1 1033; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[IV_NEXT]], [[TMP0]] 1034; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 1035; CHECK: for.end.loopexit: 1036; CHECK-NEXT: br label [[FOR_END]] 1037; CHECK: for.end: 1038; CHECK-NEXT: ret void 1039; 1040entry: 1041 %in_range = icmp ult i16 %n, 256 1042 br i1 %in_range, label %for.body, label %for.end 1043 1044for.body: ; preds = %entry, %for.body 1045 %iv = phi i8 [ %iv.next, %for.body ], [ 0, %entry ] 1046 %iv.next = add i8 %iv, 1 1047 %zext = zext i8 %iv.next to i16 1048 %cmp = icmp slt i16 %zext, %n 1049 br i1 %cmp, label %for.body, label %for.end 1050 1051for.end: ; preds = %for.body, %entry 1052 ret void 1053} 1054 1055define i8 @test_drop_icmp_samesign(i1 %cond, i32 range(i32 0, 32) %x) { 1056; CHECK-LABEL: @test_drop_icmp_samesign( 1057; CHECK-NEXT: entry: 1058; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY_PREHEADER:%.*]], label [[ELSE:%.*]] 1059; CHECK: for.body.preheader: 1060; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X:%.*]] to i8 1061; CHECK-NEXT: br label [[FOR_BODY:%.*]] 1062; CHECK: else: 1063; CHECK-NEXT: [[CALL1:%.*]] = call i8 @callee() 1064; CHECK-NEXT: br label [[EXIT:%.*]] 1065; CHECK: for.body: 1066; CHECK-NEXT: [[CALL2:%.*]] = call i8 @callee() 1067; CHECK-NEXT: [[COND2:%.*]] = icmp ugt i8 [[TMP0]], [[CALL2]] 1068; CHECK-NEXT: br i1 [[COND2]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] 1069; CHECK: exit.loopexit: 1070; CHECK-NEXT: [[CALL2_LCSSA:%.*]] = phi i8 [ [[CALL2]], [[FOR_BODY]] ] 1071; CHECK-NEXT: br label [[EXIT]] 1072; CHECK: exit: 1073; CHECK-NEXT: [[RES:%.*]] = phi i8 [ [[CALL1]], [[ELSE]] ], [ [[CALL2_LCSSA]], [[EXIT_LOOPEXIT]] ] 1074; CHECK-NEXT: ret i8 [[RES]] 1075; 1076entry: 1077 br i1 %cond, label %for.body, label %else 1078 1079else: 1080 %call1 = call i8 @callee() 1081 br label %exit 1082 1083for.body: 1084 %call2 = call i8 @callee() 1085 %ext = zext i8 %call2 to i32 1086 %cond2 = icmp samesign ugt i32 %x, %ext 1087 br i1 %cond2, label %for.body, label %exit 1088 1089exit: 1090 %res = phi i8 [ %call1, %else ], [ %call2, %for.body ] 1091 ret i8 %res 1092} 1093 1094declare i8 @callee() 1095