Home | History | Annotate | Download | only in IRCE
      1 ; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
      2 ; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
      3 
      4 define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
      5  entry:
      6   %len = load i32, i32* %a_len_ptr, !range !0
      7   %first.itr.check = icmp sgt i32 %n, 0
      8   br i1 %first.itr.check, label %loop, label %exit
      9 
     10  loop:
     11   %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
     12   %idx.next = add i32 %idx, 1
     13   %abc = icmp slt i32 %idx, %len
     14   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
     15 
     16  in.bounds:
     17   %addr = getelementptr i32, i32* %arr, i32 %idx
     18   store i32 0, i32* %addr
     19   %next = icmp slt i32 %idx.next, %n
     20   br i1 %next, label %loop, label %exit
     21 
     22  out.of.bounds:
     23   ret void
     24 
     25  exit:
     26   ret void
     27 }
     28 
     29 ; CHECK-LABEL: @single_access_no_preloop_no_offset(
     30 
     31 ; CHECK: loop:
     32 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
     33 
     34 ; CHECK: main.exit.selector:
     35 ; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
     36 ; CHECK-NEXT: [[continue:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, %n
     37 ; CHECK-NEXT: br i1 [[continue]], label %main.pseudo.exit, label %exit.loopexit
     38 
     39 ; CHECK: main.pseudo.exit:
     40 ; CHECK-NEXT: %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
     41 ; CHECK-NEXT: %indvar.end = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
     42 ; CHECK-NEXT: br label %postloop
     43 
     44 ; CHECK: postloop:
     45 ; CHECK-NEXT: br label %loop.postloop
     46 
     47 ; CHECK: loop.postloop:
     48 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
     49 ; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1
     50 ; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %len
     51 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds
     52 
     53 ; CHECK: in.bounds.postloop:
     54 ; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
     55 ; CHECK-NEXT: store i32 0, i32* %addr.postloop
     56 ; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, %n
     57 ; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
     58 
     59 
     60 define void @single_access_no_preloop_with_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
     61  entry:
     62   %len = load i32, i32* %a_len_ptr, !range !0
     63   %first.itr.check = icmp sgt i32 %n, 0
     64   br i1 %first.itr.check, label %loop, label %exit
     65 
     66  loop:
     67   %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
     68   %idx.next = add i32 %idx, 1
     69   %idx.for.abc = add i32 %idx, 4
     70   %abc = icmp slt i32 %idx.for.abc, %len
     71   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
     72 
     73  in.bounds:
     74   %addr = getelementptr i32, i32* %arr, i32 %idx.for.abc
     75   store i32 0, i32* %addr
     76   %next = icmp slt i32 %idx.next, %n
     77   br i1 %next, label %loop, label %exit
     78 
     79  out.of.bounds:
     80   ret void
     81 
     82  exit:
     83   ret void
     84 }
     85 
     86 ; CHECK-LABEL: @single_access_no_preloop_with_offset(
     87 
     88 ; CHECK: loop.preheader:
     89 ; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len
     90 ; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
     91 ; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_safe_range_end]], [[not_n]]
     92 ; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_safe_range_end]], i32 [[not_n]]
     93 ; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]]
     94 ; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0
     95 ; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0
     96 ; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]]
     97 ; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit
     98 
     99 ; CHECK: loop:
    100 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
    101 
    102 ; CHECK: in.bounds:
    103 ; CHECK: [[continue_main_loop:[^ ]+]] = icmp slt i32 %idx.next, [[exit_main_loop_at_loclamp]]
    104 ; CHECK: br i1 [[continue_main_loop]], label %loop, label %main.exit.selector
    105 
    106 ; CHECK: main.pseudo.exit:
    107 ; CHECK:  %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
    108 ; CHECK:  br label %postloop
    109 
    110 ; CHECK: loop.postloop:
    111 ; CHECK: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
    112 
    113 ; CHECK: in.bounds.postloop:
    114 ; CHECK: %next.postloop = icmp slt i32 %idx.next.postloop, %n
    115 ; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
    116 
    117 ; Make sure that we do not do IRCE if we know that the safe iteration range of
    118 ; the main loop is empty.
    119 
    120 define void @single_access_empty_range(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
    121  entry:
    122   %len = load i32, i32* %a_len_ptr, !range !0
    123   %first.itr.check = icmp sgt i32 %n, 0
    124   br i1 %first.itr.check, label %loop, label %exit
    125 
    126  loop:
    127   %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
    128   %idx.next = add i32 %idx, 1
    129   %abc = icmp slt i32 %idx, 0
    130   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
    131 
    132  in.bounds:
    133   %addr = getelementptr i32, i32* %arr, i32 %idx
    134   store i32 0, i32* %addr
    135   %next = icmp slt i32 %idx.next, %n
    136   br i1 %next, label %loop, label %exit
    137 
    138  out.of.bounds:
    139   ret void
    140 
    141  exit:
    142   ret void
    143 }
    144 
    145 ; CHECK-LABEL: @single_access_empty_range(
    146 ; CHECK-NOT:   br i1 false
    147 ; CHECK-NOT:   preloop
    148 ; CHECK-NOT:   postloop
    149 
    150 define void @single_access_empty_range_2(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
    151  entry:
    152   %len = load i32, i32* %a_len_ptr, !range !0
    153   %first.itr.check = icmp sgt i32 %n, 0
    154   br i1 %first.itr.check, label %loop, label %exit
    155 
    156  loop:
    157   %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds2 ]
    158   %idx.next = add i32 %idx, 1
    159   %abc = icmp slt i32 %idx, 60
    160   br i1 %abc, label %in.bounds1, label %out.of.bounds, !prof !1
    161 
    162  in.bounds1:
    163   %def = icmp slt i32 %idx, 0
    164   br i1 %def, label %in.bounds2, label %out.of.bounds, !prof !1
    165 
    166 in.bounds2:
    167   %addr = getelementptr i32, i32* %arr, i32 %idx
    168   store i32 0, i32* %addr
    169   %next = icmp slt i32 %idx.next, %n
    170   br i1 %next, label %loop, label %exit
    171 
    172  out.of.bounds:
    173   ret void
    174 
    175  exit:
    176   ret void
    177 }
    178 
    179 ; CHECK-LABEL: @single_access_empty_range_2(
    180 ; CHECK-NOT:   br i1 false
    181 ; CHECK-NOT:   preloop
    182 
    183 define void @single_access_no_preloop_no_offset_phi_len(i32 *%arr, i32 *%a_len_ptr, i32 *%b_len_ptr, i32 %n, i1 %unknown_cond) {
    184  entry:
    185   br i1 %unknown_cond, label %if.true, label %if.false
    186 
    187 if.true:
    188   %len_a = load i32, i32* %a_len_ptr, !range !0
    189   br label %merge
    190 
    191 if.false:
    192   %len_b = load i32, i32* %b_len_ptr, !range !0
    193   br label %merge
    194 
    195 merge:
    196   %len = phi i32 [ %len_a, %if.true ], [ %len_b, %if.false ]
    197   %first.itr.check = icmp sgt i32 %n, 0
    198   br i1 %first.itr.check, label %loop, label %exit
    199 
    200  loop:
    201   %idx = phi i32 [ 0, %merge ] , [ %idx.next, %in.bounds ]
    202   %idx.next = add i32 %idx, 1
    203   %abc = icmp slt i32 %idx, %len
    204   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
    205 
    206  in.bounds:
    207   %addr = getelementptr i32, i32* %arr, i32 %idx
    208   store i32 0, i32* %addr
    209   %next = icmp slt i32 %idx.next, %n
    210   br i1 %next, label %loop, label %exit
    211 
    212  out.of.bounds:
    213   ret void
    214 
    215  exit:
    216   ret void
    217 }
    218 
    219 ; CHECK-LABEL: @single_access_no_preloop_no_offset_phi_len(
    220 
    221 ; CHECK: loop:
    222 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
    223 
    224 ; CHECK: main.exit.selector:
    225 ; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
    226 ; CHECK-NEXT: [[continue:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, %n
    227 ; CHECK-NEXT: br i1 [[continue]], label %main.pseudo.exit, label %exit.loopexit
    228 
    229 ; CHECK: main.pseudo.exit:
    230 ; CHECK-NEXT: %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
    231 ; CHECK-NEXT: %indvar.end = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
    232 ; CHECK-NEXT: br label %postloop
    233 
    234 ; CHECK: postloop:
    235 ; CHECK-NEXT: br label %loop.postloop
    236 
    237 ; CHECK: loop.postloop:
    238 ; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
    239 ; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1
    240 ; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %len
    241 ; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds
    242 
    243 ; CHECK: in.bounds.postloop:
    244 ; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
    245 ; CHECK-NEXT: store i32 0, i32* %addr.postloop
    246 ; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, %n
    247 ; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
    248 
    249 !0 = !{i32 0, i32 2147483647}
    250 !1 = !{!"branch_weights", i32 64, i32 4}
    251