Home | History | Annotate | Download | only in SimpleLoopUnswitch
      1 ; Specifically exercise the cost modeling for non-trivial loop unswitching.
      2 ;
      3 ; RUN: opt -passes='loop(unswitch),verify<loops>' -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s
      4 ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s
      5 
      6 declare void @a()
      7 declare void @b()
      8 declare void @x()
      9 
     10 ; First establish enough code size in the duplicated 'loop_begin' block to
     11 ; suppress unswitching.
     12 define void @test_no_unswitch(i1* %ptr, i1 %cond) {
     13 ; CHECK-LABEL: @test_no_unswitch(
     14 entry:
     15   br label %loop_begin
     16 ; CHECK-NEXT:  entry:
     17 ; CHECK-NEXT:    br label %loop_begin
     18 ;
     19 ; We shouldn't have unswitched into any other block either.
     20 ; CHECK-NOT:     br i1 %cond
     21 
     22 loop_begin:
     23   call void @x()
     24   call void @x()
     25   call void @x()
     26   call void @x()
     27   br i1 %cond, label %loop_a, label %loop_b
     28 ; CHECK:       loop_begin:
     29 ; CHECK-NEXT:    call void @x()
     30 ; CHECK-NEXT:    call void @x()
     31 ; CHECK-NEXT:    call void @x()
     32 ; CHECK-NEXT:    call void @x()
     33 ; CHECK-NEXT:    br i1 %cond, label %loop_a, label %loop_b
     34 
     35 loop_a:
     36   call void @a()
     37   br label %loop_latch
     38 
     39 loop_b:
     40   call void @b()
     41   br label %loop_latch
     42 
     43 loop_latch:
     44   %v = load i1, i1* %ptr
     45   br i1 %v, label %loop_begin, label %loop_exit
     46 
     47 loop_exit:
     48   ret void
     49 }
     50 
     51 ; Now check that the smaller formulation of 'loop_begin' does in fact unswitch
     52 ; with our low threshold.
     53 define void @test_unswitch(i1* %ptr, i1 %cond) {
     54 ; CHECK-LABEL: @test_unswitch(
     55 entry:
     56   br label %loop_begin
     57 ; CHECK-NEXT:  entry:
     58 ; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
     59 
     60 loop_begin:
     61   call void @x()
     62   br i1 %cond, label %loop_a, label %loop_b
     63 
     64 loop_a:
     65   call void @a()
     66   br label %loop_latch
     67 ; The 'loop_a' unswitched loop.
     68 ;
     69 ; CHECK:       entry.split.us:
     70 ; CHECK-NEXT:    br label %loop_begin.us
     71 ;
     72 ; CHECK:       loop_begin.us:
     73 ; CHECK-NEXT:    call void @x()
     74 ; CHECK-NEXT:    br label %loop_a.us
     75 ;
     76 ; CHECK:       loop_a.us:
     77 ; CHECK-NEXT:    call void @a()
     78 ; CHECK-NEXT:    br label %loop_latch.us
     79 ;
     80 ; CHECK:       loop_latch.us:
     81 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
     82 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
     83 ;
     84 ; CHECK:       loop_exit.split.us:
     85 ; CHECK-NEXT:    br label %loop_exit
     86 
     87 loop_b:
     88   call void @b()
     89   br label %loop_latch
     90 ; The 'loop_b' unswitched loop.
     91 ;
     92 ; CHECK:       entry.split:
     93 ; CHECK-NEXT:    br label %loop_begin
     94 ;
     95 ; CHECK:       loop_begin:
     96 ; CHECK-NEXT:    call void @x()
     97 ; CHECK-NEXT:    br label %loop_b
     98 ;
     99 ; CHECK:       loop_b:
    100 ; CHECK-NEXT:    call void @b()
    101 ; CHECK-NEXT:    br label %loop_latch
    102 ;
    103 ; CHECK:       loop_latch:
    104 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    105 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin, label %loop_exit.split
    106 ;
    107 ; CHECK:       loop_exit.split:
    108 ; CHECK-NEXT:    br label %loop_exit
    109 
    110 loop_latch:
    111   %v = load i1, i1* %ptr
    112   br i1 %v, label %loop_begin, label %loop_exit
    113 
    114 loop_exit:
    115   ret void
    116 ; CHECK:       loop_exit:
    117 ; CHECK-NEXT:    ret void
    118 }
    119 
    120 ; Check that even with large amounts of code on either side of the unswitched
    121 ; branch, if that code would be kept in only one of the unswitched clones it
    122 ; doesn't contribute to the cost.
    123 define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
    124 ; CHECK-LABEL: @test_unswitch_non_dup_code(
    125 entry:
    126   br label %loop_begin
    127 ; CHECK-NEXT:  entry:
    128 ; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
    129 
    130 loop_begin:
    131   call void @x()
    132   br i1 %cond, label %loop_a, label %loop_b
    133 
    134 loop_a:
    135   call void @a()
    136   call void @a()
    137   call void @a()
    138   call void @a()
    139   br label %loop_latch
    140 ; The 'loop_a' unswitched loop.
    141 ;
    142 ; CHECK:       entry.split.us:
    143 ; CHECK-NEXT:    br label %loop_begin.us
    144 ;
    145 ; CHECK:       loop_begin.us:
    146 ; CHECK-NEXT:    call void @x()
    147 ; CHECK-NEXT:    br label %loop_a.us
    148 ;
    149 ; CHECK:       loop_a.us:
    150 ; CHECK-NEXT:    call void @a()
    151 ; CHECK-NEXT:    call void @a()
    152 ; CHECK-NEXT:    call void @a()
    153 ; CHECK-NEXT:    call void @a()
    154 ; CHECK-NEXT:    br label %loop_latch.us
    155 ;
    156 ; CHECK:       loop_latch.us:
    157 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    158 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
    159 ;
    160 ; CHECK:       loop_exit.split.us:
    161 ; CHECK-NEXT:    br label %loop_exit
    162 
    163 loop_b:
    164   call void @b()
    165   call void @b()
    166   call void @b()
    167   call void @b()
    168   br label %loop_latch
    169 ; The 'loop_b' unswitched loop.
    170 ;
    171 ; CHECK:       entry.split:
    172 ; CHECK-NEXT:    br label %loop_begin
    173 ;
    174 ; CHECK:       loop_begin:
    175 ; CHECK-NEXT:    call void @x()
    176 ; CHECK-NEXT:    br label %loop_b
    177 ;
    178 ; CHECK:       loop_b:
    179 ; CHECK-NEXT:    call void @b()
    180 ; CHECK-NEXT:    call void @b()
    181 ; CHECK-NEXT:    call void @b()
    182 ; CHECK-NEXT:    call void @b()
    183 ; CHECK-NEXT:    br label %loop_latch
    184 ;
    185 ; CHECK:       loop_latch:
    186 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    187 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin, label %loop_exit.split
    188 ;
    189 ; CHECK:       loop_exit.split:
    190 ; CHECK-NEXT:    br label %loop_exit
    191 
    192 loop_latch:
    193   %v = load i1, i1* %ptr
    194   br i1 %v, label %loop_begin, label %loop_exit
    195 
    196 loop_exit:
    197   ret void
    198 ; CHECK:       loop_exit:
    199 ; CHECK-NEXT:    ret void
    200 }
    201 
    202 ; Much like with non-duplicated code directly in the successor, we also won't
    203 ; duplicate even interesting CFGs.
    204 define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
    205 ; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
    206 entry:
    207   br label %loop_begin
    208 ; CHECK-NEXT:  entry:
    209 ; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
    210 
    211 loop_begin:
    212   call void @x()
    213   br i1 %cond, label %loop_a, label %loop_b
    214 
    215 loop_a:
    216   %v1 = load i1, i1* %ptr
    217   br i1 %v1, label %loop_a_a, label %loop_a_b
    218 
    219 loop_a_a:
    220   call void @a()
    221   br label %loop_latch
    222 
    223 loop_a_b:
    224   call void @a()
    225   br label %loop_latch
    226 ; The 'loop_a' unswitched loop.
    227 ;
    228 ; CHECK:       entry.split.us:
    229 ; CHECK-NEXT:    br label %loop_begin.us
    230 ;
    231 ; CHECK:       loop_begin.us:
    232 ; CHECK-NEXT:    call void @x()
    233 ; CHECK-NEXT:    br label %loop_a.us
    234 ;
    235 ; CHECK:       loop_a.us:
    236 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    237 ; CHECK-NEXT:    br i1 %[[V]], label %loop_a_a.us, label %loop_a_b.us
    238 ;
    239 ; CHECK:       loop_a_b.us:
    240 ; CHECK-NEXT:    call void @a()
    241 ; CHECK-NEXT:    br label %loop_latch.us
    242 ;
    243 ; CHECK:       loop_a_a.us:
    244 ; CHECK-NEXT:    call void @a()
    245 ; CHECK-NEXT:    br label %loop_latch.us
    246 ;
    247 ; CHECK:       loop_latch.us:
    248 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    249 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
    250 ;
    251 ; CHECK:       loop_exit.split.us:
    252 ; CHECK-NEXT:    br label %loop_exit
    253 
    254 loop_b:
    255   %v2 = load i1, i1* %ptr
    256   br i1 %v2, label %loop_b_a, label %loop_b_b
    257 
    258 loop_b_a:
    259   call void @b()
    260   br label %loop_latch
    261 
    262 loop_b_b:
    263   call void @b()
    264   br label %loop_latch
    265 ; The 'loop_b' unswitched loop.
    266 ;
    267 ; CHECK:       entry.split:
    268 ; CHECK-NEXT:    br label %loop_begin
    269 ;
    270 ; CHECK:       loop_begin:
    271 ; CHECK-NEXT:    call void @x()
    272 ; CHECK-NEXT:    br label %loop_b
    273 ;
    274 ; CHECK:       loop_b:
    275 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    276 ; CHECK-NEXT:    br i1 %[[V]], label %loop_b_a, label %loop_b_b
    277 ;
    278 ; CHECK:       loop_b_a:
    279 ; CHECK-NEXT:    call void @b()
    280 ; CHECK-NEXT:    br label %loop_latch
    281 ;
    282 ; CHECK:       loop_b_b:
    283 ; CHECK-NEXT:    call void @b()
    284 ; CHECK-NEXT:    br label %loop_latch
    285 ;
    286 ; CHECK:       loop_latch:
    287 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    288 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin, label %loop_exit.split
    289 ;
    290 ; CHECK:       loop_exit.split:
    291 ; CHECK-NEXT:    br label %loop_exit
    292 
    293 loop_latch:
    294   %v3 = load i1, i1* %ptr
    295   br i1 %v3, label %loop_begin, label %loop_exit
    296 
    297 loop_exit:
    298   ret void
    299 ; CHECK:       loop_exit:
    300 ; CHECK-NEXT:    ret void
    301 }
    302 
    303 ; Check that even if there is *some* non-duplicated code on one side of an
    304 ; unswitch, we don't count any other code in the loop that will in fact have to
    305 ; be duplicated.
    306 define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
    307 ; CHECK-LABEL: @test_no_unswitch_non_dup_code(
    308 entry:
    309   br label %loop_begin
    310 ; CHECK-NEXT:  entry:
    311 ; CHECK-NEXT:    br label %loop_begin
    312 ;
    313 ; We shouldn't have unswitched into any other block either.
    314 ; CHECK-NOT:     br i1 %cond
    315 
    316 loop_begin:
    317   call void @x()
    318   br i1 %cond, label %loop_a, label %loop_b
    319 ; CHECK:       loop_begin:
    320 ; CHECK-NEXT:    call void @x()
    321 ; CHECK-NEXT:    br i1 %cond, label %loop_a, label %loop_b
    322 
    323 loop_a:
    324   %v1 = load i1, i1* %ptr
    325   br i1 %v1, label %loop_a_a, label %loop_a_b
    326 
    327 loop_a_a:
    328   call void @a()
    329   br label %loop_latch
    330 
    331 loop_a_b:
    332   call void @a()
    333   br label %loop_latch
    334 
    335 loop_b:
    336   %v2 = load i1, i1* %ptr
    337   br i1 %v2, label %loop_b_a, label %loop_b_b
    338 
    339 loop_b_a:
    340   call void @b()
    341   br label %loop_latch
    342 
    343 loop_b_b:
    344   call void @b()
    345   br label %loop_latch
    346 
    347 loop_latch:
    348   call void @x()
    349   call void @x()
    350   %v = load i1, i1* %ptr
    351   br i1 %v, label %loop_begin, label %loop_exit
    352 
    353 loop_exit:
    354   ret void
    355 }
    356 
    357 ; Check that we still unswitch when the exit block contains lots of code, even
    358 ; though we do clone the exit block as part of unswitching. This should work
    359 ; because we should split the exit block before anything inside it.
    360 define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
    361 ; CHECK-LABEL: @test_unswitch_large_exit(
    362 entry:
    363   br label %loop_begin
    364 ; CHECK-NEXT:  entry:
    365 ; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
    366 
    367 loop_begin:
    368   call void @x()
    369   br i1 %cond, label %loop_a, label %loop_b
    370 
    371 loop_a:
    372   call void @a()
    373   br label %loop_latch
    374 ; The 'loop_a' unswitched loop.
    375 ;
    376 ; CHECK:       entry.split.us:
    377 ; CHECK-NEXT:    br label %loop_begin.us
    378 ;
    379 ; CHECK:       loop_begin.us:
    380 ; CHECK-NEXT:    call void @x()
    381 ; CHECK-NEXT:    br label %loop_a.us
    382 ;
    383 ; CHECK:       loop_a.us:
    384 ; CHECK-NEXT:    call void @a()
    385 ; CHECK-NEXT:    br label %loop_latch.us
    386 ;
    387 ; CHECK:       loop_latch.us:
    388 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    389 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
    390 ;
    391 ; CHECK:       loop_exit.split.us:
    392 ; CHECK-NEXT:    br label %loop_exit
    393 
    394 loop_b:
    395   call void @b()
    396   br label %loop_latch
    397 ; The 'loop_b' unswitched loop.
    398 ;
    399 ; CHECK:       entry.split:
    400 ; CHECK-NEXT:    br label %loop_begin
    401 ;
    402 ; CHECK:       loop_begin:
    403 ; CHECK-NEXT:    call void @x()
    404 ; CHECK-NEXT:    br label %loop_b
    405 ;
    406 ; CHECK:       loop_b:
    407 ; CHECK-NEXT:    call void @b()
    408 ; CHECK-NEXT:    br label %loop_latch
    409 ;
    410 ; CHECK:       loop_latch:
    411 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    412 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin, label %loop_exit.split
    413 ;
    414 ; CHECK:       loop_exit.split:
    415 ; CHECK-NEXT:    br label %loop_exit
    416 
    417 loop_latch:
    418   %v = load i1, i1* %ptr
    419   br i1 %v, label %loop_begin, label %loop_exit
    420 
    421 loop_exit:
    422   call void @x()
    423   call void @x()
    424   call void @x()
    425   call void @x()
    426   ret void
    427 ; CHECK:       loop_exit:
    428 ; CHECK-NEXT:    call void @x()
    429 ; CHECK-NEXT:    call void @x()
    430 ; CHECK-NEXT:    call void @x()
    431 ; CHECK-NEXT:    call void @x()
    432 ; CHECK-NEXT:    ret void
    433 }
    434 
    435 ; Check that we handle a dedicated exit edge unswitch which is still
    436 ; non-trivial and has lots of code in the exit.
    437 define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
    438 ; CHECK-LABEL: @test_unswitch_dedicated_exiting(
    439 entry:
    440   br label %loop_begin
    441 ; CHECK-NEXT:  entry:
    442 ; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
    443 
    444 loop_begin:
    445   call void @x()
    446   br i1 %cond, label %loop_a, label %loop_b_exit
    447 
    448 loop_a:
    449   call void @a()
    450   br label %loop_latch
    451 ; The 'loop_a' unswitched loop.
    452 ;
    453 ; CHECK:       entry.split.us:
    454 ; CHECK-NEXT:    br label %loop_begin.us
    455 ;
    456 ; CHECK:       loop_begin.us:
    457 ; CHECK-NEXT:    call void @x()
    458 ; CHECK-NEXT:    br label %loop_a.us
    459 ;
    460 ; CHECK:       loop_a.us:
    461 ; CHECK-NEXT:    call void @a()
    462 ; CHECK-NEXT:    br label %loop_latch.us
    463 ;
    464 ; CHECK:       loop_latch.us:
    465 ; CHECK-NEXT:    %[[V:.*]] = load i1, i1* %ptr
    466 ; CHECK-NEXT:    br i1 %[[V]], label %loop_begin.us, label %loop_exit.split.us
    467 ;
    468 ; CHECK:       loop_exit.split.us:
    469 ; CHECK-NEXT:    br label %loop_exit
    470 
    471 loop_b_exit:
    472   call void @b()
    473   call void @b()
    474   call void @b()
    475   call void @b()
    476   ret void
    477 ; The 'loop_b_exit' unswitched exit path.
    478 ;
    479 ; CHECK:       entry.split:
    480 ; CHECK-NEXT:    br label %loop_begin
    481 ;
    482 ; CHECK:       loop_begin:
    483 ; CHECK-NEXT:    call void @x()
    484 ; CHECK-NEXT:    br label %loop_b_exit
    485 ;
    486 ; CHECK:       loop_b_exit:
    487 ; CHECK-NEXT:    call void @b()
    488 ; CHECK-NEXT:    call void @b()
    489 ; CHECK-NEXT:    call void @b()
    490 ; CHECK-NEXT:    call void @b()
    491 ; CHECK-NEXT:    ret void
    492 
    493 loop_latch:
    494   %v = load i1, i1* %ptr
    495   br i1 %v, label %loop_begin, label %loop_exit
    496 
    497 loop_exit:
    498   ret void
    499 ; CHECK:       loop_exit:
    500 ; CHECK-NEXT:    ret void
    501 }
    502