457 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 32; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s3; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s4 5; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>6; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>7; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>8; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>9; CHECK-NOT: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>10; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>11 12; UGT condition for increasing loop.13define void @test_01(ptr %arr, ptr %a_len_ptr) #0 {14; CHECK-LABEL: define void @test_0115; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {16; CHECK-NEXT: entry:17; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]18; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]19; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]20; CHECK: loop.preheader:21; CHECK-NEXT: br label [[LOOP:%.*]]22; CHECK: loop:23; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]24; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 125; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]26; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]27; CHECK: in.bounds:28; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]29; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 430; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 10031; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]32; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true33; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]34; CHECK: main.exit.selector:35; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]36; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], 10137; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]38; CHECK: main.pseudo.exit:39; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]40; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]41; CHECK-NEXT: br label [[POSTLOOP:%.*]]42; CHECK: out.of.bounds.loopexit:43; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]44; CHECK: out.of.bounds.loopexit1:45; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]46; CHECK: out.of.bounds:47; CHECK-NEXT: ret void48; CHECK: exit.loopexit:49; CHECK-NEXT: br label [[EXIT]]50; CHECK: exit:51; CHECK-NEXT: ret void52; CHECK: postloop:53; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]54; CHECK: loop.postloop:55; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]56; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 157; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]58; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]59; CHECK: in.bounds.postloop:60; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]61; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 462; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], 10063; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone [[META6:![0-9]+]]64;65 66entry:67 %len = load i32, ptr %a_len_ptr, !range !068 br label %loop69 70loop:71 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]72 %idx.next = add nsw nuw i32 %idx, 173 %abc = icmp ult i32 %idx, %len74 br i1 %abc, label %in.bounds, label %out.of.bounds75 76in.bounds:77 %addr = getelementptr i32, ptr %arr, i32 %idx78 store i32 0, ptr %addr79 %next = icmp ugt i32 %idx.next, 10080 br i1 %next, label %exit, label %loop81 82out.of.bounds:83 ret void84 85exit:86 ret void87}88 89; UGT condition for decreasing loop.90define void @test_02(ptr %arr, ptr %a_len_ptr) #0 {91; CHECK-LABEL: define void @test_0292; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {93; CHECK-NEXT: entry:94; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]95; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)96; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -197; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 100, [[EXIT_PRELOOP_AT]]98; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]99; CHECK: loop.preloop.preheader:100; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]101; CHECK: mainloop:102; CHECK-NEXT: br label [[LOOP:%.*]]103; CHECK: loop:104; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]105; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -1106; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]107; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]108; CHECK: in.bounds:109; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]110; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4111; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0112; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]113; CHECK: out.of.bounds.loopexit:114; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]115; CHECK: out.of.bounds.loopexit1:116; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]117; CHECK: out.of.bounds:118; CHECK-NEXT: ret void119; CHECK: exit.loopexit:120; CHECK-NEXT: br label [[EXIT:%.*]]121; CHECK: exit:122; CHECK-NEXT: ret void123; CHECK: loop.preloop:124; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]125; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1126; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]127; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]128; CHECK: in.bounds.preloop:129; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]130; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4131; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0132; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]133; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone [[META6]]134; CHECK: preloop.exit.selector:135; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]136; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0137; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]138; CHECK: preloop.pseudo.exit:139; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]140; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]141; CHECK-NEXT: br label [[MAINLOOP]]142;143 144entry:145 %len = load i32, ptr %a_len_ptr, !range !0146 br label %loop147 148loop:149 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]150 %idx.next = add i32 %idx, -1151 %abc = icmp ult i32 %idx, %len152 br i1 %abc, label %in.bounds, label %out.of.bounds153 154in.bounds:155 %addr = getelementptr i32, ptr %arr, i32 %idx156 store i32 0, ptr %addr157 %next = icmp ugt i32 %idx.next, 0158 br i1 %next, label %loop, label %exit159 160out.of.bounds:161 ret void162 163exit:164 ret void165}166 167; Check SINT_MAX + 1, test is similar to test_01.168define void @test_03(ptr %arr, ptr %a_len_ptr) #0 {169; CHECK-LABEL: define void @test_03170; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {171; CHECK-NEXT: entry:172; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]173; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]174; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]175; CHECK: loop.preheader:176; CHECK-NEXT: br label [[LOOP:%.*]]177; CHECK: loop:178; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]179; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1180; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[EXIT_MAINLOOP_AT]]181; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]182; CHECK: in.bounds:183; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]184; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4185; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], -2147483648186; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]187; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[TMP1]], true188; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]189; CHECK: main.exit.selector:190; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]191; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], -2147483647192; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]193; CHECK: main.pseudo.exit:194; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]195; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]196; CHECK-NEXT: br label [[POSTLOOP:%.*]]197; CHECK: out.of.bounds.loopexit:198; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]199; CHECK: out.of.bounds.loopexit1:200; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]201; CHECK: out.of.bounds:202; CHECK-NEXT: ret void203; CHECK: exit.loopexit:204; CHECK-NEXT: br label [[EXIT]]205; CHECK: exit:206; CHECK-NEXT: ret void207; CHECK: postloop:208; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]209; CHECK: loop.postloop:210; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]211; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add nuw nsw i32 [[IDX_POSTLOOP]], 1212; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]213; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]214; CHECK: in.bounds.postloop:215; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]216; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4217; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_POSTLOOP]], -2147483648218; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_POSTLOOP]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone [[META6]]219;220 221entry:222 %len = load i32, ptr %a_len_ptr, !range !0223 br label %loop224 225loop:226 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]227 %idx.next = add nsw nuw i32 %idx, 1228 %abc = icmp ult i32 %idx, %len229 br i1 %abc, label %in.bounds, label %out.of.bounds230 231in.bounds:232 %addr = getelementptr i32, ptr %arr, i32 %idx233 store i32 0, ptr %addr234 %next = icmp ugt i32 %idx.next, 2147483648235 br i1 %next, label %exit, label %loop236 237out.of.bounds:238 ret void239 240exit:241 ret void242}243 244; Check SINT_MAX + 1, test is similar to test_02.245define void @test_04(ptr %arr, ptr %a_len_ptr) #0 {246; CHECK-LABEL: define void @test_04247; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {248; CHECK-NEXT: entry:249; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]250; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[LEN]], i32 1)251; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[UMAX]], -1252; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 -2147483648, [[EXIT_PRELOOP_AT]]253; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]254; CHECK: loop.preloop.preheader:255; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]256; CHECK: mainloop:257; CHECK-NEXT: br label [[LOOP:%.*]]258; CHECK: loop:259; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]260; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -1261; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]262; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]263; CHECK: in.bounds:264; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]265; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4266; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0267; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]268; CHECK: out.of.bounds.loopexit:269; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]270; CHECK: out.of.bounds.loopexit1:271; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]272; CHECK: out.of.bounds:273; CHECK-NEXT: ret void274; CHECK: exit.loopexit:275; CHECK-NEXT: br label [[EXIT:%.*]]276; CHECK: exit:277; CHECK-NEXT: ret void278; CHECK: loop.preloop:279; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -2147483648, [[LOOP_PRELOOP_PREHEADER]] ]280; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1281; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]282; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]283; CHECK: in.bounds.preloop:284; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]285; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4286; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0287; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]288; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone [[META6]]289; CHECK: preloop.exit.selector:290; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]291; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0292; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]293; CHECK: preloop.pseudo.exit:294; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]295; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]296; CHECK-NEXT: br label [[MAINLOOP]]297;298 299entry:300 %len = load i32, ptr %a_len_ptr, !range !0301 br label %loop302 303loop:304 %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]305 %idx.next = add i32 %idx, -1306 %abc = icmp ult i32 %idx, %len307 br i1 %abc, label %in.bounds, label %out.of.bounds308 309in.bounds:310 %addr = getelementptr i32, ptr %arr, i32 %idx311 store i32 0, ptr %addr312 %next = icmp ugt i32 %idx.next, 0313 br i1 %next, label %loop, label %exit314 315out.of.bounds:316 ret void317 318exit:319 ret void320}321 322; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.323define void @test_05(ptr %arr, ptr %a_len_ptr) #0 {324; CHECK-LABEL: define void @test_05325; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {326; CHECK-NEXT: entry:327; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]328; CHECK-NEXT: br label [[LOOP:%.*]]329; CHECK: loop:330; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]331; CHECK-NEXT: [[IDX_NEXT]] = add nuw nsw i32 [[IDX]], 1332; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]333; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]334; CHECK: in.bounds:335; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]336; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4337; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], -1338; CHECK-NEXT: br i1 [[NEXT]], label [[EXIT:%.*]], label [[LOOP]]339; CHECK: out.of.bounds:340; CHECK-NEXT: ret void341; CHECK: exit:342; CHECK-NEXT: ret void343;344 345entry:346 %len = load i32, ptr %a_len_ptr, !range !0347 br label %loop348 349loop:350 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]351 %idx.next = add nsw nuw i32 %idx, 1352 %abc = icmp ult i32 %idx, %len353 br i1 %abc, label %in.bounds, label %out.of.bounds354 355in.bounds:356 %addr = getelementptr i32, ptr %arr, i32 %idx357 store i32 0, ptr %addr358 %next = icmp ugt i32 %idx.next, 4294967295359 br i1 %next, label %exit, label %loop360 361out.of.bounds:362 ret void363 364exit:365 ret void366}367 368; Decreasing loop, UINT_MAX. Positive test.369define void @test_06(ptr %arr, ptr %a_len_ptr) #0 {370; CHECK-LABEL: define void @test_06371; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {372; CHECK-NEXT: entry:373; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]374; CHECK-NEXT: br i1 true, label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]375; CHECK: loop.preloop.preheader:376; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]377; CHECK: mainloop:378; CHECK-NEXT: br label [[LOOP:%.*]]379; CHECK: loop:380; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]381; CHECK-NEXT: [[IDX_NEXT]] = add nuw i32 [[IDX]], -1382; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[LEN]]383; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]384; CHECK: in.bounds:385; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]386; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4387; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 0388; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]389; CHECK: out.of.bounds.loopexit:390; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]391; CHECK: out.of.bounds.loopexit1:392; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]393; CHECK: out.of.bounds:394; CHECK-NEXT: ret void395; CHECK: exit.loopexit:396; CHECK-NEXT: br label [[EXIT:%.*]]397; CHECK: exit:398; CHECK-NEXT: ret void399; CHECK: loop.preloop:400; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ -1, [[LOOP_PRELOOP_PREHEADER]] ]401; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add nuw i32 [[IDX_PRELOOP]], -1402; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp ult i32 [[IDX_PRELOOP]], [[LEN]]403; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]404; CHECK: in.bounds.preloop:405; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]406; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4407; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0408; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 0409; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP10:![0-9]+]], !loop_constrainer.loop.clone [[META6]]410; CHECK: preloop.exit.selector:411; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]412; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 0413; CHECK-NEXT: br i1 [[TMP1]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]414; CHECK: preloop.pseudo.exit:415; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]416; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ -1, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]417; CHECK-NEXT: br label [[MAINLOOP]]418;419 420entry:421 %len = load i32, ptr %a_len_ptr, !range !0422 br label %loop423 424loop:425 %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]426 %idx.next = add nuw i32 %idx, -1427 %abc = icmp ult i32 %idx, %len428 br i1 %abc, label %in.bounds, label %out.of.bounds429 430in.bounds:431 %addr = getelementptr i32, ptr %arr, i32 %idx432 store i32 0, ptr %addr433 %next = icmp ugt i32 %idx.next, 0434 br i1 %next, label %loop, label %exit435 436out.of.bounds:437 ret void438 439exit:440 ret void441}442 443!0 = !{i32 0, i32 50}444;.445; CHECK: [[RNG0]] = !{i32 0, i32 50}446; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}447; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}448; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}449; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}450; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}451; CHECK: [[META6]] = !{}452; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}453; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META2]], [[META3]], [[META4]], [[META5]]}454; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META2]], [[META3]], [[META4]], [[META5]]}455; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META2]], [[META3]], [[META4]], [[META5]]}456;.457