1; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s 2; RUN: opt -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s | FileCheck %s 3 4define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) { 5; CHECK-LABEL: @f_0( 6 7; CHECK: loop.preheader: 8; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len 9; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n 10; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_safe_range_end]], [[not_n]] 11; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_safe_range_end]], i32 [[not_n]] 12; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]] 13; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0 14; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0 15; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]] 16; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit 17 18; CHECK: loop.preheader2: 19; CHECK: br label %loop 20 21 entry: 22 %len = load i32, i32* %a_len_ptr, !range !0 23 %first.itr.check = icmp sgt i32 %n, 0 24 br i1 %first.itr.check, label %loop, label %exit 25 26 loop: 27 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 28 %idx.next = add i32 %idx, 1 29 %idx.for.abc = add i32 %idx, 4 30 %abc.actual = icmp slt i32 %idx.for.abc, %len 31 %cond = load volatile i1, i1* %cond_buf 32 %abc = and i1 %cond, %abc.actual 33 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 34 35; CHECK: loop: 36; CHECK: %cond = load volatile i1, i1* %cond_buf 37; CHECK: %abc = and i1 %cond, true 38; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit3, !prof !1 39 40; CHECK: out.of.bounds.loopexit: 41; CHECK: br label %out.of.bounds 42 43 in.bounds: 44 %addr = getelementptr i32, i32* %arr, i32 %idx.for.abc 45 store i32 0, i32* %addr 46 %next = icmp slt i32 %idx.next, %n 47 br i1 %next, label %loop, label %exit 48 49 out.of.bounds: 50 ret void 51 52 exit: 53 ret void 54} 55 56define void @f_1( 57 i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) { 58; CHECK-LABEL: @f_1( 59 60; CHECK: loop.preheader: 61; CHECK: [[not_len_b:[^ ]+]] = sub i32 -1, %len.b 62; CHECK: [[not_len_a:[^ ]+]] = sub i32 -1, %len.a 63; CHECK: [[smax_not_len_cond:[^ ]+]] = icmp sgt i32 [[not_len_b]], [[not_len_a]] 64; CHECK: [[smax_not_len:[^ ]+]] = select i1 [[smax_not_len_cond]], i32 [[not_len_b]], i32 [[not_len_a]] 65; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n 66; CHECK: [[not_upper_limit_cond_loclamp:[^ ]+]] = icmp sgt i32 [[smax_not_len]], [[not_n]] 67; CHECK: [[not_upper_limit_loclamp:[^ ]+]] = select i1 [[not_upper_limit_cond_loclamp]], i32 [[smax_not_len]], i32 [[not_n]] 68; CHECK: [[upper_limit_loclamp:[^ ]+]] = sub i32 -1, [[not_upper_limit_loclamp]] 69; CHECK: [[upper_limit_cmp:[^ ]+]] = icmp sgt i32 [[upper_limit_loclamp]], 0 70; CHECK: [[upper_limit:[^ ]+]] = select i1 [[upper_limit_cmp]], i32 [[upper_limit_loclamp]], i32 0 71 72 entry: 73 %len.a = load i32, i32* %a_len_ptr, !range !0 74 %len.b = load i32, i32* %b_len_ptr, !range !0 75 %first.itr.check = icmp sgt i32 %n, 0 76 br i1 %first.itr.check, label %loop, label %exit 77 78 loop: 79 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 80 %idx.next = add i32 %idx, 1 81 %abc.a = icmp slt i32 %idx, %len.a 82 %abc.b = icmp slt i32 %idx, %len.b 83 %abc = and i1 %abc.a, %abc.b 84 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 85 86; CHECK: loop: 87; CHECK: %abc = and i1 true, true 88; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit4, !prof !1 89 90; CHECK: out.of.bounds.loopexit: 91; CHECK-NEXT: br label %out.of.bounds 92 93 94 in.bounds: 95 %addr.a = getelementptr i32, i32* %arr_a, i32 %idx 96 store i32 0, i32* %addr.a 97 %addr.b = getelementptr i32, i32* %arr_b, i32 %idx 98 store i32 -1, i32* %addr.b 99 %next = icmp slt i32 %idx.next, %n 100 br i1 %next, label %loop, label %exit 101 102 out.of.bounds: 103 ret void 104 105 exit: 106 ret void 107} 108 109!0 = !{i32 0, i32 2147483647} 110!1 = !{!"branch_weights", i32 64, i32 4} 111