1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=indvars -S < %s | FileCheck %s 3 4; Check that we are able to remove the range check basing on the following facts: 5; 0 <= len <= MAX_INT [1]; 6; iv starts from len and goes down stopping at zero and [1], therefore 7; 0 <= iv <= len [2]; 8; 3. In range_check_block, iv != 0 and [2], therefore 9; 1 <= iv <= len [3]; 10; 4. iv.next = iv - 1 and [3], therefore 11; 0 <= iv.next < len. 12define void @test_predicated_simple_unsigned(ptr %p, ptr %arr) { 13; CHECK-LABEL: @test_predicated_simple_unsigned( 14; CHECK-NEXT: preheader: 15; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0:![0-9]+]] 16; CHECK-NEXT: br label [[LOOP:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 19; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 20; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 21; CHECK: range_check_block: 22; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1 23; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]] 24; CHECK: backedge: 25; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 26; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 27; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 28; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 29; CHECK: exit: 30; CHECK-NEXT: ret void 31; CHECK: fail: 32; CHECK-NEXT: unreachable 33; 34preheader: 35 %len = load i32, ptr %p, !range !0 36 br label %loop 37 38loop: 39 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge] 40 %zero_cond = icmp eq i32 %iv, 0 41 br i1 %zero_cond, label %exit, label %range_check_block 42 43range_check_block: 44 %iv.next = sub i32 %iv, 1 45 %range_check = icmp ult i32 %iv.next, %len 46 br i1 %range_check, label %backedge, label %fail 47 48backedge: 49 %el.ptr = getelementptr i32, ptr %p, i32 %iv 50 %el = load i32, ptr %el.ptr 51 %loop.cond = icmp eq i32 %el, 0 52 br i1 %loop.cond, label %loop, label %exit 53 54exit: 55 ret void 56 57fail: 58 unreachable 59} 60 61define void @test_predicated_simple_signed(ptr %p, ptr %arr) { 62; CHECK-LABEL: @test_predicated_simple_signed( 63; CHECK-NEXT: preheader: 64; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0]] 65; CHECK-NEXT: br label [[LOOP:%.*]] 66; CHECK: loop: 67; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 68; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 69; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 70; CHECK: range_check_block: 71; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1 72; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]] 73; CHECK: backedge: 74; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 75; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 76; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 77; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 78; CHECK: exit: 79; CHECK-NEXT: ret void 80; CHECK: fail: 81; CHECK-NEXT: unreachable 82; 83preheader: 84 %len = load i32, ptr %p, !range !0 85 br label %loop 86 87loop: 88 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge] 89 %zero_cond = icmp eq i32 %iv, 0 90 br i1 %zero_cond, label %exit, label %range_check_block 91 92range_check_block: 93 %iv.next = sub i32 %iv, 1 94 %range_check = icmp slt i32 %iv.next, %len 95 br i1 %range_check, label %backedge, label %fail 96 97backedge: 98 %el.ptr = getelementptr i32, ptr %p, i32 %iv 99 %el = load i32, ptr %el.ptr 100 %loop.cond = icmp eq i32 %el, 0 101 br i1 %loop.cond, label %loop, label %exit 102 103exit: 104 ret void 105 106fail: 107 unreachable 108} 109 110; Cannot remove checks because the range check fails on the last iteration. 111define void @predicated_outside_loop_signed_neg(i32 %arg) nounwind #0 { 112; CHECK-LABEL: @predicated_outside_loop_signed_neg( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 115; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 116; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] 117; CHECK: outer.preheader: 118; CHECK-NEXT: br label [[OUTER:%.*]] 119; CHECK: outer: 120; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 121; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 122; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 123; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 124; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 125; CHECK: inner.ph: 126; CHECK-NEXT: br label [[INNER:%.*]] 127; CHECK: inner: 128; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 129; CHECK: outer.inc.loopexit: 130; CHECK-NEXT: br label [[OUTER_INC]] 131; CHECK: outer.inc: 132; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 133; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] 134; CHECK: exit.loopexit: 135; CHECK-NEXT: br label [[EXIT]] 136; CHECK: exit: 137; CHECK-NEXT: ret void 138; 139entry: 140 %sub1 = sub nsw i32 %arg, 1 141 %cmp1 = icmp slt i32 0, %sub1 142 br i1 %cmp1, label %outer, label %exit 143 144outer: 145 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 146 %sub2 = sub nsw i32 %arg, %i 147 %sub3 = sub nsw i32 %sub2, 1 148 %cmp2 = icmp slt i32 0, %sub3 149 br i1 %cmp2, label %inner.ph, label %outer.inc 150 151inner.ph: 152 br label %inner 153 154inner: 155 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 156 %j.inc = add nsw i32 %j, 1 157 %cmp3 = icmp slt i32 %j.inc, %sub3 158 br i1 %cmp3, label %inner, label %outer.inc 159 160outer.inc: 161 %i.inc = add nsw i32 %i, 1 162 %cmp4 = icmp slt i32 %i.inc, %arg 163 br i1 %cmp4, label %outer, label %exit 164 165exit: 166 ret void 167} 168 169; Range check can be removed. 170define void @predicated_outside_loop_signed_pos(i32 %arg) nounwind #0 { 171; CHECK-LABEL: @predicated_outside_loop_signed_pos( 172; CHECK-NEXT: entry: 173; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 174; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 175; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] 176; CHECK: outer.preheader: 177; CHECK-NEXT: br label [[OUTER:%.*]] 178; CHECK: outer: 179; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 180; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 181; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 182; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 183; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 184; CHECK: inner.ph: 185; CHECK-NEXT: br label [[INNER:%.*]] 186; CHECK: inner: 187; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 188; CHECK: outer.inc.loopexit: 189; CHECK-NEXT: br label [[OUTER_INC]] 190; CHECK: outer.inc: 191; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 192; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] 193; CHECK: exit.loopexit: 194; CHECK-NEXT: br label [[EXIT]] 195; CHECK: exit: 196; CHECK-NEXT: ret void 197; 198entry: 199 %sub1 = sub nsw i32 %arg, 1 200 %cmp1 = icmp slt i32 0, %sub1 201 br i1 %cmp1, label %outer, label %exit 202 203outer: 204 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 205 %sub2 = sub nsw i32 %arg, %i 206 %sub3 = sub nsw i32 %sub2, 1 207 %cmp2 = icmp slt i32 0, %sub3 208 br i1 %cmp2, label %inner.ph, label %outer.inc 209 210inner.ph: 211 br label %inner 212 213inner: 214 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 215 %j.inc = add nsw i32 %j, 1 216 %cmp3 = icmp slt i32 %j.inc, %sub3 217 br i1 %cmp3, label %inner, label %outer.inc 218 219outer.inc: 220 %i.inc = add nsw i32 %i, 1 221 %cmp4 = icmp slt i32 %i.inc, %sub1 222 br i1 %cmp4, label %outer, label %exit 223 224exit: 225 ret void 226} 227 228define void @predicated_outside_loop_unsigned(i32 %arg) nounwind #0 { 229; CHECK-LABEL: @predicated_outside_loop_unsigned( 230; CHECK-NEXT: entry: 231; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 232; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 233; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]] 234; CHECK: outer.preheader: 235; CHECK-NEXT: br label [[OUTER:%.*]] 236; CHECK: outer: 237; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 238; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 239; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 240; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]] 241; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 242; CHECK: inner.ph: 243; CHECK-NEXT: br label [[INNER:%.*]] 244; CHECK: inner: 245; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 246; CHECK: outer.inc.loopexit: 247; CHECK-NEXT: br label [[OUTER_INC]] 248; CHECK: outer.inc: 249; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 250; CHECK-NEXT: br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]] 251; CHECK: exit.loopexit: 252; CHECK-NEXT: br label [[EXIT]] 253; CHECK: exit: 254; CHECK-NEXT: ret void 255; 256entry: 257 %sub1 = sub nsw i32 %arg, 1 258 %cmp1 = icmp slt i32 0, %sub1 259 br i1 %cmp1, label %outer, label %exit 260 261outer: 262 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 263 %sub2 = sub nsw i32 %arg, %i 264 %sub3 = sub nsw i32 %sub2, 1 265 %cmp2 = icmp ult i32 0, %sub3 266 br i1 %cmp2, label %inner.ph, label %outer.inc 267 268inner.ph: 269 br label %inner 270 271inner: 272 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 273 %j.inc = add nsw i32 %j, 1 274 %cmp3 = icmp slt i32 %j.inc, %sub3 275 br i1 %cmp3, label %inner, label %outer.inc 276 277outer.inc: 278 %i.inc = add nsw i32 %i, 1 279 %cmp4 = icmp slt i32 %i.inc, %arg 280 br i1 %cmp4, label %outer, label %exit 281 282exit: 283 ret void 284} 285 286; Cannot remove checks because the range check fails on the last iteration. 287define void @predicated_inside_loop_signed_neg(i32 %arg) nounwind #0 { 288; CHECK-LABEL: @predicated_inside_loop_signed_neg( 289; CHECK-NEXT: entry: 290; CHECK-NEXT: br label [[OUTER:%.*]] 291; CHECK: outer: 292; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ] 293; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 294; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 295; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]] 296; CHECK: guarded: 297; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 298; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 299; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 300; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 301; CHECK: inner.ph: 302; CHECK-NEXT: br label [[INNER:%.*]] 303; CHECK: inner: 304; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 305; CHECK: outer.inc.loopexit: 306; CHECK-NEXT: br label [[OUTER_INC]] 307; CHECK: outer.inc: 308; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 309; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]] 310; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]] 311; CHECK: exit: 312; CHECK-NEXT: ret void 313; 314entry: 315 br label %outer 316 317outer: 318 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 319 %sub1 = sub nsw i32 %arg, 1 320 %cmp1 = icmp slt i32 0, %sub1 321 br i1 %cmp1, label %guarded, label %exit 322 323guarded: 324 %sub2 = sub nsw i32 %arg, %i 325 %sub3 = sub nsw i32 %sub2, 1 326 %cmp2 = icmp slt i32 0, %sub3 327 br i1 %cmp2, label %inner.ph, label %outer.inc 328 329inner.ph: 330 br label %inner 331 332inner: 333 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 334 %j.inc = add nsw i32 %j, 1 335 %cmp3 = icmp slt i32 %j.inc, %sub3 336 br i1 %cmp3, label %inner, label %outer.inc 337 338outer.inc: 339 %i.inc = add nsw i32 %i, 1 340 %cmp4 = icmp slt i32 %i.inc, %arg 341 br i1 %cmp4, label %outer, label %exit 342 343exit: 344 ret void 345} 346 347; Range check can be trivially removed. 348define void @predicated_inside_loop_signed_pos(i32 %arg) nounwind #0 { 349; CHECK-LABEL: @predicated_inside_loop_signed_pos( 350; CHECK-NEXT: entry: 351; CHECK-NEXT: br label [[OUTER:%.*]] 352; CHECK: outer: 353; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ] 354; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 355; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 356; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]] 357; CHECK: guarded: 358; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 359; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 360; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]] 361; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 362; CHECK: inner.ph: 363; CHECK-NEXT: br label [[INNER:%.*]] 364; CHECK: inner: 365; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 366; CHECK: outer.inc.loopexit: 367; CHECK-NEXT: br label [[OUTER_INC]] 368; CHECK: outer.inc: 369; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 370; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[SUB1]] 371; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]] 372; CHECK: exit: 373; CHECK-NEXT: ret void 374; 375entry: 376 br label %outer 377 378outer: 379 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 380 %sub1 = sub nsw i32 %arg, 1 381 %cmp1 = icmp slt i32 0, %sub1 382 br i1 %cmp1, label %guarded, label %exit 383 384guarded: 385 %sub2 = sub nsw i32 %arg, %i 386 %sub3 = sub nsw i32 %sub2, 1 387 %cmp2 = icmp slt i32 0, %sub3 388 br i1 %cmp2, label %inner.ph, label %outer.inc 389 390inner.ph: 391 br label %inner 392 393inner: 394 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 395 %j.inc = add nsw i32 %j, 1 396 %cmp3 = icmp slt i32 %j.inc, %sub3 397 br i1 %cmp3, label %inner, label %outer.inc 398 399outer.inc: 400 %i.inc = add nsw i32 %i, 1 401 %cmp4 = icmp slt i32 %i.inc, %sub1 402 br i1 %cmp4, label %outer, label %exit 403 404exit: 405 ret void 406} 407 408define void @predicated_inside_loop_unsigned(i32 %arg) nounwind #0 { 409; CHECK-LABEL: @predicated_inside_loop_unsigned( 410; CHECK-NEXT: entry: 411; CHECK-NEXT: br label [[OUTER:%.*]] 412; CHECK: outer: 413; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ] 414; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1 415; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]] 416; CHECK-NEXT: br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]] 417; CHECK: guarded: 418; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]] 419; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1 420; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]] 421; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]] 422; CHECK: inner.ph: 423; CHECK-NEXT: br label [[INNER:%.*]] 424; CHECK: inner: 425; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]] 426; CHECK: outer.inc.loopexit: 427; CHECK-NEXT: br label [[OUTER_INC]] 428; CHECK: outer.inc: 429; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1 430; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]] 431; CHECK-NEXT: br i1 [[CMP4]], label [[OUTER]], label [[EXIT]] 432; CHECK: exit: 433; CHECK-NEXT: ret void 434; 435entry: 436 br label %outer 437 438outer: 439 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] 440 %sub1 = sub nsw i32 %arg, 1 441 %cmp1 = icmp slt i32 0, %sub1 442 br i1 %cmp1, label %guarded, label %exit 443 444guarded: 445 %sub2 = sub nsw i32 %arg, %i 446 %sub3 = sub nsw i32 %sub2, 1 447 %cmp2 = icmp ult i32 0, %sub3 448 br i1 %cmp2, label %inner.ph, label %outer.inc 449 450inner.ph: 451 br label %inner 452 453inner: 454 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] 455 %j.inc = add nsw i32 %j, 1 456 %cmp3 = icmp slt i32 %j.inc, %sub3 457 br i1 %cmp3, label %inner, label %outer.inc 458 459outer.inc: 460 %i.inc = add nsw i32 %i, 1 461 %cmp4 = icmp slt i32 %i.inc, %arg 462 br i1 %cmp4, label %outer, label %exit 463 464exit: 465 ret void 466} 467 468define void @test_can_predicate_simple_unsigned(ptr %p, ptr %arr) { 469; CHECK-LABEL: @test_can_predicate_simple_unsigned( 470; CHECK-NEXT: preheader: 471; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 472; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1 473; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]] 474; CHECK-NEXT: br label [[LOOP:%.*]] 475; CHECK: loop: 476; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 477; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 478; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 479; CHECK: range_check_block: 480; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 481; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]] 482; CHECK: backedge: 483; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 484; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 485; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 486; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 487; CHECK: exit: 488; CHECK-NEXT: ret void 489; CHECK: fail: 490; CHECK-NEXT: unreachable 491; 492preheader: 493 %len = load i32, ptr %p 494 br label %loop 495 496loop: 497 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge] 498 %zero_cond = icmp eq i32 %iv, 0 499 br i1 %zero_cond, label %exit, label %range_check_block 500 501range_check_block: 502 %iv.next = sub i32 %iv, 1 503 %range_check = icmp ult i32 %iv.next, %len 504 br i1 %range_check, label %backedge, label %fail 505 506backedge: 507 %el.ptr = getelementptr i32, ptr %p, i32 %iv 508 %el = load i32, ptr %el.ptr 509 %loop.cond = icmp eq i32 %el, 0 510 br i1 %loop.cond, label %loop, label %exit 511 512exit: 513 ret void 514 515fail: 516 unreachable 517} 518 519define void @test_can_predicate_simple_unsigned_inverted(ptr %p, ptr %arr) { 520; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted( 521; CHECK-NEXT: preheader: 522; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 523; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1 524; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]] 525; CHECK-NEXT: br label [[LOOP:%.*]] 526; CHECK: loop: 527; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 528; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 529; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 530; CHECK: range_check_block: 531; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 532; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]] 533; CHECK: backedge: 534; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 535; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 536; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 537; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 538; CHECK: exit: 539; CHECK-NEXT: ret void 540; CHECK: fail: 541; CHECK-NEXT: unreachable 542; 543preheader: 544 %len = load i32, ptr %p 545 br label %loop 546 547loop: 548 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge] 549 %zero_cond = icmp eq i32 %iv, 0 550 br i1 %zero_cond, label %exit, label %range_check_block 551 552range_check_block: 553 %iv.next = sub i32 %iv, 1 554 %range_check = icmp uge i32 %iv.next, %len 555 br i1 %range_check, label %fail, label %backedge 556 557backedge: 558 %el.ptr = getelementptr i32, ptr %p, i32 %iv 559 %el = load i32, ptr %el.ptr 560 %loop.cond = icmp eq i32 %el, 0 561 br i1 %loop.cond, label %loop, label %exit 562 563exit: 564 ret void 565 566fail: 567 unreachable 568} 569 570 571define void @test_can_predicate_simple_signed(ptr %p, ptr %arr) { 572; CHECK-LABEL: @test_can_predicate_simple_signed( 573; CHECK-NEXT: preheader: 574; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 575; CHECK-NEXT: br label [[LOOP:%.*]] 576; CHECK: loop: 577; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 578; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 579; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 580; CHECK: range_check_block: 581; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 582; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]] 583; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]] 584; CHECK: backedge: 585; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 586; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 587; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 588; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 589; CHECK: exit: 590; CHECK-NEXT: ret void 591; CHECK: fail: 592; CHECK-NEXT: unreachable 593; 594preheader: 595 %len = load i32, ptr %p 596 br label %loop 597 598loop: 599 %iv = phi i32 [%len, %preheader], [%iv.next, %backedge] 600 %zero_cond = icmp eq i32 %iv, 0 601 br i1 %zero_cond, label %exit, label %range_check_block 602 603range_check_block: 604 %iv.next = sub i32 %iv, 1 605 %range_check = icmp slt i32 %iv.next, %len 606 br i1 %range_check, label %backedge, label %fail 607 608backedge: 609 %el.ptr = getelementptr i32, ptr %p, i32 %iv 610 %el = load i32, ptr %el.ptr 611 %loop.cond = icmp eq i32 %el, 0 612 br i1 %loop.cond, label %loop, label %exit 613 614exit: 615 ret void 616 617fail: 618 unreachable 619} 620 621define void @test_can_predicate_trunc_unsigned(ptr %p, ptr %arr) { 622; CHECK-LABEL: @test_can_predicate_trunc_unsigned( 623; CHECK-NEXT: preheader: 624; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 625; CHECK-NEXT: [[START:%.*]] = zext i32 [[LEN]] to i64 626; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1 627; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]] 628; CHECK-NEXT: br label [[LOOP:%.*]] 629; CHECK: loop: 630; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 631; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0 632; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 633; CHECK: range_check_block: 634; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i64 [[IV]], 1 635; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]] 636; CHECK: backedge: 637; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]] 638; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 639; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 640; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 641; CHECK: exit: 642; CHECK-NEXT: ret void 643; CHECK: fail: 644; CHECK-NEXT: unreachable 645; 646preheader: 647 %len = load i32, ptr %p 648 %start = zext i32 %len to i64 649 br label %loop 650 651loop: 652 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge] 653 %zero_cond = icmp eq i64 %iv, 0 654 br i1 %zero_cond, label %exit, label %range_check_block 655 656range_check_block: 657 %iv.next = sub i64 %iv, 1 658 %narrow = trunc i64 %iv.next to i32 659 %range_check = icmp ult i32 %narrow, %len 660 br i1 %range_check, label %backedge, label %fail 661 662backedge: 663 %el.ptr = getelementptr i32, ptr %arr, i64 %iv 664 %el = load i32, ptr %el.ptr 665 %loop.cond = icmp eq i32 %el, 0 666 br i1 %loop.cond, label %loop, label %exit 667 668exit: 669 ret void 670 671fail: 672 unreachable 673} 674 675define void @test_can_predicate_trunc_unsigned_inverted(ptr %p, ptr %arr) { 676; CHECK-LABEL: @test_can_predicate_trunc_unsigned_inverted( 677; CHECK-NEXT: preheader: 678; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 679; CHECK-NEXT: [[START:%.*]] = zext i32 [[LEN]] to i64 680; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LEN]], -1 681; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]] 682; CHECK-NEXT: br label [[LOOP:%.*]] 683; CHECK: loop: 684; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 685; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0 686; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 687; CHECK: range_check_block: 688; CHECK-NEXT: [[IV_NEXT]] = sub nuw nsw i64 [[IV]], 1 689; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]] 690; CHECK: backedge: 691; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]] 692; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 693; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 694; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 695; CHECK: exit: 696; CHECK-NEXT: ret void 697; CHECK: fail: 698; CHECK-NEXT: unreachable 699; 700preheader: 701 %len = load i32, ptr %p 702 %start = zext i32 %len to i64 703 br label %loop 704 705loop: 706 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge] 707 %zero_cond = icmp eq i64 %iv, 0 708 br i1 %zero_cond, label %exit, label %range_check_block 709 710range_check_block: 711 %iv.next = sub i64 %iv, 1 712 %narrow = trunc i64 %iv.next to i32 713 %range_check = icmp uge i32 %narrow, %len 714 br i1 %range_check, label %fail, label %backedge 715 716backedge: 717 %el.ptr = getelementptr i32, ptr %arr, i64 %iv 718 %el = load i32, ptr %el.ptr 719 %loop.cond = icmp eq i32 %el, 0 720 br i1 %loop.cond, label %loop, label %exit 721 722exit: 723 ret void 724 725fail: 726 unreachable 727} 728 729define void @test_can_predicate_trunc_unsigned_different_start_and_len(ptr %p, i64 %start, ptr %arr) { 730; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len( 731; CHECK-NEXT: preheader: 732; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 733; CHECK-NEXT: br label [[LOOP:%.*]] 734; CHECK: loop: 735; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 736; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0 737; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 738; CHECK: range_check_block: 739; CHECK-NEXT: [[IV_NEXT]] = sub nuw i64 [[IV]], 1 740; CHECK-NEXT: [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32 741; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[NARROW]], [[LEN]] 742; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]] 743; CHECK: backedge: 744; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]] 745; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 746; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 747; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 748; CHECK: exit: 749; CHECK-NEXT: ret void 750; CHECK: fail: 751; CHECK-NEXT: unreachable 752; 753preheader: 754 %len = load i32, ptr %p 755 br label %loop 756 757loop: 758 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge] 759 %zero_cond = icmp eq i64 %iv, 0 760 br i1 %zero_cond, label %exit, label %range_check_block 761 762range_check_block: 763 %iv.next = sub i64 %iv, 1 764 %narrow = trunc i64 %iv.next to i32 765 %range_check = icmp ult i32 %narrow, %len 766 br i1 %range_check, label %backedge, label %fail 767 768backedge: 769 %el.ptr = getelementptr i32, ptr %arr, i64 %iv 770 %el = load i32, ptr %el.ptr 771 %loop.cond = icmp eq i32 %el, 0 772 br i1 %loop.cond, label %loop, label %exit 773 774exit: 775 ret void 776 777fail: 778 unreachable 779} 780 781define void @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(ptr %p, i64 %start, ptr %arr) { 782; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len_inverted( 783; CHECK-NEXT: preheader: 784; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 785; CHECK-NEXT: br label [[LOOP:%.*]] 786; CHECK: loop: 787; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 788; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0 789; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 790; CHECK: range_check_block: 791; CHECK-NEXT: [[IV_NEXT]] = sub nuw i64 [[IV]], 1 792; CHECK-NEXT: [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32 793; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp uge i32 [[NARROW]], [[LEN]] 794; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[FAIL:%.*]], label [[BACKEDGE]] 795; CHECK: backedge: 796; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]] 797; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 798; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 799; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 800; CHECK: exit: 801; CHECK-NEXT: ret void 802; CHECK: fail: 803; CHECK-NEXT: unreachable 804; 805preheader: 806 %len = load i32, ptr %p 807 br label %loop 808 809loop: 810 %iv = phi i64 [%start, %preheader], [%iv.next, %backedge] 811 %zero_cond = icmp eq i64 %iv, 0 812 br i1 %zero_cond, label %exit, label %range_check_block 813 814range_check_block: 815 %iv.next = sub i64 %iv, 1 816 %narrow = trunc i64 %iv.next to i32 817 %range_check = icmp uge i32 %narrow, %len 818 br i1 %range_check, label %fail, label %backedge 819 820backedge: 821 %el.ptr = getelementptr i32, ptr %arr, i64 %iv 822 %el = load i32, ptr %el.ptr 823 %loop.cond = icmp eq i32 %el, 0 824 br i1 %loop.cond, label %loop, label %exit 825 826exit: 827 ret void 828 829fail: 830 unreachable 831} 832 833define void @test_can_predicate_simple_unsigned_different_start(i32 %start, ptr %p, ptr %arr) { 834; CHECK-LABEL: @test_can_predicate_simple_unsigned_different_start( 835; CHECK-NEXT: preheader: 836; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 837; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1 838; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]] 839; CHECK-NEXT: br label [[LOOP:%.*]] 840; CHECK: loop: 841; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 842; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 843; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 844; CHECK: range_check_block: 845; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 846; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]] 847; CHECK: backedge: 848; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 849; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 850; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 851; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 852; CHECK: exit: 853; CHECK-NEXT: ret void 854; CHECK: fail: 855; CHECK-NEXT: unreachable 856; 857preheader: 858 %len = load i32, ptr %p 859 br label %loop 860 861loop: 862 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge] 863 %zero_cond = icmp eq i32 %iv, 0 864 br i1 %zero_cond, label %exit, label %range_check_block 865 866range_check_block: 867 %iv.next = sub i32 %iv, 1 868 %range_check = icmp ult i32 %iv.next, %len 869 br i1 %range_check, label %backedge, label %fail 870 871backedge: 872 %el.ptr = getelementptr i32, ptr %p, i32 %iv 873 %el = load i32, ptr %el.ptr 874 %loop.cond = icmp eq i32 %el, 0 875 br i1 %loop.cond, label %loop, label %exit 876 877exit: 878 ret void 879 880fail: 881 unreachable 882} 883 884define void @test_can_predicate_simple_unsigned_inverted_different_start(i32 %start, ptr %p, ptr %arr) { 885; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted_different_start( 886; CHECK-NEXT: preheader: 887; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 888; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1 889; CHECK-NEXT: [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]] 890; CHECK-NEXT: br label [[LOOP:%.*]] 891; CHECK: loop: 892; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 893; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 894; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 895; CHECK: range_check_block: 896; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 897; CHECK-NEXT: br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]] 898; CHECK: backedge: 899; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 900; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 901; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 902; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 903; CHECK: exit: 904; CHECK-NEXT: ret void 905; CHECK: fail: 906; CHECK-NEXT: unreachable 907; 908preheader: 909 %len = load i32, ptr %p 910 br label %loop 911 912loop: 913 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge] 914 %zero_cond = icmp eq i32 %iv, 0 915 br i1 %zero_cond, label %exit, label %range_check_block 916 917range_check_block: 918 %iv.next = sub i32 %iv, 1 919 %range_check = icmp uge i32 %iv.next, %len 920 br i1 %range_check, label %fail, label %backedge 921 922backedge: 923 %el.ptr = getelementptr i32, ptr %p, i32 %iv 924 %el = load i32, ptr %el.ptr 925 %loop.cond = icmp eq i32 %el, 0 926 br i1 %loop.cond, label %loop, label %exit 927 928exit: 929 ret void 930 931fail: 932 unreachable 933} 934 935 936define void @test_can_predicate_simple_signed_different_start(i32 %start, ptr %p, ptr %arr) { 937; CHECK-LABEL: @test_can_predicate_simple_signed_different_start( 938; CHECK-NEXT: preheader: 939; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4 940; CHECK-NEXT: br label [[LOOP:%.*]] 941; CHECK: loop: 942; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 943; CHECK-NEXT: [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0 944; CHECK-NEXT: br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]] 945; CHECK: range_check_block: 946; CHECK-NEXT: [[IV_NEXT]] = sub nuw i32 [[IV]], 1 947; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]] 948; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]] 949; CHECK: backedge: 950; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]] 951; CHECK-NEXT: [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4 952; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0 953; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]] 954; CHECK: exit: 955; CHECK-NEXT: ret void 956; CHECK: fail: 957; CHECK-NEXT: unreachable 958; 959preheader: 960 %len = load i32, ptr %p 961 br label %loop 962 963loop: 964 %iv = phi i32 [%start, %preheader], [%iv.next, %backedge] 965 %zero_cond = icmp eq i32 %iv, 0 966 br i1 %zero_cond, label %exit, label %range_check_block 967 968range_check_block: 969 %iv.next = sub i32 %iv, 1 970 %range_check = icmp slt i32 %iv.next, %len 971 br i1 %range_check, label %backedge, label %fail 972 973backedge: 974 %el.ptr = getelementptr i32, ptr %p, i32 %iv 975 %el = load i32, ptr %el.ptr 976 %loop.cond = icmp eq i32 %el, 0 977 br i1 %loop.cond, label %loop, label %exit 978 979exit: 980 ret void 981 982fail: 983 unreachable 984} 985 986!0 = !{i32 0, i32 2147483647} 987