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