Home | History | Annotate | Download | only in LoopSimplify
      1 ; RUN: opt < %s -S -loop-simplify | FileCheck %s
      2 ; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
      3 
      4 ; This function should get a preheader inserted before bb3, that is jumped
      5 ; to by bb1 & bb2
      6 define void @test() {
      7 ; CHECK-LABEL: define void @test(
      8 entry:
      9   br i1 true, label %bb1, label %bb2
     10 
     11 bb1:
     12   br label %bb3
     13 ; CHECK:      bb1:
     14 ; CHECK-NEXT:   br label %[[PH:.*]]
     15 
     16 bb2:
     17   br label %bb3
     18 ; CHECK:      bb2:
     19 ; CHECK-NEXT:   br label %[[PH]]
     20 
     21 bb3:
     22   br label %bb3
     23 ; CHECK:      [[PH]]:
     24 ; CHECK-NEXT:   br label %bb3
     25 ;
     26 ; CHECK:      bb3:
     27 ; CHECK-NEXT:   br label %bb3
     28 }
     29 
     30 ; Test a case where we have multiple exit blocks as successors of a single loop
     31 ; block that need to be made dedicated exit blocks. We also have multiple
     32 ; exiting edges to one of the exit blocks that all should be rewritten.
     33 define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) {
     34 ; CHECK-LABEL: define void @test_multiple_exits_from_single_block(
     35 entry:
     36   switch i8 %a, label %loop [
     37     i8 0, label %exit.a
     38     i8 1, label %exit.b
     39   ]
     40 ; CHECK:      entry:
     41 ; CHECK-NEXT:   switch i8 %a, label %[[PH:.*]] [
     42 ; CHECK-NEXT:     i8 0, label %exit.a
     43 ; CHECK-NEXT:     i8 1, label %exit.b
     44 ; CHECK-NEXT:   ]
     45 
     46 loop:
     47   %b = load volatile i8, i8* %b.ptr
     48   switch i8 %b, label %loop [
     49     i8 0, label %exit.a
     50     i8 1, label %exit.b
     51     i8 2, label %loop
     52     i8 3, label %exit.a
     53     i8 4, label %loop
     54     i8 5, label %exit.a
     55     i8 6, label %loop
     56   ]
     57 ; CHECK:      [[PH]]:
     58 ; CHECK-NEXT:   br label %loop
     59 ;
     60 ; CHECK:      loop:
     61 ; CHECK-NEXT:   %[[B:.*]] = load volatile i8, i8* %b.ptr
     62 ; CHECK-NEXT:   switch i8 %[[B]], label %[[BACKEDGE:.*]] [
     63 ; CHECK-NEXT:     i8 0, label %[[LOOPEXIT_A:.*]]
     64 ; CHECK-NEXT:     i8 1, label %[[LOOPEXIT_B:.*]]
     65 ; CHECK-NEXT:     i8 2, label %[[BACKEDGE]]
     66 ; CHECK-NEXT:     i8 3, label %[[LOOPEXIT_A]]
     67 ; CHECK-NEXT:     i8 4, label %[[BACKEDGE]]
     68 ; CHECK-NEXT:     i8 5, label %[[LOOPEXIT_A]]
     69 ; CHECK-NEXT:     i8 6, label %[[BACKEDGE]]
     70 ; CHECK-NEXT:   ]
     71 ;
     72 ; CHECK:      [[BACKEDGE]]:
     73 ; CHECK-NEXT:   br label %loop
     74 
     75 exit.a:
     76   ret void
     77 ; CHECK:      [[LOOPEXIT_A]]:
     78 ; CHECK-NEXT:   br label %exit.a
     79 ;
     80 ; CHECK:      exit.a:
     81 ; CHECK-NEXT:   ret void
     82 
     83 exit.b:
     84   ret void
     85 ; CHECK:      [[LOOPEXIT_B]]:
     86 ; CHECK-NEXT:   br label %exit.b
     87 ;
     88 ; CHECK:      exit.b:
     89 ; CHECK-NEXT:   ret void
     90 }
     91 
     92 ; Check that we leave already dedicated exits alone when forming dedicated exit
     93 ; blocks.
     94 define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) {
     95 ; CHECK-LABEL: define void @test_pre_existing_dedicated_exits(
     96 entry:
     97   br i1 %a, label %loop.ph, label %non_dedicated_exit
     98 ; CHECK:      entry:
     99 ; CHECK-NEXT:   br i1 %a, label %loop.ph, label %non_dedicated_exit
    100 
    101 loop.ph:
    102   br label %loop.header
    103 ; CHECK:      loop.ph:
    104 ; CHECK-NEXT:   br label %loop.header
    105 
    106 loop.header:
    107   %c1 = load volatile i1, i1* %ptr
    108   br i1 %c1, label %loop.body1, label %dedicated_exit1
    109 ; CHECK:      loop.header:
    110 ; CHECK-NEXT:   %[[C1:.*]] = load volatile i1, i1* %ptr
    111 ; CHECK-NEXT:   br i1 %[[C1]], label %loop.body1, label %dedicated_exit1
    112 
    113 loop.body1:
    114   %c2 = load volatile i1, i1* %ptr
    115   br i1 %c2, label %loop.body2, label %non_dedicated_exit
    116 ; CHECK:      loop.body1:
    117 ; CHECK-NEXT:   %[[C2:.*]] = load volatile i1, i1* %ptr
    118 ; CHECK-NEXT:   br i1 %[[C2]], label %loop.body2, label %[[LOOPEXIT:.*]]
    119 
    120 loop.body2:
    121   %c3 = load volatile i1, i1* %ptr
    122   br i1 %c3, label %loop.backedge, label %dedicated_exit2
    123 ; CHECK:      loop.body2:
    124 ; CHECK-NEXT:   %[[C3:.*]] = load volatile i1, i1* %ptr
    125 ; CHECK-NEXT:   br i1 %[[C3]], label %loop.backedge, label %dedicated_exit2
    126 
    127 loop.backedge:
    128   br label %loop.header
    129 ; CHECK:      loop.backedge:
    130 ; CHECK-NEXT:   br label %loop.header
    131 
    132 dedicated_exit1:
    133   ret void
    134 ; Check that there isn't a split loop exit.
    135 ; CHECK-NOT:    br label %dedicated_exit1
    136 ;
    137 ; CHECK:      dedicated_exit1:
    138 ; CHECK-NEXT:   ret void
    139 
    140 dedicated_exit2:
    141   ret void
    142 ; Check that there isn't a split loop exit.
    143 ; CHECK-NOT:    br label %dedicated_exit2
    144 ;
    145 ; CHECK:      dedicated_exit2:
    146 ; CHECK-NEXT:   ret void
    147 
    148 non_dedicated_exit:
    149   ret void
    150 ; CHECK:      [[LOOPEXIT]]:
    151 ; CHECK-NEXT:   br label %non_dedicated_exit
    152 ;
    153 ; CHECK:      non_dedicated_exit:
    154 ; CHECK-NEXT:   ret void
    155 }
    156 
    157 ; Check that we form what dedicated exits we can even when some exits are
    158 ; reached via indirectbr which precludes forming dedicated exits.
    159 define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, i8* %ptr, i8** %addr.ptr) {
    160 ; CHECK-LABEL: define void @test_form_some_dedicated_exits_despite_indirectbr(
    161 entry:
    162   switch i8 %a, label %loop.ph [
    163     i8 0, label %exit.a
    164     i8 1, label %exit.b
    165     i8 2, label %exit.c
    166   ]
    167 ; CHECK:      entry:
    168 ; CHECK-NEXT:   switch i8 %a, label %loop.ph [
    169 ; CHECK-NEXT:     i8 0, label %exit.a
    170 ; CHECK-NEXT:     i8 1, label %exit.b
    171 ; CHECK-NEXT:     i8 2, label %exit.c
    172 ; CHECK-NEXT:   ]
    173 
    174 loop.ph:
    175   br label %loop.header
    176 ; CHECK:      loop.ph:
    177 ; CHECK-NEXT:   br label %loop.header
    178 
    179 loop.header:
    180   %addr1 = load volatile i8*, i8** %addr.ptr
    181   indirectbr i8* %addr1, [label %loop.body1, label %exit.a]
    182 ; CHECK:      loop.header:
    183 ; CHECK-NEXT:   %[[ADDR1:.*]] = load volatile i8*, i8** %addr.ptr
    184 ; CHECK-NEXT:   indirectbr i8* %[[ADDR1]], [label %loop.body1, label %exit.a]
    185 
    186 loop.body1:
    187   %b = load volatile i8, i8* %ptr
    188   switch i8 %b, label %loop.body2 [
    189     i8 0, label %exit.a
    190     i8 1, label %exit.b
    191     i8 2, label %exit.c
    192   ]
    193 ; CHECK:      loop.body1:
    194 ; CHECK-NEXT:   %[[B:.*]] = load volatile i8, i8* %ptr
    195 ; CHECK-NEXT:   switch i8 %[[B]], label %loop.body2 [
    196 ; CHECK-NEXT:     i8 0, label %exit.a
    197 ; CHECK-NEXT:     i8 1, label %[[LOOPEXIT:.*]]
    198 ; CHECK-NEXT:     i8 2, label %exit.c
    199 ; CHECK-NEXT:   ]
    200 
    201 loop.body2:
    202   %addr2 = load volatile i8*, i8** %addr.ptr
    203   indirectbr i8* %addr2, [label %loop.backedge, label %exit.c]
    204 ; CHECK:      loop.body2:
    205 ; CHECK-NEXT:   %[[ADDR2:.*]] = load volatile i8*, i8** %addr.ptr
    206 ; CHECK-NEXT:   indirectbr i8* %[[ADDR2]], [label %loop.backedge, label %exit.c]
    207 
    208 loop.backedge:
    209   br label %loop.header
    210 ; CHECK:      loop.backedge:
    211 ; CHECK-NEXT:   br label %loop.header
    212 
    213 exit.a:
    214   ret void
    215 ; Check that there isn't a split loop exit.
    216 ; CHECK-NOT:    br label %exit.a
    217 ;
    218 ; CHECK:      exit.a:
    219 ; CHECK-NEXT:   ret void
    220 
    221 exit.b:
    222   ret void
    223 ; CHECK:      [[LOOPEXIT]]:
    224 ; CHECK-NEXT:   br label %exit.b
    225 ;
    226 ; CHECK:      exit.b:
    227 ; CHECK-NEXT:   ret void
    228 
    229 exit.c:
    230   ret void
    231 ; Check that there isn't a split loop exit.
    232 ; CHECK-NOT:    br label %exit.c
    233 ;
    234 ; CHECK:      exit.c:
    235 ; CHECK-NEXT:   ret void
    236 }
    237