1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -verify-loop-info -passes=irce -irce-print-scaled-boundary-range-checks -S < %s 2>&1 | FileCheck %s 3 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: 0 10; 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: 0 16; 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: 0 22 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 @test1 28; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 29; CHECK-NEXT: entry: 30; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 31; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 32; CHECK: loop.preheader: 33; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -1 34; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], -128 35; 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]], 1 40; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]] 41; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i16 42; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 127 43; CHECK-NEXT: [[SMIN3:%.*]] = call i16 @llvm.smin.i16(i16 [[TMP6]], i16 0) 44; CHECK-NEXT: [[TMP7:%.*]] = trunc i16 [[SMIN3]] to i8 45; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 1 46; 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]], 2 57; 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]], 1 60; 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]], 2 96; 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]], 1 99; 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 !5 101; 102entry: 103 %precheck = icmp sgt i8 %limit, 0 104 br i1 %precheck, label %loop, label %exit 105 106loop: 107 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 108 %sub = sub i8 %n, %idx 109 %check = icmp sge i8 %sub, 2 110 br i1 %check, label %inbounds, label %out_of_bounds 111 112inbounds: 113 %idx.next = add nuw i8 %idx, 1 114 %cmp = icmp slt i8 %idx.next, %limit 115 br i1 %cmp, label %loop, label %exit 116 117exit: 118 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 119 ret i8 %res 120 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 @test1a 131; 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]], 0 135; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 136; CHECK: loop.preheader: 137; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1 138; CHECK-NEXT: [[SMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP0]], i8 0) 139; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[SMIN]], 1 140; 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]], 2 151; 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]], 1 154; 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]], 2 190; 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]], 1 193; 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 !5 195; 196entry: 197 %n = load i8, ptr %p, !range !0 198 %precheck = icmp sgt i8 %limit, 0 199 br i1 %precheck, label %loop, label %exit 200 201loop: 202 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 203 %sub = sub i8 %n, %idx 204 %check = icmp sge i8 %sub, 2 205 br i1 %check, label %inbounds, label %out_of_bounds 206 207inbounds: 208 %idx.next = add nuw i8 %idx, 1 209 %cmp = icmp slt i8 %idx.next, %limit 210 br i1 %cmp, label %loop, label %exit 211 212exit: 213 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 214 ret i8 %res 215 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 @test2 225; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 226; CHECK-NEXT: entry: 227; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 228; 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]], -2 235; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]] 236; CHECK: inbounds: 237; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1 238; 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, 0 252 br i1 %precheck, label %loop, label %exit 253 254loop: 255 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 256 %sub = sub i8 %idx, %n 257 %check = icmp sle i8 %sub, -2 258 br i1 %check, label %inbounds, label %out_of_bounds 259 260inbounds: 261 %idx.next = add nuw i8 %idx, 1 262 %cmp = icmp slt i8 %idx.next, %limit 263 br i1 %cmp, label %loop, label %exit 264 265exit: 266 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 267 ret i8 %res 268 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 @test2a 279; 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]], 0 283; 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]], -2 290; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]] 291; CHECK: inbounds: 292; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1 293; 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 !0 307 %precheck = icmp sgt i8 %limit, 0 308 br i1 %precheck, label %loop, label %exit 309 310loop: 311 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 312 %sub = sub i8 %idx, %n 313 %check = icmp sle i8 %sub, -2 314 br i1 %check, label %inbounds, label %out_of_bounds 315 316inbounds: 317 %idx.next = add nuw i8 %idx, 1 318 %cmp = icmp slt i8 %idx.next, %limit 319 br i1 %cmp, label %loop, label %exit 320 321exit: 322 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 323 ret i8 %res 324 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 @test3 334; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 335; CHECK-NEXT: entry: 336; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 337; 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]], 2 343; 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]], 1 347; 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, 0 361 br i1 %precheck, label %loop, label %exit 362 363loop: 364 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 365 %add = add i8 %idx, 2 366 %check = icmp sle i8 %add, %n 367 br i1 %check, label %inbounds, label %out_of_bounds 368 369inbounds: 370 %idx.next = add nuw i8 %idx, 1 371 %cmp = icmp slt i8 %idx.next, %limit 372 br i1 %cmp, label %loop, label %exit 373 374exit: 375 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 376 ret i8 %res 377 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 @test3a 388; 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]], 0 392; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 393; CHECK: loop.preheader: 394; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -1 395; 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]], 2 404; 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]], 1 408; 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]], 2 443; 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]], 1 447; 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 !5 449; 450entry: 451 %n = load i8, ptr %p, !range !0 452 %precheck = icmp sgt i8 %limit, 0 453 br i1 %precheck, label %loop, label %exit 454 455loop: 456 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 457 %add = add i8 %idx, 2 458 %check = icmp sle i8 %add, %n 459 br i1 %check, label %inbounds, label %out_of_bounds 460 461inbounds: 462 %idx.next = add nuw i8 %idx, 1 463 %cmp = icmp slt i8 %idx.next, %limit 464 br i1 %cmp, label %loop, label %exit 465 466exit: 467 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 468 ret i8 %res 469 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 @test4 479; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 480; CHECK-NEXT: entry: 481; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 482; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 483; CHECK: loop.preheader: 484; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2 485; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[N]], 127 486; 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]], 1 491; CHECK-NEXT: [[TMP4:%.*]] = mul i8 [[TMP2]], [[TMP3]] 492; CHECK-NEXT: [[TMP5:%.*]] = sext i8 [[N]] to i16 493; CHECK-NEXT: [[TMP6:%.*]] = add nsw i16 [[TMP5]], 126 494; 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 i8 497; CHECK-NEXT: [[TMP8:%.*]] = add nsw i8 [[TMP7]], 1 498; 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]], 2 509; 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]], 1 512; 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]], 2 548; 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]], 1 551; 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 !5 553; 554entry: 555 %precheck = icmp sgt i8 %limit, 0 556 br i1 %precheck, label %loop, label %exit 557 558loop: 559 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 560 %sub = sub i8 %n, %idx 561 %check = icmp sgt i8 %sub, 2 562 br i1 %check, label %inbounds, label %out_of_bounds 563 564inbounds: 565 %idx.next = add nuw i8 %idx, 1 566 %cmp = icmp slt i8 %idx.next, %limit 567 br i1 %cmp, label %loop, label %exit 568 569exit: 570 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 571 ret i8 %res 572 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 @test4a 583; 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]], 0 587; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 588; CHECK: loop.preheader: 589; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -2 590; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[N]], 127 591; 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]], -2 594; 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]], 1 597; 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]], 2 608; 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]], 1 611; 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]], 2 647; 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]], 1 650; 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 !5 652; 653entry: 654 %n = load i8, ptr %p, !range !0 655 %precheck = icmp sgt i8 %limit, 0 656 br i1 %precheck, label %loop, label %exit 657 658loop: 659 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 660 %sub = sub i8 %n, %idx 661 %check = icmp sgt i8 %sub, 2 662 br i1 %check, label %inbounds, label %out_of_bounds 663 664inbounds: 665 %idx.next = add nuw i8 %idx, 1 666 %cmp = icmp slt i8 %idx.next, %limit 667 br i1 %cmp, label %loop, label %exit 668 669exit: 670 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 671 ret i8 %res 672 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 @test5 682; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 683; CHECK-NEXT: entry: 684; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 685; 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]], -2 692; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]] 693; CHECK: inbounds: 694; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1 695; 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, 0 709 br i1 %precheck, label %loop, label %exit 710 711loop: 712 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 713 %sub = sub i8 %idx, %n 714 %check = icmp slt i8 %sub, -2 715 br i1 %check, label %inbounds, label %out_of_bounds 716 717inbounds: 718 %idx.next = add nuw i8 %idx, 1 719 %cmp = icmp slt i8 %idx.next, %limit 720 br i1 %cmp, label %loop, label %exit 721 722exit: 723 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 724 ret i8 %res 725 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 @test5a 736; 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]], 0 740; 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]], -2 747; CHECK-NEXT: br i1 [[CHECK]], label [[INBOUNDS]], label [[OUT_OF_BOUNDS:%.*]] 748; CHECK: inbounds: 749; CHECK-NEXT: [[IDX_NEXT]] = add nuw i8 [[IDX]], 1 750; 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 !0 764 %precheck = icmp sgt i8 %limit, 0 765 br i1 %precheck, label %loop, label %exit 766 767loop: 768 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 769 %sub = sub i8 %idx, %n 770 %check = icmp slt i8 %sub, -2 771 br i1 %check, label %inbounds, label %out_of_bounds 772 773inbounds: 774 %idx.next = add nuw i8 %idx, 1 775 %cmp = icmp slt i8 %idx.next, %limit 776 br i1 %cmp, label %loop, label %exit 777 778exit: 779 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 780 ret i8 %res 781 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 @test6 791; CHECK-SAME: (i8 [[LIMIT:%.*]], i8 [[N:%.*]]) { 792; CHECK-NEXT: entry: 793; CHECK-NEXT: [[PRECHECK:%.*]] = icmp sgt i8 [[LIMIT]], 0 794; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 795; CHECK: loop.preheader: 796; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], -127 797; 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]], 1 802; 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]], 2 812; 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]], 1 816; 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]], 2 851; 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]], 1 855; 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 !5 857; 858entry: 859 %precheck = icmp sgt i8 %limit, 0 860 br i1 %precheck, label %loop, label %exit 861 862loop: 863 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 864 %add = add i8 %idx, 2 865 %check = icmp slt i8 %add, %n 866 br i1 %check, label %inbounds, label %out_of_bounds 867 868inbounds: 869 %idx.next = add nuw i8 %idx, 1 870 %cmp = icmp slt i8 %idx.next, %limit 871 br i1 %cmp, label %loop, label %exit 872 873exit: 874 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 875 ret i8 %res 876 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 @test6a 887; 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]], 0 891; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 892; CHECK: loop.preheader: 893; CHECK-NEXT: [[TMP0:%.*]] = add nsw i8 [[N]], -2 894; 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]], 2 903; 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]], 1 907; 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]], 2 942; 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]], 1 946; 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 !5 948; 949entry: 950 %n = load i8, ptr %p, !range !0 951 %precheck = icmp sgt i8 %limit, 0 952 br i1 %precheck, label %loop, label %exit 953 954loop: 955 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 956 %add = add i8 %idx, 2 957 %check = icmp slt i8 %add, %n 958 br i1 %check, label %inbounds, label %out_of_bounds 959 960inbounds: 961 %idx.next = add nuw i8 %idx, 1 962 %cmp = icmp slt i8 %idx.next, %limit 963 br i1 %cmp, label %loop, label %exit 964 965exit: 966 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 967 ret i8 %res 968 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_time 981; 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]], 0 985; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 986; CHECK: loop.preheader: 987; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i8 [[N]], 2 988; 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]], -2 998; 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]], 1 1001; 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]], -2 1037; 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]], 1 1040; 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 !5 1042; 1043entry: 1044 %n = load i8, ptr %p, !range !1 1045 %precheck = icmp sgt i8 %limit, 0 1046 br i1 %precheck, label %loop, label %exit 1047 1048loop: 1049 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 1050 %sub = sub i8 %n, %idx 1051 %check = icmp sgt i8 %sub, -2 1052 br i1 %check, label %inbounds, label %out_of_bounds 1053 1054inbounds: 1055 %idx.next = add nuw i8 %idx, 1 1056 %cmp = icmp slt i8 %idx.next, %limit 1057 br i1 %cmp, label %loop, label %exit 1058 1059exit: 1060 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 1061 ret i8 %res 1062 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 and 1073; runtime overflow check is required. 1074define i8 @test_overflow_check_runtime(i8 %limit, ptr %p) { 1075; CHECK-LABEL: define i8 @test_overflow_check_runtime 1076; 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]], 0 1080; CHECK-NEXT: br i1 [[PRECHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 1081; CHECK: loop.preheader: 1082; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[N]], 3 1083; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[N]], -124 1084; 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]], 3 1087; 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]], 1 1090; CHECK-NEXT: [[TMP5:%.*]] = mul i8 [[TMP2]], [[TMP4]] 1091; CHECK-NEXT: [[TMP6:%.*]] = zext nneg i8 [[N]] to i16 1092; 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 i8 1095; CHECK-NEXT: [[TMP9:%.*]] = add nsw i8 [[TMP8]], 1 1096; 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]], -2 1107; 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]], 1 1110; 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]], -2 1146; 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]], 1 1149; 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 !5 1151; 1152entry: 1153 %n = load i8, ptr %p, !range !1 1154 %precheck = icmp sgt i8 %limit, 0 1155 br i1 %precheck, label %loop, label %exit 1156 1157loop: 1158 %idx = phi i8 [ %idx.next, %inbounds ], [ 0, %entry ] 1159 %sub = sub i8 %n, %idx 1160 %check = icmp sge i8 %sub, -2 1161 br i1 %check, label %inbounds, label %out_of_bounds 1162 1163inbounds: 1164 %idx.next = add nuw i8 %idx, 1 1165 %cmp = icmp slt i8 %idx.next, %limit 1166 br i1 %cmp, label %loop, label %exit 1167 1168exit: 1169 %res = phi i8 [ 0, %entry ], [ %idx, %inbounds ] 1170 ret i8 %res 1171 1172out_of_bounds: 1173 ret i8 %idx; 1174} 1175 1176!0 = !{i8 0, i8 127} 1177!1 = !{i8 0, i8 126} 1178