1178 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -verify-loop-info -passes=irce -irce-print-scaled-boundary-range-checks -S < %s 2>&1 | FileCheck %s3 4 5; CHECK: irce: in function test1, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>6; CHECK-NEXT: there is range check with scaled boundary:7; CHECK-NEXT: InductiveRangeCheck:8; CHECK-NEXT: Begin: 0 Step: 1 End: (-1 + (sext i8 %n to i16))<nsw>9; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 010;11; CHECK-NEXT: irce: in function test4, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>12; CHECK-NEXT: there is range check with scaled boundary:13; CHECK-NEXT: InductiveRangeCheck:14; CHECK-NEXT: Begin: 0 Step: 1 End: (-2 + (sext i8 %n to i16))<nsw>15; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 016;17; CHECK-NEXT: irce: in function test_overflow_check_runtime, in Loop at depth 1 containing: %loop<header><exiting>,%inbounds<latch><exiting>18; CHECK-NEXT: there is range check with scaled boundary:19; CHECK-NEXT: InductiveRangeCheck:20; CHECK-NEXT: Begin: 0 Step: 1 End: (3 + (zext i8 %n to i16))<nuw><nsw>21; CHECK-NEXT: CheckUse: br i1 %check, label %inbounds, label %out_of_bounds Operand: 022 23; IV = 0; IV <s limit; IV += 1;24; Check(N - IV >= 2)25; IRCE is allowed.26define i8 @test1(i8 %limit, i8 %n) {27; CHECK-LABEL: define i8 @test128; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {29; CHECK-NEXT: entry:30; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 031; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]32; CHECK: loop.preheader:33; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -134; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], -12835; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)36; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]37; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)38; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)39; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[SMAX2]], 140; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]]41; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i1642; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 12743; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP6]], i16 0)44; CHECK-NEXT: [[TMP7:%.*]] = trunc i16 [[SMIN3]] to i845; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 146; CHECK-NEXT: [[TMP9:%.*]] = mul i8 [[TMP4]], [[TMP8]]47; CHECK-NEXT: [[SMIN4:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP9]])48; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN4]], i8 0)49; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]50; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP_PREHEADER7:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]51; CHECK: loop.preheader7:52; CHECK-NEXT: br label [[LOOP:%.*]]53; CHECK: loop:54; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER7]] ]55; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]56; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 257; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]58; CHECK: inbounds:59; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 160; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]61; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]62; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]63; CHECK: main.exit.selector:64; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]65; CHECK-NEXT: [[IDX_LCSSA6:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]66; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]67; CHECK-NEXT: br i1 [[TMP12]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]68; CHECK: main.pseudo.exit:69; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]70; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]71; CHECK-NEXT: br label [[POSTLOOP:%.*]]72; CHECK: exit.loopexit.loopexit:73; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]74; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]75; CHECK: exit.loopexit:76; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA6]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]77; CHECK-NEXT: br label [[EXIT]]78; CHECK: exit:79; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]80; CHECK-NEXT: ret i8 [[RES]]81; CHECK: out_of_bounds.loopexit:82; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]83; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]84; CHECK: out_of_bounds.loopexit8:85; CHECK-NEXT: [[IDX_LCSSA_PH9:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]86; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]87; CHECK: out_of_bounds:88; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH9]], [[OUT_OF_BOUNDS_LOOPEXIT8]] ]89; CHECK-NEXT: ret i8 [[IDX_LCSSA]]90; CHECK: postloop:91; CHECK-NEXT: br label [[LOOP_POSTLOOP]]92; CHECK: loop.postloop:93; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]94; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]95; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], 296; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]97; CHECK: inbounds.postloop:98; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 199; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]100; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP0:![0-9]+]], !loop_constrainer.loop.clone !5101;102entry:103 %precheck = icmp sgt i8 %limit, 0104 br i1 %precheck, label %loop, label %exit105 106loop:107 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]108 %sub = sub i8 %n, %idx109 %check = icmp sge i8 %sub, 2110 br i1 %check, label %inbounds, label %out_of_bounds111 112inbounds:113 %idx.next = add nuw i8 %idx, 1114 %cmp = icmp slt i8 %idx.next, %limit115 br i1 %cmp, label %loop, label %exit116 117exit:118 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]119 ret i8 %res120 121out_of_bounds:122 ret i8 %idx;123}124 125; IV = 0; IV <s limit; IV += 1;126; Check(N - IV >= 2)127; N is known to be non-negative.128; TODO: IRCE is allowed.129define i8 @test1a(i8 %limit, ptr %p) {130; CHECK-LABEL: define i8 @test1a131; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {132; CHECK-NEXT: entry:133; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6:![0-9]+]]134; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0135; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]136; CHECK: loop.preheader:137; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1138; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)139; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[SMIN]], 1140; CHECK-NEXT: [[TMP2:%.*]] = mul i8 [[TMP0]], [[TMP1]]141; CHECK-NEXT: [[SMIN2:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP2]])142; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN2]], i8 0)143; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]144; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_PREHEADER4:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]145; CHECK: loop.preheader4:146; CHECK-NEXT: br label [[LOOP:%.*]]147; CHECK: loop:148; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER4]] ]149; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]150; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], 2151; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]]152; CHECK: inbounds:153; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1154; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]155; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]156; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]157; CHECK: main.exit.selector:158; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]159; CHECK-NEXT: [[IDX_LCSSA3:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]160; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]161; CHECK-NEXT: br i1 [[TMP5]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]162; CHECK: main.pseudo.exit:163; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]164; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]165; CHECK-NEXT: br label [[POSTLOOP:%.*]]166; CHECK: exit.loopexit.loopexit:167; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]168; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]169; CHECK: exit.loopexit:170; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA3]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]171; CHECK-NEXT: br label [[EXIT]]172; CHECK: exit:173; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]174; CHECK-NEXT: ret i8 [[RES]]175; CHECK: out_of_bounds.loopexit:176; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]177; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]178; CHECK: out_of_bounds.loopexit5:179; CHECK-NEXT: [[IDX_LCSSA_PH6:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]180; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]181; CHECK: out_of_bounds:182; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH6]], [[OUT_OF_BOUNDS_LOOPEXIT5]] ]183; CHECK-NEXT: ret i8 [[IDX_LCSSA]]184; CHECK: postloop:185; CHECK-NEXT: br label [[LOOP_POSTLOOP]]186; CHECK: loop.postloop:187; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]188; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]189; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], 2190; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]191; CHECK: inbounds.postloop:192; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1193; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]194; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !5195;196entry:197 %n = load i8, ptr %p, !range !0198 %precheck = icmp sgt i8 %limit, 0199 br i1 %precheck, label %loop, label %exit200 201loop:202 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]203 %sub = sub i8 %n, %idx204 %check = icmp sge i8 %sub, 2205 br i1 %check, label %inbounds, label %out_of_bounds206 207inbounds:208 %idx.next = add nuw i8 %idx, 1209 %cmp = icmp slt i8 %idx.next, %limit210 br i1 %cmp, label %loop, label %exit211 212exit:213 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]214 ret i8 %res215 216out_of_bounds:217 ret i8 %idx;218}219 220; IV = 0; IV <s limit; IV += 1;221; Check(IV - N <= -2)222; TODO: IRCE is allowed.223define i8 @test2(i8 %limit, i8 %n) {224; CHECK-LABEL: define i8 @test2225; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {226; CHECK-NEXT: entry:227; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0228; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]229; CHECK: loop.preheader:230; CHECK-NEXT: br label [[LOOP:%.*]]231; CHECK: loop:232; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]233; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]234; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[SUB]], -2235; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]236; CHECK: inbounds:237; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1238; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]239; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]240; CHECK: exit.loopexit:241; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]242; CHECK-NEXT: br label [[EXIT]]243; CHECK: exit:244; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]245; CHECK-NEXT: ret i8 [[RES]]246; CHECK: out_of_bounds:247; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]248; CHECK-NEXT: ret i8 [[IDX_LCSSA]]249;250entry:251 %precheck = icmp sgt i8 %limit, 0252 br i1 %precheck, label %loop, label %exit253 254loop:255 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]256 %sub = sub i8 %idx, %n257 %check = icmp sle i8 %sub, -2258 br i1 %check, label %inbounds, label %out_of_bounds259 260inbounds:261 %idx.next = add nuw i8 %idx, 1262 %cmp = icmp slt i8 %idx.next, %limit263 br i1 %cmp, label %loop, label %exit264 265exit:266 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]267 ret i8 %res268 269out_of_bounds:270 ret i8 %idx;271}272 273; IV = 0; IV <s limit; IV += 1;274; Check(IV - N <= -2)275; N is known to be non-negative.276; TODO: IRCE is allowed.277define i8 @test2a(i8 %limit, ptr %p) {278; CHECK-LABEL: define i8 @test2a279; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {280; CHECK-NEXT: entry:281; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]282; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0283; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]284; CHECK: loop.preheader:285; CHECK-NEXT: br label [[LOOP:%.*]]286; CHECK: loop:287; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]288; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]289; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[SUB]], -2290; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]291; CHECK: inbounds:292; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1293; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]294; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]295; CHECK: exit.loopexit:296; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]297; CHECK-NEXT: br label [[EXIT]]298; CHECK: exit:299; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]300; CHECK-NEXT: ret i8 [[RES]]301; CHECK: out_of_bounds:302; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]303; CHECK-NEXT: ret i8 [[IDX_LCSSA]]304;305entry:306 %n = load i8, ptr %p, !range !0307 %precheck = icmp sgt i8 %limit, 0308 br i1 %precheck, label %loop, label %exit309 310loop:311 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]312 %sub = sub i8 %idx, %n313 %check = icmp sle i8 %sub, -2314 br i1 %check, label %inbounds, label %out_of_bounds315 316inbounds:317 %idx.next = add nuw i8 %idx, 1318 %cmp = icmp slt i8 %idx.next, %limit319 br i1 %cmp, label %loop, label %exit320 321exit:322 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]323 ret i8 %res324 325out_of_bounds:326 ret i8 %idx;327}328 329; IV = 0; IV <s limit; IV += 1;330; Check(IV + 2 <= N)331; TODO: IRCE is allowed.332define i8 @test3(i8 %limit, i8 %n) {333; CHECK-LABEL: define i8 @test3334; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {335; CHECK-NEXT: entry:336; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0337; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]338; CHECK: loop.preheader:339; CHECK-NEXT: br label [[LOOP:%.*]]340; CHECK: loop:341; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]342; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2343; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[ADD]], [[N]]344; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]345; CHECK: inbounds:346; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1347; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]348; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]349; CHECK: exit.loopexit:350; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]351; CHECK-NEXT: br label [[EXIT]]352; CHECK: exit:353; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]354; CHECK-NEXT: ret i8 [[RES]]355; CHECK: out_of_bounds:356; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]357; CHECK-NEXT: ret i8 [[IDX_LCSSA]]358;359entry:360 %precheck = icmp sgt i8 %limit, 0361 br i1 %precheck, label %loop, label %exit362 363loop:364 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]365 %add = add i8 %idx, 2366 %check = icmp sle i8 %add, %n367 br i1 %check, label %inbounds, label %out_of_bounds368 369inbounds:370 %idx.next = add nuw i8 %idx, 1371 %cmp = icmp slt i8 %idx.next, %limit372 br i1 %cmp, label %loop, label %exit373 374exit:375 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]376 ret i8 %res377 378out_of_bounds:379 ret i8 %idx;380}381 382; IV = 0; IV <s limit; IV += 1;383; Check(IV + 2 <= N)384; N is known to be non-negative.385; IRCE is allowed.386define i8 @test3a(i8 %limit, ptr %p) {387; CHECK-LABEL: define i8 @test3a388; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {389; CHECK-NEXT: entry:390; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]391; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0392; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]393; CHECK: loop.preheader:394; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1395; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])396; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)397; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]398; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]399; CHECK: loop.preheader3:400; CHECK-NEXT: br label [[LOOP:%.*]]401; CHECK: loop:402; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]403; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2404; CHECK-NEXT: [[CHECK:%.*]] = icmp sle i8 [[ADD]], [[N]]405; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]406; CHECK: inbounds:407; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1408; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]409; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]410; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]411; CHECK: main.exit.selector:412; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]413; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]414; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]415; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]416; CHECK: main.pseudo.exit:417; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]418; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]419; CHECK-NEXT: br label [[POSTLOOP:%.*]]420; CHECK: exit.loopexit.loopexit:421; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]422; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]423; CHECK: exit.loopexit:424; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]425; CHECK-NEXT: br label [[EXIT]]426; CHECK: exit:427; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]428; CHECK-NEXT: ret i8 [[RES]]429; CHECK: out_of_bounds.loopexit:430; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]431; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]432; CHECK: out_of_bounds.loopexit4:433; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]434; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]435; CHECK: out_of_bounds:436; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]437; CHECK-NEXT: ret i8 [[IDX_LCSSA]]438; CHECK: postloop:439; CHECK-NEXT: br label [[LOOP_POSTLOOP]]440; CHECK: loop.postloop:441; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]442; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2443; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sle i8 [[ADD_POSTLOOP]], [[N]]444; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]445; CHECK: inbounds.postloop:446; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1447; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]448; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone !5449;450entry:451 %n = load i8, ptr %p, !range !0452 %precheck = icmp sgt i8 %limit, 0453 br i1 %precheck, label %loop, label %exit454 455loop:456 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]457 %add = add i8 %idx, 2458 %check = icmp sle i8 %add, %n459 br i1 %check, label %inbounds, label %out_of_bounds460 461inbounds:462 %idx.next = add nuw i8 %idx, 1463 %cmp = icmp slt i8 %idx.next, %limit464 br i1 %cmp, label %loop, label %exit465 466exit:467 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]468 ret i8 %res469 470out_of_bounds:471 ret i8 %idx;472}473 474; IV = 0; IV <s limit; IV += 1;475; Check(N - IV > 2)476; IRCE is allowed.477define i8 @test4(i8 %limit, i8 %n) {478; CHECK-LABEL: define i8 @test4479; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {480; CHECK-NEXT: entry:481; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0482; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]483; CHECK: loop.preheader:484; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2485; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], 127486; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)487; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]488; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0)489; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)490; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[SMAX2]], 1491; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]]492; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i16493; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 126494; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP6]], i16 0)495; CHECK-NEXT: [[SMAX4:%.*]] = call i16 @llvm.smax.i16(i16 [[SMIN3]], i16 -1)496; CHECK-NEXT: [[TMP7:%.*]] = trunc i16 [[SMAX4]] to i8497; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 1498; CHECK-NEXT: [[TMP9:%.*]] = mul i8 [[TMP4]], [[TMP8]]499; CHECK-NEXT: [[SMIN5:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP9]])500; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN5]], i8 0)501; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]502; CHECK-NEXT: br i1 [[TMP10]], label [[LOOP_PREHEADER8:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]503; CHECK: loop.preheader8:504; CHECK-NEXT: br label [[LOOP:%.*]]505; CHECK: loop:506; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER8]] ]507; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]508; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2509; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT9:%.*]]510; CHECK: inbounds:511; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1512; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]513; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]514; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]515; CHECK: main.exit.selector:516; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]517; CHECK-NEXT: [[IDX_LCSSA7:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]518; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]519; CHECK-NEXT: br i1 [[TMP12]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]520; CHECK: main.pseudo.exit:521; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]522; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]523; CHECK-NEXT: br label [[POSTLOOP:%.*]]524; CHECK: exit.loopexit.loopexit:525; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]526; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]527; CHECK: exit.loopexit:528; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA7]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]529; CHECK-NEXT: br label [[EXIT]]530; CHECK: exit:531; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]532; CHECK-NEXT: ret i8 [[RES]]533; CHECK: out_of_bounds.loopexit:534; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]535; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]536; CHECK: out_of_bounds.loopexit9:537; CHECK-NEXT: [[IDX_LCSSA_PH10:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]538; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]539; CHECK: out_of_bounds:540; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH10]], [[OUT_OF_BOUNDS_LOOPEXIT9]] ]541; CHECK-NEXT: ret i8 [[IDX_LCSSA]]542; CHECK: postloop:543; CHECK-NEXT: br label [[LOOP_POSTLOOP]]544; CHECK: loop.postloop:545; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]546; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]547; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], 2548; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]549; CHECK: inbounds.postloop:550; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1551; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]552; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone !5553;554entry:555 %precheck = icmp sgt i8 %limit, 0556 br i1 %precheck, label %loop, label %exit557 558loop:559 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]560 %sub = sub i8 %n, %idx561 %check = icmp sgt i8 %sub, 2562 br i1 %check, label %inbounds, label %out_of_bounds563 564inbounds:565 %idx.next = add nuw i8 %idx, 1566 %cmp = icmp slt i8 %idx.next, %limit567 br i1 %cmp, label %loop, label %exit568 569exit:570 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]571 ret i8 %res572 573out_of_bounds:574 ret i8 %idx;575}576 577; IV = 0; IV <s limit; IV += 1;578; Check(N - IV > 2)579; N is known to be non-negative.580; TODO: IRCE is allowed.581define i8 @test4a(i8 %limit, ptr %p) {582; CHECK-LABEL: define i8 @test4a583; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {584; CHECK-NEXT: entry:585; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]586; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0587; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]588; CHECK: loop.preheader:589; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2590; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[N]], 127591; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)592; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]593; CHECK-NEXT: [[TMP3:%.*]] = add nsw i8 [[N]], -2594; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP3]], i8 0)595; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)596; CHECK-NEXT: [[TMP4:%.*]] = add nsw i8 [[SMAX2]], 1597; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]]598; CHECK-NEXT: [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP5]])599; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)600; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]601; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]602; CHECK: loop.preheader6:603; CHECK-NEXT: br label [[LOOP:%.*]]604; CHECK: loop:605; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]606; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]607; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], 2608; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]609; CHECK: inbounds:610; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1611; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]612; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]613; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]614; CHECK: main.exit.selector:615; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]616; CHECK-NEXT: [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]617; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]618; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]619; CHECK: main.pseudo.exit:620; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]621; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]622; CHECK-NEXT: br label [[POSTLOOP:%.*]]623; CHECK: exit.loopexit.loopexit:624; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]625; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]626; CHECK: exit.loopexit:627; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]628; CHECK-NEXT: br label [[EXIT]]629; CHECK: exit:630; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]631; CHECK-NEXT: ret i8 [[RES]]632; CHECK: out_of_bounds.loopexit:633; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]634; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]635; CHECK: out_of_bounds.loopexit7:636; CHECK-NEXT: [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]637; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]638; CHECK: out_of_bounds:639; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]640; CHECK-NEXT: ret i8 [[IDX_LCSSA]]641; CHECK: postloop:642; CHECK-NEXT: br label [[LOOP_POSTLOOP]]643; CHECK: loop.postloop:644; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]645; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]646; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], 2647; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]648; CHECK: inbounds.postloop:649; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1650; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]651; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone !5652;653entry:654 %n = load i8, ptr %p, !range !0655 %precheck = icmp sgt i8 %limit, 0656 br i1 %precheck, label %loop, label %exit657 658loop:659 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]660 %sub = sub i8 %n, %idx661 %check = icmp sgt i8 %sub, 2662 br i1 %check, label %inbounds, label %out_of_bounds663 664inbounds:665 %idx.next = add nuw i8 %idx, 1666 %cmp = icmp slt i8 %idx.next, %limit667 br i1 %cmp, label %loop, label %exit668 669exit:670 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]671 ret i8 %res672 673out_of_bounds:674 ret i8 %idx;675}676 677; IV = 0; IV <s limit; IV += 1;678; Check(IV - N < -2)679; TODO: IRCE is allowed.680define i8 @test5(i8 %limit, i8 %n) {681; CHECK-LABEL: define i8 @test5682; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {683; CHECK-NEXT: entry:684; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0685; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]686; CHECK: loop.preheader:687; CHECK-NEXT: br label [[LOOP:%.*]]688; CHECK: loop:689; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]690; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]691; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2692; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]693; CHECK: inbounds:694; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1695; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]696; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]697; CHECK: exit.loopexit:698; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]699; CHECK-NEXT: br label [[EXIT]]700; CHECK: exit:701; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]702; CHECK-NEXT: ret i8 [[RES]]703; CHECK: out_of_bounds:704; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]705; CHECK-NEXT: ret i8 [[IDX_LCSSA]]706;707entry:708 %precheck = icmp sgt i8 %limit, 0709 br i1 %precheck, label %loop, label %exit710 711loop:712 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]713 %sub = sub i8 %idx, %n714 %check = icmp slt i8 %sub, -2715 br i1 %check, label %inbounds, label %out_of_bounds716 717inbounds:718 %idx.next = add nuw i8 %idx, 1719 %cmp = icmp slt i8 %idx.next, %limit720 br i1 %cmp, label %loop, label %exit721 722exit:723 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]724 ret i8 %res725 726out_of_bounds:727 ret i8 %idx;728}729 730; IV = 0; IV <s limit; IV += 1;731; Check(IV - N < -2)732; N is known to be non-negative.733; TODO: IRCE is allowed.734define i8 @test5a(i8 %limit, ptr %p) {735; CHECK-LABEL: define i8 @test5a736; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {737; CHECK-NEXT: entry:738; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]739; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0740; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]741; CHECK: loop.preheader:742; CHECK-NEXT: br label [[LOOP:%.*]]743; CHECK: loop:744; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]745; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[IDX]], [[N]]746; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[SUB]], -2747; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]]748; CHECK: inbounds:749; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1750; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]751; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]752; CHECK: exit.loopexit:753; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]754; CHECK-NEXT: br label [[EXIT]]755; CHECK: exit:756; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]757; CHECK-NEXT: ret i8 [[RES]]758; CHECK: out_of_bounds:759; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]760; CHECK-NEXT: ret i8 [[IDX_LCSSA]]761;762entry:763 %n = load i8, ptr %p, !range !0764 %precheck = icmp sgt i8 %limit, 0765 br i1 %precheck, label %loop, label %exit766 767loop:768 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]769 %sub = sub i8 %idx, %n770 %check = icmp slt i8 %sub, -2771 br i1 %check, label %inbounds, label %out_of_bounds772 773inbounds:774 %idx.next = add nuw i8 %idx, 1775 %cmp = icmp slt i8 %idx.next, %limit776 br i1 %cmp, label %loop, label %exit777 778exit:779 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]780 ret i8 %res781 782out_of_bounds:783 ret i8 %idx;784}785 786; IV = 0; IV <s limit; IV += 1;787; Check(IV + 2 < N)788; IRCE is allowed.789define i8 @test6(i8 %limit, i8 %n) {790; CHECK-LABEL: define i8 @test6791; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) {792; CHECK-NEXT: entry:793; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0794; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]795; CHECK: loop.preheader:796; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -127797; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP0]], i8 2)798; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[N]], [[SMAX]]799; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[N]], i8 0)800; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)801; CHECK-NEXT: [[TMP2:%.*]] = add nsw i8 [[SMAX2]], 1802; CHECK-NEXT: [[TMP3:%.*]] = mul i8 [[TMP1]], [[TMP2]]803; CHECK-NEXT: [[SMIN3:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP3]])804; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN3]], i8 0)805; CHECK-NEXT: [[TMP4:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]806; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP_PREHEADER6:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]807; CHECK: loop.preheader6:808; CHECK-NEXT: br label [[LOOP:%.*]]809; CHECK: loop:810; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER6]] ]811; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2812; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]813; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT7:%.*]]814; CHECK: inbounds:815; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1816; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]817; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]818; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]819; CHECK: main.exit.selector:820; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]821; CHECK-NEXT: [[IDX_LCSSA5:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]822; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]823; CHECK-NEXT: br i1 [[TMP6]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]824; CHECK: main.pseudo.exit:825; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]826; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]827; CHECK-NEXT: br label [[POSTLOOP:%.*]]828; CHECK: exit.loopexit.loopexit:829; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]830; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]831; CHECK: exit.loopexit:832; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA5]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]833; CHECK-NEXT: br label [[EXIT]]834; CHECK: exit:835; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]836; CHECK-NEXT: ret i8 [[RES]]837; CHECK: out_of_bounds.loopexit:838; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]839; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]840; CHECK: out_of_bounds.loopexit7:841; CHECK-NEXT: [[IDX_LCSSA_PH8:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]842; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]843; CHECK: out_of_bounds:844; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH8]], [[OUT_OF_BOUNDS_LOOPEXIT7]] ]845; CHECK-NEXT: ret i8 [[IDX_LCSSA]]846; CHECK: postloop:847; CHECK-NEXT: br label [[LOOP_POSTLOOP]]848; CHECK: loop.postloop:849; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]850; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2851; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]852; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]853; CHECK: inbounds.postloop:854; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1855; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]856; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone !5857;858entry:859 %precheck = icmp sgt i8 %limit, 0860 br i1 %precheck, label %loop, label %exit861 862loop:863 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]864 %add = add i8 %idx, 2865 %check = icmp slt i8 %add, %n866 br i1 %check, label %inbounds, label %out_of_bounds867 868inbounds:869 %idx.next = add nuw i8 %idx, 1870 %cmp = icmp slt i8 %idx.next, %limit871 br i1 %cmp, label %loop, label %exit872 873exit:874 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]875 ret i8 %res876 877out_of_bounds:878 ret i8 %idx;879}880 881; IV = 0; IV <s limit; IV += 1;882; Check(IV + 2 < N)883; N is known to be non-negative.884; IRCE is allowed.885define i8 @test6a(i8 %limit, ptr %p) {886; CHECK-LABEL: define i8 @test6a887; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {888; CHECK-NEXT: entry:889; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG6]]890; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0891; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]892; CHECK: loop.preheader:893; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -2894; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])895; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)896; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]897; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]898; CHECK: loop.preheader3:899; CHECK-NEXT: br label [[LOOP:%.*]]900; CHECK: loop:901; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]902; CHECK-NEXT: [[ADD:%.*]] = add i8 [[IDX]], 2903; CHECK-NEXT: [[CHECK:%.*]] = icmp slt i8 [[ADD]], [[N]]904; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]905; CHECK: inbounds:906; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 1907; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]908; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]909; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]910; CHECK: main.exit.selector:911; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]912; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]913; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]914; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]915; CHECK: main.pseudo.exit:916; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]917; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]918; CHECK-NEXT: br label [[POSTLOOP:%.*]]919; CHECK: exit.loopexit.loopexit:920; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]921; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]922; CHECK: exit.loopexit:923; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]924; CHECK-NEXT: br label [[EXIT]]925; CHECK: exit:926; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]927; CHECK-NEXT: ret i8 [[RES]]928; CHECK: out_of_bounds.loopexit:929; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]930; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]931; CHECK: out_of_bounds.loopexit4:932; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]933; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]934; CHECK: out_of_bounds:935; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]936; CHECK-NEXT: ret i8 [[IDX_LCSSA]]937; CHECK: postloop:938; CHECK-NEXT: br label [[LOOP_POSTLOOP]]939; CHECK: loop.postloop:940; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]941; CHECK-NEXT: [[ADD_POSTLOOP:%.*]] = add i8 [[IDX_POSTLOOP]], 2942; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp slt i8 [[ADD_POSTLOOP]], [[N]]943; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]944; CHECK: inbounds.postloop:945; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 1946; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]947; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone !5948;949entry:950 %n = load i8, ptr %p, !range !0951 %precheck = icmp sgt i8 %limit, 0952 br i1 %precheck, label %loop, label %exit953 954loop:955 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]956 %add = add i8 %idx, 2957 %check = icmp slt i8 %add, %n958 br i1 %check, label %inbounds, label %out_of_bounds959 960inbounds:961 %idx.next = add nuw i8 %idx, 1962 %cmp = icmp slt i8 %idx.next, %limit963 br i1 %cmp, label %loop, label %exit964 965exit:966 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]967 ret i8 %res968 969out_of_bounds:970 ret i8 %idx;971}972 973; IV = 0; IV <s limit; IV += 1;974; Check(N - IV > -2)975;976; IRCE is allowed.977; IRCE will reassociate this range check to the 'IV < N + 2',978; since N < 126 no-overflow fact is provable at compile time.979define i8 @test_overflow_check_compile_time(i8 %limit, ptr %p) {980; CHECK-LABEL: define i8 @test_overflow_check_compile_time981; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {982; CHECK-NEXT: entry:983; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG13:![0-9]+]]984; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0985; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]986; CHECK: loop.preheader:987; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i8 [[N]], 2988; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP0]])989; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 0)990; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]991; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PREHEADER3:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]992; CHECK: loop.preheader3:993; CHECK-NEXT: br label [[LOOP:%.*]]994; CHECK: loop:995; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER3]] ]996; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]997; CHECK-NEXT: [[CHECK:%.*]] = icmp sgt i8 [[SUB]], -2998; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT4:%.*]]999; CHECK: inbounds:1000; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 11001; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]1002; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]1003; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]1004; CHECK: main.exit.selector:1005; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]1006; CHECK-NEXT: [[IDX_LCSSA2:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]1007; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]1008; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]1009; CHECK: main.pseudo.exit:1010; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]1011; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]1012; CHECK-NEXT: br label [[POSTLOOP:%.*]]1013; CHECK: exit.loopexit.loopexit:1014; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]1015; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]1016; CHECK: exit.loopexit:1017; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA2]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]1018; CHECK-NEXT: br label [[EXIT]]1019; CHECK: exit:1020; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]1021; CHECK-NEXT: ret i8 [[RES]]1022; CHECK: out_of_bounds.loopexit:1023; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]1024; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]1025; CHECK: out_of_bounds.loopexit4:1026; CHECK-NEXT: [[IDX_LCSSA_PH5:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]1027; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]1028; CHECK: out_of_bounds:1029; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH5]], [[OUT_OF_BOUNDS_LOOPEXIT4]] ]1030; CHECK-NEXT: ret i8 [[IDX_LCSSA]]1031; CHECK: postloop:1032; CHECK-NEXT: br label [[LOOP_POSTLOOP]]1033; CHECK: loop.postloop:1034; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]1035; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]1036; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sgt i8 [[SUB_POSTLOOP]], -21037; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]1038; CHECK: inbounds.postloop:1039; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 11040; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]1041; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP14:![0-9]+]], !loop_constrainer.loop.clone !51042;1043entry:1044 %n = load i8, ptr %p, !range !11045 %precheck = icmp sgt i8 %limit, 01046 br i1 %precheck, label %loop, label %exit1047 1048loop:1049 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]1050 %sub = sub i8 %n, %idx1051 %check = icmp sgt i8 %sub, -21052 br i1 %check, label %inbounds, label %out_of_bounds1053 1054inbounds:1055 %idx.next = add nuw i8 %idx, 11056 %cmp = icmp slt i8 %idx.next, %limit1057 br i1 %cmp, label %loop, label %exit1058 1059exit:1060 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]1061 ret i8 %res1062 1063out_of_bounds:1064 ret i8 %idx;1065}1066 1067; IV = 0; IV <s limit; IV += 1;1068; Check(N - IV >= -2)1069;1070; IRCE is allowed.1071; IRCE will reassociate this range check to the 'IV < (N + 2) + 1',1072; since N < 126 no-overflow fact is NOT provable at compile time and1073; runtime overflow check is required.1074define i8 @test_overflow_check_runtime(i8 %limit, ptr %p) {1075; CHECK-LABEL: define i8 @test_overflow_check_runtime1076; CHECK-SAME: (i8 [[LIMIT:%.*]], ptr [[P:%.*]]) {1077; CHECK-NEXT: entry:1078; CHECK-NEXT: [[N:%.*]] = load i8, ptr [[P]], align 1, !range [[RNG13]]1079; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 01080; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]1081; CHECK: loop.preheader:1082; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], 31083; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[N]], -1241084; CHECK-NEXT: [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0)1085; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0]], [[SMAX]]1086; CHECK-NEXT: [[TMP3:%.*]] = add nuw i8 [[N]], 31087; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP3]], i8 0)1088; CHECK-NEXT: [[SMAX2:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN]], i8 -1)1089; CHECK-NEXT: [[TMP4:%.*]] = add nsw i8 [[SMAX2]], 11090; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]]1091; CHECK-NEXT: [[TMP6:%.*]] = zext nneg i8 [[N]] to i161092; CHECK-NEXT: [[TMP7:%.*]] = sub i16 124, [[TMP6]]1093; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP7]], i16 0)1094; CHECK-NEXT: [[TMP8:%.*]] = trunc i16 [[SMIN3]] to i81095; CHECK-NEXT: [[TMP9:%.*]] = add nsw i8 [[TMP8]], 11096; CHECK-NEXT: [[TMP10:%.*]] = mul i8 [[TMP5]], [[TMP9]]1097; CHECK-NEXT: [[SMIN4:%.*]] = call i8 @llvm.smin.i8(i8 [[LIMIT]], i8 [[TMP10]])1098; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i8 @llvm.smax.i8(i8 [[SMIN4]], i8 0)1099; CHECK-NEXT: [[TMP11:%.*]] = icmp slt i8 0, [[EXIT_MAINLOOP_AT]]1100; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER7:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]1101; CHECK: loop.preheader7:1102; CHECK-NEXT: br label [[LOOP:%.*]]1103; CHECK: loop:1104; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ [[IDX_NEXT:%.*]], [[INBOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER7]] ]1105; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[N]], [[IDX]]1106; CHECK-NEXT: [[CHECK:%.*]] = icmp sge i8 [[SUB]], -21107; CHECK-NEXT: br i1 true, label [[INBOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT8:%.*]]1108; CHECK: inbounds:1109; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i8 [[IDX]], 11110; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[IDX_NEXT]], [[LIMIT]]1111; CHECK-NEXT: [[TMP12:%.*]] = icmp slt i8 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]1112; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]1113; CHECK: main.exit.selector:1114; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i8 [ [[IDX_NEXT]], [[INBOUNDS]] ]1115; CHECK-NEXT: [[IDX_LCSSA6:%.*]] = phi i8 [ [[IDX]], [[INBOUNDS]] ]1116; CHECK-NEXT: [[TMP13:%.*]] = icmp slt i8 [[IDX_NEXT_LCSSA]], [[LIMIT]]1117; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]1118; CHECK: main.pseudo.exit:1119; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]1120; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i8 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]1121; CHECK-NEXT: br label [[POSTLOOP:%.*]]1122; CHECK: exit.loopexit.loopexit:1123; CHECK-NEXT: [[IDX_LCSSA1_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP:%.*]] ]1124; CHECK-NEXT: br label [[EXIT_LOOPEXIT]]1125; CHECK: exit.loopexit:1126; CHECK-NEXT: [[IDX_LCSSA1:%.*]] = phi i8 [ [[IDX_LCSSA6]], [[MAIN_EXIT_SELECTOR]] ], [ [[IDX_LCSSA1_PH]], [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] ]1127; CHECK-NEXT: br label [[EXIT]]1128; CHECK: exit:1129; CHECK-NEXT: [[RES:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[IDX_LCSSA1]], [[EXIT_LOOPEXIT]] ]1130; CHECK-NEXT: ret i8 [[RES]]1131; CHECK: out_of_bounds.loopexit:1132; CHECK-NEXT: [[IDX_LCSSA_PH:%.*]] = phi i8 [ [[IDX_POSTLOOP]], [[LOOP_POSTLOOP:%.*]] ]1133; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]1134; CHECK: out_of_bounds.loopexit8:1135; CHECK-NEXT: [[IDX_LCSSA_PH9:%.*]] = phi i8 [ [[IDX]], [[LOOP]] ]1136; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]1137; CHECK: out_of_bounds:1138; CHECK-NEXT: [[IDX_LCSSA:%.*]] = phi i8 [ [[IDX_LCSSA_PH]], [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] ], [ [[IDX_LCSSA_PH9]], [[OUT_OF_BOUNDS_LOOPEXIT8]] ]1139; CHECK-NEXT: ret i8 [[IDX_LCSSA]]1140; CHECK: postloop:1141; CHECK-NEXT: br label [[LOOP_POSTLOOP]]1142; CHECK: loop.postloop:1143; CHECK-NEXT: [[IDX_POSTLOOP]] = phi i8 [ [[IDX_NEXT_POSTLOOP:%.*]], [[INBOUNDS_POSTLOOP]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]1144; CHECK-NEXT: [[SUB_POSTLOOP:%.*]] = sub i8 [[N]], [[IDX_POSTLOOP]]1145; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp sge i8 [[SUB_POSTLOOP]], -21146; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[INBOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT]]1147; CHECK: inbounds.postloop:1148; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw i8 [[IDX_POSTLOOP]], 11149; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i8 [[IDX_NEXT_POSTLOOP]], [[LIMIT]]1150; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT]], !llvm.loop [[LOOP15:![0-9]+]], !loop_constrainer.loop.clone !51151;1152entry:1153 %n = load i8, ptr %p, !range !11154 %precheck = icmp sgt i8 %limit, 01155 br i1 %precheck, label %loop, label %exit1156 1157loop:1158 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ]1159 %sub = sub i8 %n, %idx1160 %check = icmp sge i8 %sub, -21161 br i1 %check, label %inbounds, label %out_of_bounds1162 1163inbounds:1164 %idx.next = add nuw i8 %idx, 11165 %cmp = icmp slt i8 %idx.next, %limit1166 br i1 %cmp, label %loop, label %exit1167 1168exit:1169 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ]1170 ret i8 %res1171 1172out_of_bounds:1173 ret i8 %idx;1174}1175 1176!0 = !{i8 0, i8 127}1177!1 = !{i8 0, i8 126}1178