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 4 define 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 56 define 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