brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.8 KiB · d9b868e Raw
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