1003 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -S -passes=licm -verify-memoryssa < %s | FileCheck %s3 4; x - iv < 4 ==> iv > x - 45define i32 @test_01(ptr %p, ptr %x_p, ptr %length_p) {6; CHECK-LABEL: define i32 @test_017; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {8; CHECK-NEXT: entry:9; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG0:![0-9]+]]10; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]11; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nsw i32 [[X]], 412; CHECK-NEXT: br label [[LOOP:%.*]]13; CHECK: loop:14; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]15; CHECK-NEXT: [[X_CHECK:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_OP]]16; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]17; CHECK: backedge:18; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]19; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 420; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 421; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]22; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]23; CHECK: exit:24; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]25; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]26; CHECK: out_of_bounds:27; CHECK-NEXT: ret i32 -128;29entry:30 %x = load i32, ptr %x_p, !range !031 %length = load i32, ptr %length_p, !range !032 br label %loop33 34loop:35 %iv = phi i32 [0, %entry], [%iv.next, %backedge]36 %arith = sub nsw i32 %x, %iv37 %x_check = icmp slt i32 %arith, 438 br i1 %x_check, label %out_of_bounds, label %backedge39 40backedge:41 %el.ptr = getelementptr i32, ptr %p, i32 %iv42 store i32 1, ptr %el.ptr43 %iv.next = add nuw nsw i32 %iv, 444 %loop_cond = icmp slt i32 %iv.next, %length45 br i1 %loop_cond, label %loop, label %exit46 47exit:48 ret i32 %iv.next49 50out_of_bounds:51 ret i32 -152}53 54define i32 @test_01_unsigned(ptr %p, ptr %x_p, ptr %length_p) {55; CHECK-LABEL: define i32 @test_01_unsigned56; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {57; CHECK-NEXT: entry:58; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG1:![0-9]+]]59; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG2:![0-9]+]]60; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nuw i32 [[X]], 461; CHECK-NEXT: br label [[LOOP:%.*]]62; CHECK: loop:63; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]64; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_OP]]65; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]66; CHECK: backedge:67; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]68; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 469; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 470; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]71; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]72; CHECK: exit:73; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]74; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]75; CHECK: out_of_bounds:76; CHECK-NEXT: ret i32 -177;78entry:79 %x = load i32, ptr %x_p, !range !280 %length = load i32, ptr %length_p, !range !181 br label %loop82 83loop:84 %iv = phi i32 [0, %entry], [%iv.next, %backedge]85 %arith = sub nuw i32 %x, %iv86 %x_check = icmp ult i32 %arith, 487 br i1 %x_check, label %out_of_bounds, label %backedge88 89backedge:90 %el.ptr = getelementptr i32, ptr %p, i32 %iv91 store i32 1, ptr %el.ptr92 %iv.next = add nuw nsw i32 %iv, 493 %loop_cond = icmp ult i32 %iv.next, %length94 br i1 %loop_cond, label %loop, label %exit95 96exit:97 ret i32 %iv.next98 99out_of_bounds:100 ret i32 -1101}102 103; TODO: x - iv < 4 ==> iv > x - 4104define i32 @test_01a(ptr %p, ptr %x_p, ptr %length_p) {105; CHECK-LABEL: define i32 @test_01a106; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {107; CHECK-NEXT: entry:108; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4109; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4110; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp sge i32 [[X]], 0111; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp sge i32 [[LENGTH]], 0112; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]113; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]114; CHECK: loop.preheader:115; CHECK-NEXT: br label [[LOOP:%.*]]116; CHECK: loop:117; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]118; CHECK-NEXT: [[ARITH:%.*]] = sub nsw i32 [[X]], [[IV]]119; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[ARITH]], 4120; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]121; CHECK: backedge:122; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]123; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4124; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4125; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]126; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]127; CHECK: exit:128; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]129; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]130; CHECK: out_of_bounds:131; CHECK-NEXT: ret i32 -1132; CHECK: failed:133; CHECK-NEXT: ret i32 -2134;135entry:136 %x = load i32, ptr %x_p137 %length = load i32, ptr %length_p138 %precond_1 = icmp sge i32 %x, 0139 %precond_2 = icmp sge i32 %length, 0140 %precond = and i1 %precond_1, %precond_2141 br i1 %precond, label %loop, label %failed142 143loop:144 %iv = phi i32 [0, %entry], [%iv.next, %backedge]145 %arith = sub nsw i32 %x, %iv146 %x_check = icmp slt i32 %arith, 4147 br i1 %x_check, label %out_of_bounds, label %backedge148 149backedge:150 %el.ptr = getelementptr i32, ptr %p, i32 %iv151 store i32 1, ptr %el.ptr152 %iv.next = add nuw nsw i32 %iv, 4153 %loop_cond = icmp slt i32 %iv.next, %length154 br i1 %loop_cond, label %loop, label %exit155 156exit:157 ret i32 %iv.next158 159out_of_bounds:160 ret i32 -1161 162failed:163 ret i32 -2164}165 166define i32 @test_01a_unsigned(ptr %p, ptr %x_p, ptr %length_p) {167; CHECK-LABEL: define i32 @test_01a_unsigned168; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {169; CHECK-NEXT: entry:170; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4171; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4172; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp uge i32 [[X]], 0173; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp uge i32 [[LENGTH]], 0174; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]175; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]176; CHECK: loop.preheader:177; CHECK-NEXT: br label [[LOOP:%.*]]178; CHECK: loop:179; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]180; CHECK-NEXT: [[ARITH:%.*]] = sub nuw i32 [[X]], [[IV]]181; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[ARITH]], 4182; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]183; CHECK: backedge:184; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]185; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4186; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4187; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]188; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]189; CHECK: exit:190; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]191; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]192; CHECK: out_of_bounds:193; CHECK-NEXT: ret i32 -1194; CHECK: failed:195; CHECK-NEXT: ret i32 -2196;197entry:198 %x = load i32, ptr %x_p199 %length = load i32, ptr %length_p200 %precond_1 = icmp uge i32 %x, 0201 %precond_2 = icmp uge i32 %length, 0202 %precond = and i1 %precond_1, %precond_2203 br i1 %precond, label %loop, label %failed204 205loop:206 %iv = phi i32 [0, %entry], [%iv.next, %backedge]207 %arith = sub nuw i32 %x, %iv208 %x_check = icmp ult i32 %arith, 4209 br i1 %x_check, label %out_of_bounds, label %backedge210 211backedge:212 %el.ptr = getelementptr i32, ptr %p, i32 %iv213 store i32 1, ptr %el.ptr214 %iv.next = add nuw nsw i32 %iv, 4215 %loop_cond = icmp ult i32 %iv.next, %length216 br i1 %loop_cond, label %loop, label %exit217 218exit:219 ret i32 %iv.next220 221out_of_bounds:222 ret i32 -1223 224failed:225 ret i32 -2226}227 228; Range info is missing for x, cannot prove no-overflow. Should not hoist.229define i32 @test_01_neg(ptr %p, ptr %x_p, ptr %length_p) {230; CHECK-LABEL: define i32 @test_01_neg231; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {232; CHECK-NEXT: entry:233; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4234; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]235; CHECK-NEXT: br label [[LOOP:%.*]]236; CHECK: loop:237; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]238; CHECK-NEXT: [[ARITH:%.*]] = sub nsw i32 [[X]], [[IV]]239; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[ARITH]], 4240; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]241; CHECK: backedge:242; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]243; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4244; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4245; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]246; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]247; CHECK: exit:248; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]249; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]250; CHECK: out_of_bounds:251; CHECK-NEXT: ret i32 -1252;253entry:254 %x = load i32, ptr %x_p255 %length = load i32, ptr %length_p, !range !0256 br label %loop257 258loop:259 %iv = phi i32 [0, %entry], [%iv.next, %backedge]260 %arith = sub nsw i32 %x, %iv261 %x_check = icmp slt i32 %arith, 4262 br i1 %x_check, label %out_of_bounds, label %backedge263 264backedge:265 %el.ptr = getelementptr i32, ptr %p, i32 %iv266 store i32 1, ptr %el.ptr267 %iv.next = add nuw nsw i32 %iv, 4268 %loop_cond = icmp slt i32 %iv.next, %length269 br i1 %loop_cond, label %loop, label %exit270 271exit:272 ret i32 %iv.next273 274out_of_bounds:275 ret i32 -1276}277 278define i32 @test_01_neg_unsigned(ptr %p, ptr %x_p, ptr %length_p) {279; CHECK-LABEL: define i32 @test_01_neg_unsigned280; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {281; CHECK-NEXT: entry:282; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4283; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]284; CHECK-NEXT: br label [[LOOP:%.*]]285; CHECK: loop:286; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]287; CHECK-NEXT: [[ARITH:%.*]] = sub nuw i32 [[X]], [[IV]]288; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[ARITH]], 4289; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]290; CHECK: backedge:291; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]292; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4293; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4294; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]295; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]296; CHECK: exit:297; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]298; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]299; CHECK: out_of_bounds:300; CHECK-NEXT: ret i32 -1301;302entry:303 %x = load i32, ptr %x_p304 %length = load i32, ptr %length_p, !range !0305 br label %loop306 307loop:308 %iv = phi i32 [0, %entry], [%iv.next, %backedge]309 %arith = sub nuw i32 %x, %iv310 %x_check = icmp ult i32 %arith, 4311 br i1 %x_check, label %out_of_bounds, label %backedge312 313backedge:314 %el.ptr = getelementptr i32, ptr %p, i32 %iv315 store i32 1, ptr %el.ptr316 %iv.next = add nuw nsw i32 %iv, 4317 %loop_cond = icmp ult i32 %iv.next, %length318 br i1 %loop_cond, label %loop, label %exit319 320exit:321 ret i32 %iv.next322 323out_of_bounds:324 ret i32 -1325}326 327; x + iv < 4 ==> iv < 4 - x328define i32 @test_02(ptr %p, ptr %x_p, ptr %length_p) {329; CHECK-LABEL: define i32 @test_02330; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {331; CHECK-NEXT: entry:332; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG0]]333; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]334; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nsw i32 4, [[X]]335; CHECK-NEXT: br label [[LOOP:%.*]]336; CHECK: loop:337; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]338; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_OP]]339; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]340; CHECK: backedge:341; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]342; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4343; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4344; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]345; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]346; CHECK: exit:347; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]348; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]349; CHECK: out_of_bounds:350; CHECK-NEXT: ret i32 -1351;352entry:353 %x = load i32, ptr %x_p, !range !0354 %length = load i32, ptr %length_p, !range !0355 br label %loop356 357loop:358 %iv = phi i32 [0, %entry], [%iv.next, %backedge]359 %arith = add nsw i32 %x, %iv360 %x_check = icmp slt i32 %arith, 4361 br i1 %x_check, label %out_of_bounds, label %backedge362 363backedge:364 %el.ptr = getelementptr i32, ptr %p, i32 %iv365 store i32 1, ptr %el.ptr366 %iv.next = add nuw nsw i32 %iv, 4367 %loop_cond = icmp slt i32 %iv.next, %length368 br i1 %loop_cond, label %loop, label %exit369 370exit:371 ret i32 %iv.next372 373out_of_bounds:374 ret i32 -1375}376 377define i32 @test_02_unsigned(ptr %p, ptr %x_p, ptr %length_p) {378; CHECK-LABEL: define i32 @test_02_unsigned379; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {380; CHECK-NEXT: entry:381; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG3:![0-9]+]]382; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG2]]383; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nuw i32 4, [[X]]384; CHECK-NEXT: br label [[LOOP:%.*]]385; CHECK: loop:386; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]387; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_OP]]388; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]389; CHECK: backedge:390; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]391; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4392; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4393; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]394; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]395; CHECK: exit:396; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]397; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]398; CHECK: out_of_bounds:399; CHECK-NEXT: ret i32 -1400;401entry:402 %x = load i32, ptr %x_p, !range !3403 %length = load i32, ptr %length_p, !range !1404 br label %loop405 406loop:407 %iv = phi i32 [0, %entry], [%iv.next, %backedge]408 %arith = add nuw i32 %x, %iv409 %x_check = icmp ult i32 %arith, 4410 br i1 %x_check, label %out_of_bounds, label %backedge411 412backedge:413 %el.ptr = getelementptr i32, ptr %p, i32 %iv414 store i32 1, ptr %el.ptr415 %iv.next = add nuw nsw i32 %iv, 4416 %loop_cond = icmp ult i32 %iv.next, %length417 br i1 %loop_cond, label %loop, label %exit418 419exit:420 ret i32 %iv.next421 422out_of_bounds:423 ret i32 -1424}425 426; TODO: x + iv < 4 ==> iv < 4 - x427define i32 @test_02a(ptr %p, ptr %x_p, ptr %length_p) {428; CHECK-LABEL: define i32 @test_02a429; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {430; CHECK-NEXT: entry:431; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4432; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4433; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp sge i32 [[X]], 0434; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp sge i32 [[LENGTH]], 0435; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]436; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]437; CHECK: loop.preheader:438; CHECK-NEXT: br label [[LOOP:%.*]]439; CHECK: loop:440; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]441; CHECK-NEXT: [[ARITH:%.*]] = add nsw i32 [[X]], [[IV]]442; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[ARITH]], 4443; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]444; CHECK: backedge:445; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]446; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4447; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4448; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]449; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]450; CHECK: exit:451; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]452; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]453; CHECK: out_of_bounds:454; CHECK-NEXT: ret i32 -1455; CHECK: failed:456; CHECK-NEXT: ret i32 -2457;458entry:459 %x = load i32, ptr %x_p460 %length = load i32, ptr %length_p461 %precond_1 = icmp sge i32 %x, 0462 %precond_2 = icmp sge i32 %length, 0463 %precond = and i1 %precond_1, %precond_2464 br i1 %precond, label %loop, label %failed465 466loop:467 %iv = phi i32 [0, %entry], [%iv.next, %backedge]468 %arith = add nsw i32 %x, %iv469 %x_check = icmp slt i32 %arith, 4470 br i1 %x_check, label %out_of_bounds, label %backedge471 472backedge:473 %el.ptr = getelementptr i32, ptr %p, i32 %iv474 store i32 1, ptr %el.ptr475 %iv.next = add nuw nsw i32 %iv, 4476 %loop_cond = icmp slt i32 %iv.next, %length477 br i1 %loop_cond, label %loop, label %exit478 479exit:480 ret i32 %iv.next481 482out_of_bounds:483 ret i32 -1484 485failed:486 ret i32 -2487}488 489define i32 @test_02a_unsigned(ptr %p, ptr %x_p, ptr %length_p) {490; CHECK-LABEL: define i32 @test_02a_unsigned491; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {492; CHECK-NEXT: entry:493; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4494; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4495; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp uge i32 [[X]], 0496; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp uge i32 [[LENGTH]], 0497; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]498; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]499; CHECK: loop.preheader:500; CHECK-NEXT: br label [[LOOP:%.*]]501; CHECK: loop:502; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]503; CHECK-NEXT: [[ARITH:%.*]] = add nuw i32 [[X]], [[IV]]504; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[ARITH]], 4505; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]506; CHECK: backedge:507; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]508; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4509; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4510; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]511; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]512; CHECK: exit:513; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]514; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]515; CHECK: out_of_bounds:516; CHECK-NEXT: ret i32 -1517; CHECK: failed:518; CHECK-NEXT: ret i32 -2519;520entry:521 %x = load i32, ptr %x_p522 %length = load i32, ptr %length_p523 %precond_1 = icmp uge i32 %x, 0524 %precond_2 = icmp uge i32 %length, 0525 %precond = and i1 %precond_1, %precond_2526 br i1 %precond, label %loop, label %failed527 528loop:529 %iv = phi i32 [0, %entry], [%iv.next, %backedge]530 %arith = add nuw i32 %x, %iv531 %x_check = icmp ult i32 %arith, 4532 br i1 %x_check, label %out_of_bounds, label %backedge533 534backedge:535 %el.ptr = getelementptr i32, ptr %p, i32 %iv536 store i32 1, ptr %el.ptr537 %iv.next = add nuw nsw i32 %iv, 4538 %loop_cond = icmp ult i32 %iv.next, %length539 br i1 %loop_cond, label %loop, label %exit540 541exit:542 ret i32 %iv.next543 544out_of_bounds:545 ret i32 -1546 547failed:548 ret i32 -2549}550 551; iv - x < 4 ==> iv < 4 + x552define i32 @test_03(ptr %p, ptr %x_p, ptr %length_p) {553; CHECK-LABEL: define i32 @test_03554; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {555; CHECK-NEXT: entry:556; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG2]]557; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]558; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nsw i32 [[X]], 4559; CHECK-NEXT: br label [[LOOP:%.*]]560; CHECK: loop:561; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]562; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_OP]]563; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]564; CHECK: backedge:565; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]566; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4567; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4568; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]569; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]570; CHECK: exit:571; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]572; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]573; CHECK: out_of_bounds:574; CHECK-NEXT: ret i32 -1575;576entry:577 %x = load i32, ptr %x_p, !range !1578 %length = load i32, ptr %length_p, !range !0579 br label %loop580 581loop:582 %iv = phi i32 [0, %entry], [%iv.next, %backedge]583 %arith = sub nsw i32 %iv, %x584 %x_check = icmp slt i32 %arith, 4585 br i1 %x_check, label %out_of_bounds, label %backedge586 587backedge:588 %el.ptr = getelementptr i32, ptr %p, i32 %iv589 store i32 1, ptr %el.ptr590 %iv.next = add nuw nsw i32 %iv, 4591 %loop_cond = icmp slt i32 %iv.next, %length592 br i1 %loop_cond, label %loop, label %exit593 594exit:595 ret i32 %iv.next596 597out_of_bounds:598 ret i32 -1599}600 601define i32 @test_03_unsigned(ptr %p, ptr %x_p, ptr %length_p) {602; CHECK-LABEL: define i32 @test_03_unsigned603; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {604; CHECK-NEXT: entry:605; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG2]]606; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG2]]607; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i32 [[X]], 4608; CHECK-NEXT: br label [[LOOP:%.*]]609; CHECK: loop:610; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]611; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_OP]]612; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]613; CHECK: backedge:614; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]615; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4616; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4617; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]618; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]619; CHECK: exit:620; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]621; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]622; CHECK: out_of_bounds:623; CHECK-NEXT: ret i32 -1624;625entry:626 %x = load i32, ptr %x_p, !range !1627 %length = load i32, ptr %length_p, !range !1628 br label %loop629 630loop:631 %iv = phi i32 [0, %entry], [%iv.next, %backedge]632 %arith = sub nuw i32 %iv, %x633 %x_check = icmp ult i32 %arith, 4634 br i1 %x_check, label %out_of_bounds, label %backedge635 636backedge:637 %el.ptr = getelementptr i32, ptr %p, i32 %iv638 store i32 1, ptr %el.ptr639 %iv.next = add nuw nsw i32 %iv, 4640 %loop_cond = icmp ult i32 %iv.next, %length641 br i1 %loop_cond, label %loop, label %exit642 643exit:644 ret i32 %iv.next645 646out_of_bounds:647 ret i32 -1648}649 650; TODO: iv - x < 4 ==> iv < 4 + x651define i32 @test_03a(ptr %p, ptr %x_p, ptr %length_p) {652; CHECK-LABEL: define i32 @test_03a653; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {654; CHECK-NEXT: entry:655; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4656; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4657; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp ult i32 [[X]], 2147483640658; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp sge i32 [[LENGTH]], 0659; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]660; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]661; CHECK: loop.preheader:662; CHECK-NEXT: br label [[LOOP:%.*]]663; CHECK: loop:664; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]665; CHECK-NEXT: [[ARITH:%.*]] = sub nsw i32 [[IV]], [[X]]666; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[ARITH]], 4667; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]668; CHECK: backedge:669; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]670; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4671; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4672; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]673; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]674; CHECK: exit:675; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]676; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]677; CHECK: out_of_bounds:678; CHECK-NEXT: ret i32 -1679; CHECK: failed:680; CHECK-NEXT: ret i32 -2681;682entry:683 %x = load i32, ptr %x_p684 %length = load i32, ptr %length_p685 %precond_1 = icmp ult i32 %x, 2147483640686 %precond_2 = icmp sge i32 %length, 0687 %precond = and i1 %precond_1, %precond_2688 br i1 %precond, label %loop, label %failed689 690loop:691 %iv = phi i32 [0, %entry], [%iv.next, %backedge]692 %arith = sub nsw i32 %iv, %x693 %x_check = icmp slt i32 %arith, 4694 br i1 %x_check, label %out_of_bounds, label %backedge695 696backedge:697 %el.ptr = getelementptr i32, ptr %p, i32 %iv698 store i32 1, ptr %el.ptr699 %iv.next = add nuw nsw i32 %iv, 4700 %loop_cond = icmp slt i32 %iv.next, %length701 br i1 %loop_cond, label %loop, label %exit702 703exit:704 ret i32 %iv.next705 706out_of_bounds:707 ret i32 -1708 709failed:710 ret i32 -2711}712 713define i32 @test_03a_unsigned(ptr %p, ptr %x_p, ptr %length_p) {714; CHECK-LABEL: define i32 @test_03a_unsigned715; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {716; CHECK-NEXT: entry:717; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4718; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4719; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp ult i32 [[X]], 2147483640720; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp uge i32 [[LENGTH]], 0721; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]722; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]723; CHECK: loop.preheader:724; CHECK-NEXT: br label [[LOOP:%.*]]725; CHECK: loop:726; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]727; CHECK-NEXT: [[ARITH:%.*]] = sub nuw i32 [[IV]], [[X]]728; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[ARITH]], 4729; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]730; CHECK: backedge:731; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]732; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4733; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4734; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]735; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]736; CHECK: exit:737; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]738; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]739; CHECK: out_of_bounds:740; CHECK-NEXT: ret i32 -1741; CHECK: failed:742; CHECK-NEXT: ret i32 -2743;744entry:745 %x = load i32, ptr %x_p746 %length = load i32, ptr %length_p747 %precond_1 = icmp ult i32 %x, 2147483640748 %precond_2 = icmp uge i32 %length, 0749 %precond = and i1 %precond_1, %precond_2750 br i1 %precond, label %loop, label %failed751 752loop:753 %iv = phi i32 [0, %entry], [%iv.next, %backedge]754 %arith = sub nuw i32 %iv, %x755 %x_check = icmp ult i32 %arith, 4756 br i1 %x_check, label %out_of_bounds, label %backedge757 758backedge:759 %el.ptr = getelementptr i32, ptr %p, i32 %iv760 store i32 1, ptr %el.ptr761 %iv.next = add nuw nsw i32 %iv, 4762 %loop_cond = icmp ult i32 %iv.next, %length763 br i1 %loop_cond, label %loop, label %exit764 765exit:766 ret i32 %iv.next767 768out_of_bounds:769 ret i32 -1770 771failed:772 ret i32 -2773}774 775; iv + x < 4 ==> iv < 4 - x776define i32 @test_04(ptr %p, ptr %x_p, ptr %length_p) {777; CHECK-LABEL: define i32 @test_04778; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {779; CHECK-NEXT: entry:780; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG0]]781; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG0]]782; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nsw i32 4, [[X]]783; CHECK-NEXT: br label [[LOOP:%.*]]784; CHECK: loop:785; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]786; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_OP]]787; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]788; CHECK: backedge:789; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]790; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4791; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4792; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]793; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]794; CHECK: exit:795; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]796; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]797; CHECK: out_of_bounds:798; CHECK-NEXT: ret i32 -1799;800entry:801 %x = load i32, ptr %x_p, !range !0802 %length = load i32, ptr %length_p, !range !0803 br label %loop804 805loop:806 %iv = phi i32 [0, %entry], [%iv.next, %backedge]807 %arith = add nsw i32 %iv, %x808 %x_check = icmp slt i32 %arith, 4809 br i1 %x_check, label %out_of_bounds, label %backedge810 811backedge:812 %el.ptr = getelementptr i32, ptr %p, i32 %iv813 store i32 1, ptr %el.ptr814 %iv.next = add nuw nsw i32 %iv, 4815 %loop_cond = icmp slt i32 %iv.next, %length816 br i1 %loop_cond, label %loop, label %exit817 818exit:819 ret i32 %iv.next820 821out_of_bounds:822 ret i32 -1823}824 825define i32 @test_04_unsigned(ptr %p, ptr %x_p, ptr %length_p) {826; CHECK-LABEL: define i32 @test_04_unsigned827; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {828; CHECK-NEXT: entry:829; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4, !range [[RNG3]]830; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4, !range [[RNG2]]831; CHECK-NEXT: [[INVARIANT_OP:%.*]] = sub nuw i32 4, [[X]]832; CHECK-NEXT: br label [[LOOP:%.*]]833; CHECK: loop:834; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]835; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_OP]]836; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]837; CHECK: backedge:838; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]839; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4840; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4841; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]842; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]843; CHECK: exit:844; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]845; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]846; CHECK: out_of_bounds:847; CHECK-NEXT: ret i32 -1848;849entry:850 %x = load i32, ptr %x_p, !range !3851 %length = load i32, ptr %length_p, !range !1852 br label %loop853 854loop:855 %iv = phi i32 [0, %entry], [%iv.next, %backedge]856 %arith = add nuw i32 %iv, %x857 %x_check = icmp ult i32 %arith, 4858 br i1 %x_check, label %out_of_bounds, label %backedge859 860backedge:861 %el.ptr = getelementptr i32, ptr %p, i32 %iv862 store i32 1, ptr %el.ptr863 %iv.next = add nuw nsw i32 %iv, 4864 %loop_cond = icmp ult i32 %iv.next, %length865 br i1 %loop_cond, label %loop, label %exit866 867exit:868 ret i32 %iv.next869 870out_of_bounds:871 ret i32 -1872}873 874; TODO: iv + x < 4 ==> iv < 4 - x875define i32 @test_04a(ptr %p, ptr %x_p, ptr %length_p) {876; CHECK-LABEL: define i32 @test_04a877; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {878; CHECK-NEXT: entry:879; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4880; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4881; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp sge i32 [[X]], 0882; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp sge i32 [[LENGTH]], 0883; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]884; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]885; CHECK: loop.preheader:886; CHECK-NEXT: br label [[LOOP:%.*]]887; CHECK: loop:888; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]889; CHECK-NEXT: [[ARITH:%.*]] = add nsw i32 [[IV]], [[X]]890; CHECK-NEXT: [[X_CHECK:%.*]] = icmp slt i32 [[ARITH]], 4891; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]892; CHECK: backedge:893; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]894; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4895; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4896; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[LENGTH]]897; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]898; CHECK: exit:899; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]900; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]901; CHECK: out_of_bounds:902; CHECK-NEXT: ret i32 -1903; CHECK: failed:904; CHECK-NEXT: ret i32 -2905;906entry:907 %x = load i32, ptr %x_p908 %length = load i32, ptr %length_p909 %precond_1 = icmp sge i32 %x, 0910 %precond_2 = icmp sge i32 %length, 0911 %precond = and i1 %precond_1, %precond_2912 br i1 %precond, label %loop, label %failed913 914loop:915 %iv = phi i32 [0, %entry], [%iv.next, %backedge]916 %arith = add nsw i32 %iv, %x917 %x_check = icmp slt i32 %arith, 4918 br i1 %x_check, label %out_of_bounds, label %backedge919 920backedge:921 %el.ptr = getelementptr i32, ptr %p, i32 %iv922 store i32 1, ptr %el.ptr923 %iv.next = add nuw nsw i32 %iv, 4924 %loop_cond = icmp slt i32 %iv.next, %length925 br i1 %loop_cond, label %loop, label %exit926 927exit:928 ret i32 %iv.next929 930out_of_bounds:931 ret i32 -1932 933failed:934 ret i32 -2935}936 937define i32 @test_04a_unsigned(ptr %p, ptr %x_p, ptr %length_p) {938; CHECK-LABEL: define i32 @test_04a_unsigned939; CHECK-SAME: (ptr [[P:%.*]], ptr [[X_P:%.*]], ptr [[LENGTH_P:%.*]]) {940; CHECK-NEXT: entry:941; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[X_P]], align 4942; CHECK-NEXT: [[LENGTH:%.*]] = load i32, ptr [[LENGTH_P]], align 4943; CHECK-NEXT: [[PRECOND_1:%.*]] = icmp sge i32 [[X]], 0944; CHECK-NEXT: [[PRECOND_2:%.*]] = icmp sge i32 [[LENGTH]], 0945; CHECK-NEXT: [[PRECOND:%.*]] = and i1 [[PRECOND_1]], [[PRECOND_2]]946; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP_PREHEADER:%.*]], label [[FAILED:%.*]]947; CHECK: loop.preheader:948; CHECK-NEXT: br label [[LOOP:%.*]]949; CHECK: loop:950; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]951; CHECK-NEXT: [[ARITH:%.*]] = add nuw i32 [[IV]], [[X]]952; CHECK-NEXT: [[X_CHECK:%.*]] = icmp ult i32 [[ARITH]], 4953; CHECK-NEXT: br i1 [[X_CHECK]], label [[OUT_OF_BOUNDS:%.*]], label [[BACKEDGE]]954; CHECK: backedge:955; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]956; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4957; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4958; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LENGTH]]959; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]960; CHECK: exit:961; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]962; CHECK-NEXT: ret i32 [[IV_NEXT_LCSSA]]963; CHECK: out_of_bounds:964; CHECK-NEXT: ret i32 -1965; CHECK: failed:966; CHECK-NEXT: ret i32 -2967;968entry:969 %x = load i32, ptr %x_p970 %length = load i32, ptr %length_p971 %precond_1 = icmp sge i32 %x, 0972 %precond_2 = icmp sge i32 %length, 0973 %precond = and i1 %precond_1, %precond_2974 br i1 %precond, label %loop, label %failed975 976loop:977 %iv = phi i32 [0, %entry], [%iv.next, %backedge]978 %arith = add nuw i32 %iv, %x979 %x_check = icmp ult i32 %arith, 4980 br i1 %x_check, label %out_of_bounds, label %backedge981 982backedge:983 %el.ptr = getelementptr i32, ptr %p, i32 %iv984 store i32 1, ptr %el.ptr985 %iv.next = add nuw nsw i32 %iv, 4986 %loop_cond = icmp ult i32 %iv.next, %length987 br i1 %loop_cond, label %loop, label %exit988 989exit:990 ret i32 %iv.next991 992out_of_bounds:993 ret i32 -1994 995failed:996 ret i32 -2997}998 999!0 = !{i32 0, i32 2147483648}1000!1 = !{i32 0, i32 2147483640}1001!2 = !{i32 256, i32 32768}1002!3 = !{i32 0, i32 2}1003