991 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; 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: 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; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>12; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>13 14; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.15define void @test_01(ptr %arr, ptr %a_len_ptr) {16; CHECK-LABEL: define void @test_0117; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {18; CHECK-NEXT: entry:19; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]20; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]21; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]22; CHECK: loop.preheader:23; CHECK-NEXT: br label [[LOOP:%.*]]24; CHECK: loop:25; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]26; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 727; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]28; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]29; CHECK: in.bounds:30; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]31; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 432; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 10033; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]34; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]35; CHECK: main.exit.selector:36; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]37; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 10038; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]39; CHECK: main.pseudo.exit:40; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]41; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]42; CHECK-NEXT: br label [[POSTLOOP:%.*]]43; CHECK: out.of.bounds.loopexit:44; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]45; CHECK: out.of.bounds.loopexit1:46; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]47; CHECK: out.of.bounds:48; CHECK-NEXT: ret void49; CHECK: exit.loopexit:50; CHECK-NEXT: br label [[EXIT]]51; CHECK: exit:52; CHECK-NEXT: ret void53; CHECK: postloop:54; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]55; CHECK: loop.postloop:56; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]57; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 758; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]59; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]60; CHECK: in.bounds.postloop:61; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]62; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 463; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 10064; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !665;66 67entry:68 %len = load i32, ptr %a_len_ptr, !range !069 br label %loop70 71loop:72 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]73 %idx.next = add i32 %idx, 774 %abc = icmp slt i32 %idx, %len75 br i1 %abc, label %in.bounds, label %out.of.bounds76 77in.bounds:78 %addr = getelementptr i32, ptr %arr, i32 %idx79 store i32 0, ptr %addr80 %next = icmp slt i32 %idx.next, 10081 br i1 %next, label %loop, label %exit82 83out.of.bounds:84 ret void85 86exit:87 ret void88}89 90; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.91define void @test_02(ptr %arr, ptr %a_len_ptr) {92; CHECK-LABEL: define void @test_0293; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {94; CHECK-NEXT: entry:95; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]96; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]97; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]98; CHECK: loop.preheader:99; CHECK-NEXT: br label [[LOOP:%.*]]100; CHECK: loop:101; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]102; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7103; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]104; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]105; CHECK: in.bounds:106; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]107; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4108; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483640109; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]110; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]111; CHECK: main.exit.selector:112; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]113; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483640114; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]115; CHECK: main.pseudo.exit:116; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]117; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]118; CHECK-NEXT: br label [[POSTLOOP:%.*]]119; CHECK: out.of.bounds.loopexit:120; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]121; CHECK: out.of.bounds.loopexit1:122; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]123; CHECK: out.of.bounds:124; CHECK-NEXT: ret void125; CHECK: exit.loopexit:126; CHECK-NEXT: br label [[EXIT]]127; CHECK: exit:128; CHECK-NEXT: ret void129; CHECK: postloop:130; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]131; CHECK: loop.postloop:132; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]133; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7134; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]135; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]136; CHECK: in.bounds.postloop:137; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]138; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4139; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483640140; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6141;142 143entry:144 %len = load i32, ptr %a_len_ptr, !range !0145 br label %loop146 147loop:148 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]149 %idx.next = add i32 %idx, 7150 %abc = icmp slt i32 %idx, %len151 br i1 %abc, label %in.bounds, label %out.of.bounds152 153in.bounds:154 %addr = getelementptr i32, ptr %arr, i32 %idx155 store i32 0, ptr %addr156 %next = icmp slt i32 %idx.next, 2147483640157 br i1 %next, label %loop, label %exit158 159out.of.bounds:160 ret void161 162exit:163 ret void164}165 166; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest167; value of Len for which IRCE is allowed.168define void @test_03(ptr %arr, ptr %a_len_ptr) {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 [[RNG8:![0-9]+]]173; CHECK-NEXT: [[TMP0:%.*]] = icmp slt 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 nsw i32 [[IDX]], 7180; CHECK-NEXT: [[ABC:%.*]] = icmp slt 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 slt i32 [[IDX_NEXT]], 2147483647186; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]187; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]188; CHECK: main.exit.selector:189; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]190; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647191; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]192; CHECK: main.pseudo.exit:193; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]194; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]195; CHECK-NEXT: br label [[POSTLOOP:%.*]]196; CHECK: out.of.bounds.loopexit:197; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]198; CHECK: out.of.bounds.loopexit1:199; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]200; CHECK: out.of.bounds:201; CHECK-NEXT: ret void202; CHECK: exit.loopexit:203; CHECK-NEXT: br label [[EXIT]]204; CHECK: exit:205; CHECK-NEXT: ret void206; CHECK: postloop:207; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]208; CHECK: loop.postloop:209; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]210; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7211; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]212; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]213; CHECK: in.bounds.postloop:214; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]215; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4216; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647217; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP9:![0-9]+]], !loop_constrainer.loop.clone !6218;219 220entry:221 %len = load i32, ptr %a_len_ptr, !range !1222 br label %loop223 224loop:225 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]226 %idx.next = add i32 %idx, 7227 %abc = icmp slt i32 %idx, %len228 br i1 %abc, label %in.bounds, label %out.of.bounds229 230in.bounds:231 %addr = getelementptr i32, ptr %arr, i32 %idx232 store i32 0, ptr %addr233 %next = icmp slt i32 %idx.next, 2147483647234 br i1 %next, label %loop, label %exit235 236out.of.bounds:237 ret void238 239exit:240 ret void241}242 243; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed244; because the branch would fail once idx.next == MAX_INT - 1 keeping the245; access in bounds.246define void @test_04(ptr %arr, ptr %a_len_ptr) {247; CHECK-LABEL: define void @test_04248; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {249; CHECK-NEXT: entry:250; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG10:![0-9]+]]251; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]252; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]253; CHECK: loop.preheader:254; CHECK-NEXT: br label [[LOOP:%.*]]255; CHECK: loop:256; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]257; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 7258; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]259; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]260; CHECK: in.bounds:261; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]262; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4263; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647264; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]265; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]266; CHECK: main.exit.selector:267; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]268; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647269; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]270; CHECK: main.pseudo.exit:271; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]272; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]273; CHECK-NEXT: br label [[POSTLOOP:%.*]]274; CHECK: out.of.bounds.loopexit:275; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]276; CHECK: out.of.bounds.loopexit1:277; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]278; CHECK: out.of.bounds:279; CHECK-NEXT: ret void280; CHECK: exit.loopexit:281; CHECK-NEXT: br label [[EXIT]]282; CHECK: exit:283; CHECK-NEXT: ret void284; CHECK: postloop:285; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]286; CHECK: loop.postloop:287; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]288; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 7289; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]290; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]291; CHECK: in.bounds.postloop:292; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]293; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4294; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647295; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP11:![0-9]+]], !loop_constrainer.loop.clone !6296;297 298 299 300entry:301 %len = load i32, ptr %a_len_ptr, !range !2302 br label %loop303 304loop:305 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]306 %idx.next = add i32 %idx, 7307 %abc = icmp slt i32 %idx, %len308 br i1 %abc, label %in.bounds, label %out.of.bounds309 310in.bounds:311 %addr = getelementptr i32, ptr %arr, i32 %idx312 store i32 0, ptr %addr313 %next = icmp slt i32 %idx.next, 2147483647314 br i1 %next, label %loop, label %exit315 316out.of.bounds:317 ret void318 319exit:320 ret void321}322 323; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.324define void @test_05(ptr %arr, ptr %a_len_ptr) {325; CHECK-LABEL: define void @test_05326; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {327; CHECK-NEXT: entry:328; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]329; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1330; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 100, [[EXIT_PRELOOP_AT]]331; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]332; CHECK: loop.preloop.preheader:333; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]334; CHECK: mainloop:335; CHECK-NEXT: br label [[LOOP:%.*]]336; CHECK: loop:337; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]338; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], -7339; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]340; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]341; CHECK: in.bounds:342; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]343; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4344; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_NEXT]], -1345; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]346; CHECK: out.of.bounds.loopexit:347; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]348; CHECK: out.of.bounds.loopexit1:349; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]350; CHECK: out.of.bounds:351; CHECK-NEXT: ret void352; CHECK: exit.loopexit:353; CHECK-NEXT: br label [[EXIT:%.*]]354; CHECK: exit:355; CHECK-NEXT: ret void356; CHECK: loop.preloop:357; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 100, [[LOOP_PRELOOP_PREHEADER]] ]358; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7359; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]360; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]361; CHECK: in.bounds.preloop:362; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]363; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4364; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1365; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]366; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP12:![0-9]+]], !loop_constrainer.loop.clone !6367; CHECK: preloop.exit.selector:368; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]369; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP_LCSSA]], -1370; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]371; CHECK: preloop.pseudo.exit:372; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]373; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 100, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]374; CHECK-NEXT: br label [[MAINLOOP]]375;376 377entry:378 %len = load i32, ptr %a_len_ptr, !range !0379 br label %loop380 381loop:382 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]383 %idx.next = add i32 %idx, -7384 %abc = icmp slt i32 %idx, %len385 br i1 %abc, label %in.bounds, label %out.of.bounds386 387in.bounds:388 %addr = getelementptr i32, ptr %arr, i32 %idx389 store i32 0, ptr %addr390 %next = icmp sgt i32 %idx.next, -1391 br i1 %next, label %loop, label %exit392 393out.of.bounds:394 ret void395 396exit:397 ret void398}399 400; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.401define void @test_06(ptr %arr, ptr %a_len_ptr) {402; CHECK-LABEL: define void @test_06403; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {404; CHECK-NEXT: entry:405; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13:![0-9]+]]406; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1407; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483640, [[EXIT_PRELOOP_AT]]408; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]409; CHECK: loop.preloop.preheader:410; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]411; CHECK: mainloop:412; CHECK-NEXT: br label [[LOOP:%.*]]413; CHECK: loop:414; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]415; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7416; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]417; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]418; CHECK: in.bounds:419; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]420; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4421; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6422; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]423; CHECK: out.of.bounds.loopexit:424; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]425; CHECK: out.of.bounds.loopexit1:426; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]427; CHECK: out.of.bounds:428; CHECK-NEXT: ret void429; CHECK: exit.loopexit:430; CHECK-NEXT: br label [[EXIT:%.*]]431; CHECK: exit:432; CHECK-NEXT: ret void433; CHECK: loop.preloop:434; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483640, [[LOOP_PRELOOP_PREHEADER]] ]435; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7436; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]437; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]438; CHECK: in.bounds.preloop:439; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]440; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4441; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6442; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]443; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP14:![0-9]+]], !loop_constrainer.loop.clone !6444; CHECK: preloop.exit.selector:445; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]446; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6447; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]448; CHECK: preloop.pseudo.exit:449; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]450; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483640, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]451; CHECK-NEXT: br label [[MAINLOOP]]452;453 454entry:455 %len = load i32, ptr %a_len_ptr, !range !3456 br label %loop457 458loop:459 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]460 %idx.next = add i32 %idx, -7461 %abc = icmp slt i32 %idx, %len462 br i1 %abc, label %in.bounds, label %out.of.bounds463 464in.bounds:465 %addr = getelementptr i32, ptr %arr, i32 %idx466 store i32 0, ptr %addr467 %next = icmp ugt i32 %idx.next, 6468 br i1 %next, label %loop, label %exit469 470out.of.bounds:471 ret void472 473exit:474 ret void475}476 477; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed,478; because we can cross the 0 border.479define void @test_07(ptr %arr, ptr %a_len_ptr) {480; CHECK-LABEL: define void @test_07481; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {482; CHECK-NEXT: entry:483; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]484; CHECK-NEXT: br label [[LOOP:%.*]]485; CHECK: loop:486; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 2147483640, [[ENTRY:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]487; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7488; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]489; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]]490; CHECK: in.bounds:491; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]492; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4493; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 5494; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT:%.*]]495; CHECK: out.of.bounds:496; CHECK-NEXT: ret void497; CHECK: exit:498; CHECK-NEXT: ret void499;500 501entry:502 %len = load i32, ptr %a_len_ptr, !range !3503 br label %loop504 505loop:506 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]507 %idx.next = add i32 %idx, -7508 %abc = icmp slt i32 %idx, %len509 br i1 %abc, label %in.bounds, label %out.of.bounds510 511in.bounds:512 %addr = getelementptr i32, ptr %arr, i32 %idx513 store i32 0, ptr %addr514 %next = icmp ugt i32 %idx.next, 5515 br i1 %next, label %loop, label %exit516 517out.of.bounds:518 ret void519 520exit:521 ret void522}523 524; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.525define void @test_08(ptr %arr, ptr %a_len_ptr) {526; CHECK-LABEL: define void @test_08527; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {528; CHECK-NEXT: entry:529; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG13]]530; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[LEN]], -1531; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 2147483647, [[EXIT_PRELOOP_AT]]532; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]533; CHECK: loop.preloop.preheader:534; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]]535; CHECK: mainloop:536; CHECK-NEXT: br label [[LOOP:%.*]]537; CHECK: loop:538; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]539; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], -7540; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]541; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]542; CHECK: in.bounds:543; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]544; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4545; CHECK-NEXT: [[NEXT:%.*]] = icmp ugt i32 [[IDX_NEXT]], 6546; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]547; CHECK: out.of.bounds.loopexit:548; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]549; CHECK: out.of.bounds.loopexit1:550; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]551; CHECK: out.of.bounds:552; CHECK-NEXT: ret void553; CHECK: exit.loopexit:554; CHECK-NEXT: br label [[EXIT:%.*]]555; CHECK: exit:556; CHECK-NEXT: ret void557; CHECK: loop.preloop:558; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483647, [[LOOP_PRELOOP_PREHEADER]] ]559; CHECK-NEXT: [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -7560; CHECK-NEXT: [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]561; CHECK-NEXT: br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]562; CHECK: in.bounds.preloop:563; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]564; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4565; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], 6566; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP]], [[EXIT_PRELOOP_AT]]567; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP15:![0-9]+]], !loop_constrainer.loop.clone !6568; CHECK: preloop.exit.selector:569; CHECK-NEXT: [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]570; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[IDX_NEXT_PRELOOP_LCSSA]], 6571; CHECK-NEXT: br i1 [[TMP2]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]572; CHECK: preloop.pseudo.exit:573; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]574; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2147483647, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]575; CHECK-NEXT: br label [[MAINLOOP]]576;577 578entry:579 %len = load i32, ptr %a_len_ptr, !range !3580 br label %loop581 582loop:583 %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]584 %idx.next = add i32 %idx, -7585 %abc = icmp slt i32 %idx, %len586 br i1 %abc, label %in.bounds, label %out.of.bounds587 588in.bounds:589 %addr = getelementptr i32, ptr %arr, i32 %idx590 store i32 0, ptr %addr591 %next = icmp ugt i32 %idx.next, 6592 br i1 %next, label %loop, label %exit593 594out.of.bounds:595 ret void596 597exit:598 ret void599}600 601; IRCE is legal here.602; Here how it is done if the step was 1: https://godbolt.org/z/jEqWaseWc603; It is also legal for step 4. Proof:604; - Capacity check ensures that iv < limit <= SINT_MAX - 3, meaning that605; iv <= SINT_MAX - 4.606; - Because of this, iv.next is always computed w/o overflow.607; - The loop goes to backedge as long as iv < capacity - 3 && iv < num.elements - 4.608; - So iterating up to smin(capacity - 3, num.elements - 4) should be safe.609; - Proof by alive2: https://alive2.llvm.org/ce/z/vEhMxa610define i32 @test_09(ptr %p, ptr %capacity_p, ptr %num_elements_p) {611; CHECK-LABEL: define i32 @test_09612; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {613; CHECK-NEXT: entry:614; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16:![0-9]+]]615; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]616; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3617; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3618; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646619; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)620; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]621; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0)622; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)623; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1624; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]625; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]])626; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)627; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]628; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]629; CHECK: loop.preheader:630; CHECK-NEXT: br label [[LOOP:%.*]]631; CHECK: loop:632; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]633; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]]634; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17:![0-9]+]]635; CHECK: backedge:636; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64637; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]638; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4639; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4640; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]641; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]642; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]643; CHECK: main.exit.selector:644; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]645; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]646; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]647; CHECK-NEXT: br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]648; CHECK: main.pseudo.exit:649; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]650; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]651; CHECK-NEXT: br label [[POSTLOOP:%.*]]652; CHECK: exit.loopexit:653; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]654; CHECK-NEXT: br label [[EXIT]]655; CHECK: exit:656; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]657; CHECK-NEXT: ret i32 [[IV_LCSSA1]]658; CHECK: out_of_bounds.loopexit:659; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]660; CHECK: out_of_bounds.loopexit5:661; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]662; CHECK: out_of_bounds:663; CHECK-NEXT: ret i32 -1664; CHECK: postloop:665; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]666; CHECK: loop.postloop:667; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]668; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]]669; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]670; CHECK: backedge.postloop:671; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64672; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]673; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4674; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4675; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]676; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP18:![0-9]+]], !loop_constrainer.loop.clone !6677;678entry:679 %capacity = load i32, ptr %capacity_p, !range !4680 %num_elements = load i32, ptr %num_elements_p, !range !4681 %limit = sub i32 %capacity, 3682 br label %loop683 684loop:685 %iv = phi i32 [0, %entry], [%iv.next, %backedge]686 %capacity_check = icmp slt i32 %iv, %limit687 br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5688 689backedge:690 %iv.wide = zext i32 %iv to i64691 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide692 store i32 1, ptr %el.ptr693 %iv.next = add nuw nsw i32 %iv, 4694 %loop_cond = icmp slt i32 %iv.next, %num_elements695 br i1 %loop_cond, label %loop, label %exit696 697exit:698 ret i32 %iv699 700out_of_bounds:701 ret i32 -1702}703 704; Same as test_09 but range check comparison is inversed.705; IRCE is allowed.706define i32 @test_10(ptr %p, ptr %capacity_p, ptr %num_elements_p) {707; CHECK-LABEL: define i32 @test_10708; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {709; CHECK-NEXT: entry:710; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]]711; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]712; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 3713; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3714; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646715; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)716; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]717; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LIMIT]], i32 0)718; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)719; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[SMAX2]], 1720; CHECK-NEXT: [[TMP4:%.*]] = mul i32 [[TMP2]], [[TMP3]]721; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP4]])722; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)723; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]724; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]725; CHECK: loop.preheader:726; CHECK-NEXT: br label [[LOOP:%.*]]727; CHECK: loop:728; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]729; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp slt i32 [[IV]], [[LIMIT]]730; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]]731; CHECK: backedge:732; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64733; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]734; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4735; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4736; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]737; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]738; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]739; CHECK: main.exit.selector:740; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]741; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]742; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]743; CHECK-NEXT: br i1 [[TMP7]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]744; CHECK: main.pseudo.exit:745; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]746; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]747; CHECK-NEXT: br label [[POSTLOOP:%.*]]748; CHECK: exit.loopexit:749; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]750; CHECK-NEXT: br label [[EXIT]]751; CHECK: exit:752; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]753; CHECK-NEXT: ret i32 [[IV_LCSSA1]]754; CHECK: out_of_bounds.loopexit:755; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]756; CHECK: out_of_bounds.loopexit5:757; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]758; CHECK: out_of_bounds:759; CHECK-NEXT: ret i32 -1760; CHECK: postloop:761; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]762; CHECK: loop.postloop:763; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]764; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[LIMIT]]765; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]766; CHECK: backedge.postloop:767; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64768; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]769; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4770; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4771; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]772; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP19:![0-9]+]], !loop_constrainer.loop.clone !6773;774entry:775 %capacity = load i32, ptr %capacity_p, !range !4776 %num_elements = load i32, ptr %num_elements_p, !range !4777 %limit = sub i32 %capacity, 3778 br label %loop779 780loop:781 %iv = phi i32 [0, %entry], [%iv.next, %backedge]782 %capacity_check = icmp sge i32 %iv, %limit783 br i1 %capacity_check, label %out_of_bounds, label %backedge, !prof !6784 785backedge:786 %iv.wide = zext i32 %iv to i64787 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide788 store i32 1, ptr %el.ptr789 %iv.next = add nuw nsw i32 %iv, 4790 %loop_cond = icmp slt i32 %iv.next, %num_elements791 br i1 %loop_cond, label %loop, label %exit792 793exit:794 ret i32 %iv795 796out_of_bounds:797 ret i32 -1798}799 800; Same as test_09 but range check comparison is non-strict:801; IRCE is allowed.802define i32 @test_11(ptr %p, ptr %capacity_p, ptr %num_elements_p) {803; CHECK-LABEL: define i32 @test_11804; CHECK-SAME: (ptr [[P:%.*]], ptr [[CAPACITY_P:%.*]], ptr [[NUM_ELEMENTS_P:%.*]]) {805; CHECK-NEXT: entry:806; CHECK-NEXT: [[CAPACITY:%.*]] = load i32, ptr [[CAPACITY_P]], align 4, !range [[RNG16]]807; CHECK-NEXT: [[NUM_ELEMENTS:%.*]] = load i32, ptr [[NUM_ELEMENTS_P]], align 4, !range [[RNG16]]808; CHECK-NEXT: [[LIMIT:%.*]] = sub i32 [[CAPACITY]], 4809; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[CAPACITY]], -3810; CHECK-NEXT: [[TMP1:%.*]] = add nuw i32 [[CAPACITY]], 2147483646811; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0)812; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[SMAX]]813; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[CAPACITY]], -3814; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[TMP3]], i32 0)815; CHECK-NEXT: [[SMAX2:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)816; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[SMAX2]], 1817; CHECK-NEXT: [[TMP5:%.*]] = mul i32 [[TMP2]], [[TMP4]]818; CHECK-NEXT: [[SMIN3:%.*]] = call i32 @llvm.smin.i32(i32 [[NUM_ELEMENTS]], i32 [[TMP5]])819; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN3]], i32 0)820; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]821; CHECK-NEXT: br i1 [[TMP6]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]822; CHECK: loop.preheader:823; CHECK-NEXT: br label [[LOOP:%.*]]824; CHECK: loop:825; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]826; CHECK-NEXT: [[CAPACITY_CHECK:%.*]] = icmp sle i32 [[IV]], [[LIMIT]]827; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[OUT_OF_BOUNDS_LOOPEXIT5:%.*]], !prof [[PROF17]]828; CHECK: backedge:829; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64830; CHECK-NEXT: [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE]]831; CHECK-NEXT: store i32 1, ptr [[EL_PTR]], align 4832; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 4833; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[NUM_ELEMENTS]]834; CHECK-NEXT: [[TMP7:%.*]] = icmp slt i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]835; CHECK-NEXT: br i1 [[TMP7]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]836; CHECK: main.exit.selector:837; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]838; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]839; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i32 [[IV_NEXT_LCSSA]], [[NUM_ELEMENTS]]840; CHECK-NEXT: br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]841; CHECK: main.pseudo.exit:842; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]843; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]844; CHECK-NEXT: br label [[POSTLOOP:%.*]]845; CHECK: exit.loopexit:846; CHECK-NEXT: [[IV_LCSSA1_PH:%.*]] = phi i32 [ [[IV_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP:%.*]] ]847; CHECK-NEXT: br label [[EXIT]]848; CHECK: exit:849; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ], [ [[IV_LCSSA1_PH]], [[EXIT_LOOPEXIT:%.*]] ]850; CHECK-NEXT: ret i32 [[IV_LCSSA1]]851; CHECK: out_of_bounds.loopexit:852; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]]853; CHECK: out_of_bounds.loopexit5:854; CHECK-NEXT: br label [[OUT_OF_BOUNDS]]855; CHECK: out_of_bounds:856; CHECK-NEXT: ret i32 -1857; CHECK: postloop:858; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]]859; CHECK: loop.postloop:860; CHECK-NEXT: [[IV_POSTLOOP]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[BACKEDGE_POSTLOOP]] ]861; CHECK-NEXT: [[CAPACITY_CHECK_POSTLOOP:%.*]] = icmp sle i32 [[IV_POSTLOOP]], [[LIMIT]]862; CHECK-NEXT: br i1 [[CAPACITY_CHECK_POSTLOOP]], label [[BACKEDGE_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof [[PROF17]]863; CHECK: backedge.postloop:864; CHECK-NEXT: [[IV_WIDE_POSTLOOP:%.*]] = zext i32 [[IV_POSTLOOP]] to i64865; CHECK-NEXT: [[EL_PTR_POSTLOOP:%.*]] = getelementptr i32, ptr [[P]], i64 [[IV_WIDE_POSTLOOP]]866; CHECK-NEXT: store i32 1, ptr [[EL_PTR_POSTLOOP]], align 4867; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[IV_POSTLOOP]], 4868; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp slt i32 [[IV_NEXT_POSTLOOP]], [[NUM_ELEMENTS]]869; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP20:![0-9]+]], !loop_constrainer.loop.clone !6870;871entry:872 %capacity = load i32, ptr %capacity_p, !range !4873 %num_elements = load i32, ptr %num_elements_p, !range !4874 %limit = sub i32 %capacity, 4875 br label %loop876 877loop:878 %iv = phi i32 [0, %entry], [%iv.next, %backedge]879 %capacity_check = icmp sle i32 %iv, %limit880 br i1 %capacity_check, label %backedge, label %out_of_bounds, !prof !5881 882backedge:883 %iv.wide = zext i32 %iv to i64884 %el.ptr = getelementptr i32, ptr %p, i64 %iv.wide885 store i32 1, ptr %el.ptr886 %iv.next = add nuw nsw i32 %iv, 4887 %loop_cond = icmp slt i32 %iv.next, %num_elements888 br i1 %loop_cond, label %loop, label %exit889 890exit:891 ret i32 %iv892 893out_of_bounds:894 ret i32 -1895}896 897; Indvar base is non-overflowing binary 'or':898; check that IRCE isn't trying to add NSW flag on it.899define i32 @binop_or_is_iv_base(ptr %p, i32 %end) {900; CHECK-LABEL: define i32 @binop_or_is_iv_base901; CHECK-SAME: (ptr [[P:%.*]], i32 [[END:%.*]]) {902; CHECK-NEXT: entry:903; CHECK-NEXT: [[N:%.*]] = load atomic i32, ptr [[P]] unordered, align 8, !range [[RNG8]]904; CHECK-NEXT: [[CMP0:%.*]] = icmp sgt i32 [[END]], 7905; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[COMMON_RET:%.*]]906; CHECK: loop.header.preheader:907; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[N]], 7908; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[END]], i32 [[TMP0]])909; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 7)910; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 7, [[EXIT_MAINLOOP_AT]]911; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_HEADER_PREHEADER1:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]912; CHECK: loop.header.preheader1:913; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]914; CHECK: loop.header:915; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_ADD:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_HEADER_PREHEADER1]] ]916; CHECK-NEXT: [[CHECK:%.*]] = icmp ult i32 [[IV]], [[N]]917; CHECK-NEXT: br i1 true, label [[GUARDED]], label [[DEOPT_LOOPEXIT2:%.*]]918; CHECK: guarded:919; CHECK-NEXT: [[IV_ADD]] = add i32 [[IV]], 8920; CHECK-NEXT: [[IV_OR:%.*]] = or disjoint i32 [[IV_ADD]], 7921; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_OR]], [[END]]922; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IV_OR]], [[EXIT_MAINLOOP_AT]]923; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]924; CHECK: main.exit.selector:925; CHECK-NEXT: [[IV_ADD_LCSSA:%.*]] = phi i32 [ [[IV_ADD]], [[GUARDED]] ]926; CHECK-NEXT: [[IV_OR_LCSSA:%.*]] = phi i32 [ [[IV_OR]], [[GUARDED]] ]927; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[IV_OR_LCSSA]], [[END]]928; CHECK-NEXT: br i1 [[TMP3]], label [[MAIN_PSEUDO_EXIT]], label [[COMMON_RET_LOOPEXIT:%.*]]929; CHECK: main.pseudo.exit:930; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 0, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_ADD_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]931; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 7, [[LOOP_HEADER_PREHEADER]] ], [ [[IV_OR_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]932; CHECK-NEXT: br label [[POSTLOOP:%.*]]933; CHECK: deopt.loopexit:934; CHECK-NEXT: br label [[DEOPT:%.*]]935; CHECK: deopt.loopexit2:936; CHECK-NEXT: br label [[DEOPT]]937; CHECK: deopt:938; CHECK-NEXT: [[RV:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ]939; CHECK-NEXT: ret i32 [[RV]]940; CHECK: common.ret.loopexit.loopexit:941; CHECK-NEXT: br label [[COMMON_RET_LOOPEXIT]]942; CHECK: common.ret.loopexit:943; CHECK-NEXT: br label [[COMMON_RET]]944; CHECK: common.ret:945; CHECK-NEXT: ret i32 [[END]]946; CHECK: postloop:947; CHECK-NEXT: br label [[LOOP_HEADER_POSTLOOP:%.*]]948; CHECK: loop.header.postloop:949; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_ADD_POSTLOOP:%.*]], [[GUARDED_POSTLOOP:%.*]] ], [ [[IV_COPY]], [[POSTLOOP]] ]950; CHECK-NEXT: [[CHECK_POSTLOOP:%.*]] = icmp ult i32 [[IV_POSTLOOP]], [[N]]951; CHECK-NEXT: br i1 [[CHECK_POSTLOOP]], label [[GUARDED_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]]952; CHECK: guarded.postloop:953; CHECK-NEXT: [[IV_ADD_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 8954; CHECK-NEXT: [[IV_OR_POSTLOOP:%.*]] = or disjoint i32 [[IV_ADD_POSTLOOP]], 7955; CHECK-NEXT: [[CMP_POSTLOOP:%.*]] = icmp slt i32 [[IV_OR_POSTLOOP]], [[END]]956; CHECK-NEXT: br i1 [[CMP_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[COMMON_RET_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP21:![0-9]+]], !loop_constrainer.loop.clone !6957;958entry:959 %n = load atomic i32, ptr %p unordered, align 8, !range !1960 %cmp0 = icmp sgt i32 %end, 7961 br i1 %cmp0, label %loop.header, label %common.ret962 963loop.header:964 %iv = phi i32 [ %iv.add, %guarded ], [ 0, %entry ]965 %check = icmp ult i32 %iv, %n966 br i1 %check, label %guarded, label %deopt967 968guarded:969 %iv.add = add i32 %iv, 8970 %iv.or = or disjoint i32 %iv.add, 7971 %cmp = icmp slt i32 %iv.or, %end972 br i1 %cmp, label %loop.header, label %common.ret973 974deopt:975 %rv = call i32 (...) @llvm.experimental.deoptimize.i32(i32 13) [ "deopt"() ]976 ret i32 %rv977 978common.ret:979 ret i32 %end980}981 982declare i32 @llvm.experimental.deoptimize.i32(...)983 984!0 = !{i32 0, i32 50}985!1 = !{i32 0, i32 2147483640}986!2 = !{i32 0, i32 2147483641}987!3 = !{i32 10, i32 50}988!4 = !{i32 1, i32 2147483648}989!5 = !{!"branch_weights", i32 1000, i32 1}990!6 = !{!"branch_weights", i32 1, i32 1000}991