499 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-LABEL: irce: in function test_01: constrained Loop at depth 1 containing:6; CHECK-LABEL: irce: in function test_02: constrained Loop at depth 1 containing:7; CHECK-LABEL: irce: in function test_03: constrained Loop at depth 1 containing:8; CHECK-LABEL: irce: in function test_04: constrained Loop at depth 1 containing:9; CHECK-LABEL: irce: in function test_05: constrained Loop at depth 1 containing:10 11; This test used to demonstrate a miscompile: the outer loop's IV iterates in12; range of [2, 400) and the range check is done against value 331. Due to a bug13; in range intersection IRCE manages to eliminate the range check without14; inserting a postloop, which is incorrect. We treat the range of this test as15; an unsigned range and are able to intersect ranges correctly and insert a16; postloop.17 18define void @test_01() {19; CHECK-LABEL: define void @test_01() {20; CHECK-NEXT: entry:21; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]22; CHECK: loop_header.preheader:23; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]24; CHECK: loop_header:25; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 2, [[LOOP_HEADER_PREHEADER]] ]26; CHECK-NEXT: [[IV_PREV:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER_PREHEADER]] ]27; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IV_PREV]], -128; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_SPLIT_US:%.*]], label [[EXIT_LOOPEXIT1:%.*]]29; CHECK: loop_header.split.us:30; CHECK-NEXT: br label [[INNER_LOOP:%.*]]31; CHECK: inner_loop:32; CHECK-NEXT: [[INNER_IV:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER_LOOP]] ]33; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 134; CHECK-NEXT: [[INNER_COND:%.*]] = icmp ult i32 [[INNER_IV_NEXT]], 3135; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_LOOP]], label [[RANGE_CHECK_BLOCK:%.*]]36; CHECK: exit.loopexit:37; CHECK-NEXT: br label [[EXIT:%.*]]38; CHECK: exit.loopexit1:39; CHECK-NEXT: br label [[EXIT]]40; CHECK: exit:41; CHECK-NEXT: ret void42; CHECK: range_check_block:43; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV]], 33144; CHECK-NEXT: br i1 true, label [[LOOP_LATCH]], label [[DEOPT_LOOPEXIT2:%.*]]45; CHECK: loop_latch:46; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 147; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 40048; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[IV_NEXT]], 33149; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]50; CHECK: main.exit.selector:51; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[LOOP_LATCH]] ]52; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ]53; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT_LCSSA]], 40054; CHECK-NEXT: br i1 [[TMP1]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT]]55; CHECK: main.pseudo.exit:56; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]57; CHECK-NEXT: [[IV_PREV_COPY:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]58; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]59; CHECK-NEXT: br label [[POSTLOOP:%.*]]60; CHECK: deopt.loopexit:61; CHECK-NEXT: br label [[DEOPT:%.*]]62; CHECK: deopt.loopexit2:63; CHECK-NEXT: br label [[DEOPT]]64; CHECK: deopt:65; CHECK-NEXT: ret void66; CHECK: postloop:67; CHECK-NEXT: br label [[LOOP_HEADER_POSTLOOP:%.*]]68; CHECK: loop_header.postloop:69; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[LOOP_LATCH_POSTLOOP:%.*]] ]70; CHECK-NEXT: [[IV_PREV_POSTLOOP:%.*]] = phi i32 [ [[IV_PREV_COPY]], [[POSTLOOP]] ], [ [[IV_POSTLOOP]], [[LOOP_LATCH_POSTLOOP]] ]71; CHECK-NEXT: [[TMP2_POSTLOOP:%.*]] = icmp sgt i32 [[IV_PREV_POSTLOOP]], -172; CHECK-NEXT: br i1 [[TMP2_POSTLOOP]], label [[LOOP_HEADER_SPLIT_US_POSTLOOP:%.*]], label [[EXIT_LOOPEXIT:%.*]]73; CHECK: loop_header.split.us.postloop:74; CHECK-NEXT: br label [[INNER_LOOP_POSTLOOP:%.*]]75; CHECK: inner_loop.postloop:76; CHECK-NEXT: [[INNER_IV_POSTLOOP:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US_POSTLOOP]] ], [ [[INNER_IV_NEXT_POSTLOOP:%.*]], [[INNER_LOOP_POSTLOOP]] ]77; CHECK-NEXT: [[INNER_IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[INNER_IV_POSTLOOP]], 178; CHECK-NEXT: [[INNER_COND_POSTLOOP:%.*]] = icmp ult i32 [[INNER_IV_NEXT_POSTLOOP]], 3179; CHECK-NEXT: br i1 [[INNER_COND_POSTLOOP]], label [[INNER_LOOP_POSTLOOP]], label [[RANGE_CHECK_BLOCK_POSTLOOP:%.*]]80; CHECK: range_check_block.postloop:81; CHECK-NEXT: [[RANGE_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], 33182; CHECK-NEXT: br i1 [[RANGE_CHECK_POSTLOOP]], label [[LOOP_LATCH_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]]83; CHECK: loop_latch.postloop:84; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 185; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp ult i32 [[IV_NEXT_POSTLOOP]], 40086; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP0:![0-9]+]], !loop_constrainer.loop.clone [[META5:![0-9]+]]87;88 89entry:90 br label %loop_header91 92loop_header: ; preds = %loop_latch, %entry93 %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]94 %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]95 %tmp2 = icmp sgt i32 %iv.prev, -196 br i1 %tmp2, label %loop_header.split.us, label %exit97 98loop_header.split.us: ; preds = %loop_header99 br label %inner_loop100 101inner_loop: ; preds = %inner_loop, %loop_header.split.us102 %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]103 %inner_iv_next = add nuw nsw i32 %inner_iv, 1104 %inner_cond = icmp ult i32 %inner_iv_next, 31105 br i1 %inner_cond, label %inner_loop, label %range_check_block106 107exit: ; preds = %loop_latch, %loop_header108 ret void109 110range_check_block: ; preds = %inner_loop111 %range_check = icmp slt i32 %iv, 331112 br i1 %range_check, label %loop_latch, label %deopt113 114loop_latch: ; preds = %range_check_block115 %iv_next = add i32 %iv, 1116 %loop_cond = icmp ult i32 %iv_next, 400117 br i1 %loop_cond, label %loop_header, label %exit118 119deopt: ; preds = %range_check_block120 ret void121}122 123; Similar to test_01, but here the range check is done against 450. No postloop124; is required.125 126define void @test_02() {127; CHECK-LABEL: define void @test_02() {128; CHECK-NEXT: entry:129; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]130; CHECK: loop_header:131; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]132; CHECK-NEXT: [[IV_PREV:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV]], [[LOOP_LATCH]] ]133; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IV_PREV]], -1134; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_SPLIT_US:%.*]], label [[EXIT:%.*]]135; CHECK: loop_header.split.us:136; CHECK-NEXT: br label [[INNER_LOOP:%.*]]137; CHECK: inner_loop:138; CHECK-NEXT: [[INNER_IV:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER_LOOP]] ]139; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1140; CHECK-NEXT: [[INNER_COND:%.*]] = icmp ult i32 [[INNER_IV_NEXT]], 31141; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_LOOP]], label [[RANGE_CHECK_BLOCK:%.*]]142; CHECK: exit:143; CHECK-NEXT: ret void144; CHECK: range_check_block:145; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV]], 450146; CHECK-NEXT: br i1 true, label [[LOOP_LATCH]], label [[DEOPT:%.*]]147; CHECK: loop_latch:148; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1149; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 400150; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP_HEADER]], label [[EXIT]]151; CHECK: deopt:152; CHECK-NEXT: ret void153;154 155entry:156 br label %loop_header157 158loop_header: ; preds = %loop_latch, %entry159 %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]160 %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]161 %tmp2 = icmp sgt i32 %iv.prev, -1162 br i1 %tmp2, label %loop_header.split.us, label %exit163 164loop_header.split.us: ; preds = %loop_header165 br label %inner_loop166 167inner_loop: ; preds = %inner_loop, %loop_header.split.us168 %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]169 %inner_iv_next = add nuw nsw i32 %inner_iv, 1170 %inner_cond = icmp ult i32 %inner_iv_next, 31171 br i1 %inner_cond, label %inner_loop, label %range_check_block172 173exit: ; preds = %loop_latch, %loop_header174 ret void175 176range_check_block: ; preds = %inner_loop177 %range_check = icmp slt i32 %iv, 450178 br i1 %range_check, label %loop_latch, label %deopt179 180loop_latch: ; preds = %range_check_block181 %iv_next = add i32 %iv, 1182 %loop_cond = icmp ult i32 %iv_next, 400183 br i1 %loop_cond, label %loop_header, label %exit184 185deopt: ; preds = %range_check_block186 ret void187}188 189; Range check is made against 0, so the safe iteration range is empty. IRCE190; should not apply to the inner loop. The condition %tmp2 can be eliminated.191 192define void @test_03() {193; CHECK-LABEL: define void @test_03() {194; CHECK-NEXT: entry:195; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]196; CHECK: loop_header:197; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]198; CHECK-NEXT: [[IV_PREV:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV]], [[LOOP_LATCH]] ]199; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IV_PREV]], -1200; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_SPLIT_US:%.*]], label [[EXIT:%.*]]201; CHECK: loop_header.split.us:202; CHECK-NEXT: br label [[INNER_LOOP:%.*]]203; CHECK: inner_loop:204; CHECK-NEXT: [[INNER_IV:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER_LOOP]] ]205; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1206; CHECK-NEXT: [[INNER_COND:%.*]] = icmp ult i32 [[INNER_IV_NEXT]], 31207; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_LOOP]], label [[RANGE_CHECK_BLOCK:%.*]]208; CHECK: exit:209; CHECK-NEXT: ret void210; CHECK: range_check_block:211; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV]], 0212; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[LOOP_LATCH]], label [[DEOPT:%.*]]213; CHECK: loop_latch:214; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1215; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 400216; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP_HEADER]], label [[EXIT]]217; CHECK: deopt:218; CHECK-NEXT: ret void219;220 221entry:222 br label %loop_header223 224loop_header: ; preds = %loop_latch, %entry225 %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]226 %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]227 %tmp2 = icmp sgt i32 %iv.prev, -1228 br i1 %tmp2, label %loop_header.split.us, label %exit229 230loop_header.split.us: ; preds = %loop_header231 br label %inner_loop232 233inner_loop: ; preds = %inner_loop, %loop_header.split.us234 %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]235 %inner_iv_next = add nuw nsw i32 %inner_iv, 1236 %inner_cond = icmp ult i32 %inner_iv_next, 31237 br i1 %inner_cond, label %inner_loop, label %range_check_block238 239exit: ; preds = %loop_latch, %loop_header240 ret void241 242range_check_block: ; preds = %inner_loop243 %range_check = icmp slt i32 %iv, 0244 br i1 %range_check, label %loop_latch, label %deopt245 246loop_latch: ; preds = %range_check_block247 %iv_next = add i32 %iv, 1248 %loop_cond = icmp ult i32 %iv_next, 400249 br i1 %loop_cond, label %loop_header, label %exit250 251deopt: ; preds = %range_check_block252 ret void253}254 255; We can also properly eliminate range check against %n which is not always256; known positive.257 258define void @test_04(ptr %p) {259; CHECK-LABEL: define void @test_04260; CHECK-SAME: (ptr [[P:%.*]]) {261; CHECK-NEXT: entry:262; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[P]], align 4263; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[N]], i32 0)264; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[SMIN]]265; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 -1)266; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[SMAX]], 1267; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[TMP0]], [[TMP1]]268; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP2]], i32 400)269; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.umax.i32(i32 [[UMIN]], i32 2)270; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 2, [[EXIT_MAINLOOP_AT]]271; CHECK-NEXT: br i1 [[TMP3]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]272; CHECK: loop_header.preheader:273; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]274; CHECK: loop_header:275; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 2, [[LOOP_HEADER_PREHEADER]] ]276; CHECK-NEXT: [[IV_PREV:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER_PREHEADER]] ]277; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IV_PREV]], -1278; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_SPLIT_US:%.*]], label [[EXIT_LOOPEXIT1:%.*]]279; CHECK: loop_header.split.us:280; CHECK-NEXT: br label [[INNER_LOOP:%.*]]281; CHECK: inner_loop:282; CHECK-NEXT: [[INNER_IV:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER_LOOP]] ]283; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1284; CHECK-NEXT: [[INNER_COND:%.*]] = icmp ult i32 [[INNER_IV_NEXT]], 31285; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_LOOP]], label [[RANGE_CHECK_BLOCK:%.*]]286; CHECK: exit.loopexit:287; CHECK-NEXT: br label [[EXIT:%.*]]288; CHECK: exit.loopexit1:289; CHECK-NEXT: br label [[EXIT]]290; CHECK: exit:291; CHECK-NEXT: ret void292; CHECK: range_check_block:293; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV]], [[N]]294; CHECK-NEXT: br i1 true, label [[LOOP_LATCH]], label [[DEOPT_LOOPEXIT2:%.*]]295; CHECK: loop_latch:296; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1297; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 400298; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]299; CHECK-NEXT: br i1 [[TMP4]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]300; CHECK: main.exit.selector:301; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[LOOP_LATCH]] ]302; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ]303; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[IV_NEXT_LCSSA]], 400304; CHECK-NEXT: br i1 [[TMP5]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT]]305; CHECK: main.pseudo.exit:306; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]307; CHECK-NEXT: [[IV_PREV_COPY:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]308; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]309; CHECK-NEXT: br label [[POSTLOOP:%.*]]310; CHECK: deopt.loopexit:311; CHECK-NEXT: br label [[DEOPT:%.*]]312; CHECK: deopt.loopexit2:313; CHECK-NEXT: br label [[DEOPT]]314; CHECK: deopt:315; CHECK-NEXT: ret void316; CHECK: postloop:317; CHECK-NEXT: br label [[LOOP_HEADER_POSTLOOP:%.*]]318; CHECK: loop_header.postloop:319; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[LOOP_LATCH_POSTLOOP:%.*]] ]320; CHECK-NEXT: [[IV_PREV_POSTLOOP:%.*]] = phi i32 [ [[IV_PREV_COPY]], [[POSTLOOP]] ], [ [[IV_POSTLOOP]], [[LOOP_LATCH_POSTLOOP]] ]321; CHECK-NEXT: [[TMP2_POSTLOOP:%.*]] = icmp sgt i32 [[IV_PREV_POSTLOOP]], -1322; CHECK-NEXT: br i1 [[TMP2_POSTLOOP]], label [[LOOP_HEADER_SPLIT_US_POSTLOOP:%.*]], label [[EXIT_LOOPEXIT:%.*]]323; CHECK: loop_header.split.us.postloop:324; CHECK-NEXT: br label [[INNER_LOOP_POSTLOOP:%.*]]325; CHECK: inner_loop.postloop:326; CHECK-NEXT: [[INNER_IV_POSTLOOP:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US_POSTLOOP]] ], [ [[INNER_IV_NEXT_POSTLOOP:%.*]], [[INNER_LOOP_POSTLOOP]] ]327; CHECK-NEXT: [[INNER_IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[INNER_IV_POSTLOOP]], 1328; CHECK-NEXT: [[INNER_COND_POSTLOOP:%.*]] = icmp ult i32 [[INNER_IV_NEXT_POSTLOOP]], 31329; CHECK-NEXT: br i1 [[INNER_COND_POSTLOOP]], label [[INNER_LOOP_POSTLOOP]], label [[RANGE_CHECK_BLOCK_POSTLOOP:%.*]]330; CHECK: range_check_block.postloop:331; CHECK-NEXT: [[RANGE_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[N]]332; CHECK-NEXT: br i1 [[RANGE_CHECK_POSTLOOP]], label [[LOOP_LATCH_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]]333; CHECK: loop_latch.postloop:334; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 1335; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp ult i32 [[IV_NEXT_POSTLOOP]], 400336; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP6:![0-9]+]], !loop_constrainer.loop.clone [[META5]]337;338 339entry:340 %n = load i32, ptr %p341 br label %loop_header342 343loop_header: ; preds = %loop_latch, %entry344 %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]345 %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]346 %tmp2 = icmp sgt i32 %iv.prev, -1347 br i1 %tmp2, label %loop_header.split.us, label %exit348 349loop_header.split.us: ; preds = %loop_header350 br label %inner_loop351 352inner_loop: ; preds = %inner_loop, %loop_header.split.us353 %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]354 %inner_iv_next = add nuw nsw i32 %inner_iv, 1355 %inner_cond = icmp ult i32 %inner_iv_next, 31356 br i1 %inner_cond, label %inner_loop, label %range_check_block357 358exit: ; preds = %loop_latch, %loop_header359 ret void360 361range_check_block: ; preds = %inner_loop362 %range_check = icmp slt i32 %iv, %n363 br i1 %range_check, label %loop_latch, label %deopt364 365loop_latch: ; preds = %range_check_block366 %iv_next = add i32 %iv, 1367 %loop_cond = icmp ult i32 %iv_next, 400368 br i1 %loop_cond, label %loop_header, label %exit369 370deopt: ; preds = %range_check_block371 ret void372}373 374; Same as test_04, but range guarantees that %n is positive. So we can safely375; intersect ranges (with insertion of postloop).376 377define void @test_05(ptr %p) {378; CHECK-LABEL: define void @test_05379; CHECK-SAME: (ptr [[P:%.*]]) {380; CHECK-NEXT: entry:381; CHECK-NEXT: [[N:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG7:![0-9]+]]382; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.umax.i32(i32 [[N]], i32 2)383; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 2, [[EXIT_MAINLOOP_AT]]384; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_HEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]385; CHECK: loop_header.preheader:386; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]387; CHECK: loop_header:388; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 2, [[LOOP_HEADER_PREHEADER]] ]389; CHECK-NEXT: [[IV_PREV:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ], [ 1, [[LOOP_HEADER_PREHEADER]] ]390; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IV_PREV]], -1391; CHECK-NEXT: br i1 true, label [[LOOP_HEADER_SPLIT_US:%.*]], label [[EXIT_LOOPEXIT1:%.*]]392; CHECK: loop_header.split.us:393; CHECK-NEXT: br label [[INNER_LOOP:%.*]]394; CHECK: inner_loop:395; CHECK-NEXT: [[INNER_IV:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER_LOOP]] ]396; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1397; CHECK-NEXT: [[INNER_COND:%.*]] = icmp ult i32 [[INNER_IV_NEXT]], 31398; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_LOOP]], label [[RANGE_CHECK_BLOCK:%.*]]399; CHECK: exit.loopexit:400; CHECK-NEXT: br label [[EXIT:%.*]]401; CHECK: exit.loopexit1:402; CHECK-NEXT: br label [[EXIT]]403; CHECK: exit:404; CHECK-NEXT: ret void405; CHECK: range_check_block:406; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV]], [[N]]407; CHECK-NEXT: br i1 true, label [[LOOP_LATCH]], label [[DEOPT_LOOPEXIT2:%.*]]408; CHECK: loop_latch:409; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1410; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 400411; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[IV_NEXT]], [[EXIT_MAINLOOP_AT]]412; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_HEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]413; CHECK: main.exit.selector:414; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[LOOP_LATCH]] ]415; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP_LATCH]] ]416; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[IV_NEXT_LCSSA]], 400417; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT]]418; CHECK: main.pseudo.exit:419; CHECK-NEXT: [[IV_COPY:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]420; CHECK-NEXT: [[IV_PREV_COPY:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]421; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 2, [[ENTRY]] ], [ [[IV_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]422; CHECK-NEXT: br label [[POSTLOOP:%.*]]423; CHECK: deopt.loopexit:424; CHECK-NEXT: br label [[DEOPT:%.*]]425; CHECK: deopt.loopexit2:426; CHECK-NEXT: br label [[DEOPT]]427; CHECK: deopt:428; CHECK-NEXT: ret void429; CHECK: postloop:430; CHECK-NEXT: br label [[LOOP_HEADER_POSTLOOP:%.*]]431; CHECK: loop_header.postloop:432; CHECK-NEXT: [[IV_POSTLOOP:%.*]] = phi i32 [ [[IV_COPY]], [[POSTLOOP]] ], [ [[IV_NEXT_POSTLOOP:%.*]], [[LOOP_LATCH_POSTLOOP:%.*]] ]433; CHECK-NEXT: [[IV_PREV_POSTLOOP:%.*]] = phi i32 [ [[IV_PREV_COPY]], [[POSTLOOP]] ], [ [[IV_POSTLOOP]], [[LOOP_LATCH_POSTLOOP]] ]434; CHECK-NEXT: [[TMP2_POSTLOOP:%.*]] = icmp sgt i32 [[IV_PREV_POSTLOOP]], -1435; CHECK-NEXT: br i1 [[TMP2_POSTLOOP]], label [[LOOP_HEADER_SPLIT_US_POSTLOOP:%.*]], label [[EXIT_LOOPEXIT:%.*]]436; CHECK: loop_header.split.us.postloop:437; CHECK-NEXT: br label [[INNER_LOOP_POSTLOOP:%.*]]438; CHECK: inner_loop.postloop:439; CHECK-NEXT: [[INNER_IV_POSTLOOP:%.*]] = phi i32 [ 1, [[LOOP_HEADER_SPLIT_US_POSTLOOP]] ], [ [[INNER_IV_NEXT_POSTLOOP:%.*]], [[INNER_LOOP_POSTLOOP]] ]440; CHECK-NEXT: [[INNER_IV_NEXT_POSTLOOP]] = add nuw nsw i32 [[INNER_IV_POSTLOOP]], 1441; CHECK-NEXT: [[INNER_COND_POSTLOOP:%.*]] = icmp ult i32 [[INNER_IV_NEXT_POSTLOOP]], 31442; CHECK-NEXT: br i1 [[INNER_COND_POSTLOOP]], label [[INNER_LOOP_POSTLOOP]], label [[RANGE_CHECK_BLOCK_POSTLOOP:%.*]]443; CHECK: range_check_block.postloop:444; CHECK-NEXT: [[RANGE_CHECK_POSTLOOP:%.*]] = icmp slt i32 [[IV_POSTLOOP]], [[N]]445; CHECK-NEXT: br i1 [[RANGE_CHECK_POSTLOOP]], label [[LOOP_LATCH_POSTLOOP]], label [[DEOPT_LOOPEXIT:%.*]]446; CHECK: loop_latch.postloop:447; CHECK-NEXT: [[IV_NEXT_POSTLOOP]] = add i32 [[IV_POSTLOOP]], 1448; CHECK-NEXT: [[LOOP_COND_POSTLOOP:%.*]] = icmp ult i32 [[IV_NEXT_POSTLOOP]], 400449; CHECK-NEXT: br i1 [[LOOP_COND_POSTLOOP]], label [[LOOP_HEADER_POSTLOOP]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP8:![0-9]+]], !loop_constrainer.loop.clone [[META5]]450;451 452entry:453 %n = load i32, ptr %p, !range !0454 br label %loop_header455 456loop_header: ; preds = %loop_latch, %entry457 %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]458 %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]459 %tmp2 = icmp sgt i32 %iv.prev, -1460 br i1 %tmp2, label %loop_header.split.us, label %exit461 462loop_header.split.us: ; preds = %loop_header463 br label %inner_loop464 465inner_loop: ; preds = %inner_loop, %loop_header.split.us466 %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]467 %inner_iv_next = add nuw nsw i32 %inner_iv, 1468 %inner_cond = icmp ult i32 %inner_iv_next, 31469 br i1 %inner_cond, label %inner_loop, label %range_check_block470 471exit: ; preds = %loop_latch, %loop_header472 ret void473 474range_check_block: ; preds = %inner_loop475 %range_check = icmp slt i32 %iv, %n476 br i1 %range_check, label %loop_latch, label %deopt477 478loop_latch: ; preds = %range_check_block479 %iv_next = add i32 %iv, 1480 %loop_cond = icmp ult i32 %iv_next, 400481 br i1 %loop_cond, label %loop_header, label %exit482 483deopt: ; preds = %range_check_block484 ret void485}486 487!0 = !{i32 0, i32 50}488;.489; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]]}490; CHECK: [[META1]] = !{!"llvm.loop.unroll.disable"}491; CHECK: [[META2]] = !{!"llvm.loop.vectorize.enable", i1 false}492; CHECK: [[META3]] = !{!"llvm.loop.licm_versioning.disable"}493; CHECK: [[META4]] = !{!"llvm.loop.distribute.enable", i1 false}494; CHECK: [[META5]] = !{}495; CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[META1]], [[META2]], [[META3]], [[META4]]}496; CHECK: [[RNG7]] = !{i32 0, i32 50}497; CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[META1]], [[META2]], [[META3]], [[META4]]}498;.499