Home | History | Annotate | Download | only in Other
      1 ; RUN: opt -aa-pipeline=basic-aa -passes='cgscc(function-attrs,function(simplify-cfg))' -S < %s | FileCheck %s
      2 
      3 declare void @readnone() readnone
      4 declare void @unknown()
      5 declare void @reference_function_pointer(void()*) readnone
      6 
      7 ; The @test1_* set of functions checks that when we mutate functions with
      8 ; simplify-cfg to delete call edges and this ends up splitting both the SCCs
      9 ; and the RefSCCs that those functions are in, we re-run the CGSCC passes to
     10 ; observe the refined call graph structure.
     11 
     12 ; CHECK: define void @test1_a() {
     13 define void @test1_a() {
     14   call void @test1_b1()
     15   call void @test1_b2()
     16   call void @test1_b3()
     17   call void @test1_b4()
     18   ret void
     19 }
     20 
     21 ; CHECK: define void @test1_b1() #0 {
     22 define void @test1_b1() {
     23   call void @readnone()
     24   ret void
     25 }
     26 
     27 ; CHECK: define void @test1_b2() #0 {
     28 define void @test1_b2() {
     29   call void @readnone()
     30   br i1 false, label %dead, label %exit
     31 
     32 dead:
     33   call void @test1_a()
     34   br label %exit
     35 
     36 exit:
     37   ret void
     38 }
     39 
     40 ; CHECK: define void @test1_b3() {
     41 define void @test1_b3() {
     42   call void @unknown()
     43   br i1 false, label %dead, label %exit
     44 
     45 dead:
     46   call void @test1_a()
     47   br label %exit
     48 
     49 exit:
     50   ret void
     51 }
     52 
     53 ; CHECK: define void @test1_b4() #0 {
     54 define void @test1_b4() {
     55   call void @readnone()
     56   br i1 false, label %dead, label %exit
     57 
     58 dead:
     59   call void @test1_a()
     60   br label %exit
     61 
     62 exit:
     63   ret void
     64 }
     65 
     66 
     67 ; The @test2_* set of functions provide similar checks to @test1_* but only
     68 ; splitting the SCCs while leaving the RefSCC intact. This is accomplished by
     69 ; having dummy ref edges to the root function.
     70 
     71 ; CHECK: define void @test2_a() {
     72 define void @test2_a() {
     73   call void @test2_b1()
     74   call void @test2_b2()
     75   call void @test2_b3()
     76   call void @test2_b4()
     77   ret void
     78 }
     79 
     80 ; CHECK: define void @test2_b1() #0 {
     81 define void @test2_b1() {
     82   call void @readnone()
     83   ret void
     84 }
     85 
     86 ; CHECK: define void @test2_b2() #0 {
     87 define void @test2_b2() {
     88   call void @reference_function_pointer(void()* @test2_a)
     89   br i1 false, label %dead, label %exit
     90 
     91 dead:
     92   call void @test2_a()
     93   br label %exit
     94 
     95 exit:
     96   ret void
     97 }
     98 
     99 ; CHECK: define void @test2_b3() {
    100 define void @test2_b3() {
    101   call void @reference_function_pointer(void()* @test2_a)
    102   call void @unknown()
    103   br i1 false, label %dead, label %exit
    104 
    105 dead:
    106   call void @test2_a()
    107   br label %exit
    108 
    109 exit:
    110   ret void
    111 }
    112 
    113 ; CHECK: define void @test2_b4() #0 {
    114 define void @test2_b4() {
    115   call void @reference_function_pointer(void()* @test2_a)
    116   br i1 false, label %dead, label %exit
    117 
    118 dead:
    119   call void @test2_a()
    120   br label %exit
    121 
    122 exit:
    123   ret void
    124 }
    125 
    126 
    127 ; The @test3_* set of functions are the same challenge as @test1_* but with
    128 ; multiple layers that have to be traversed in the correct order instead of
    129 ; a single node.
    130 
    131 ; CHECK: define void @test3_a() {
    132 define void @test3_a() {
    133   call void @test3_b11()
    134   call void @test3_b21()
    135   call void @test3_b31()
    136   call void @test3_b41()
    137   ret void
    138 }
    139 
    140 ; CHECK: define void @test3_b11() #0 {
    141 define void @test3_b11() {
    142   call void @test3_b12()
    143   ret void
    144 }
    145 
    146 ; CHECK: define void @test3_b12() #0 {
    147 define void @test3_b12() {
    148   call void @test3_b13()
    149   ret void
    150 }
    151 
    152 ; CHECK: define void @test3_b13() #0 {
    153 define void @test3_b13() {
    154   call void @readnone()
    155   ret void
    156 }
    157 
    158 ; CHECK: define void @test3_b21() #0 {
    159 define void @test3_b21() {
    160   call void @test3_b22()
    161   ret void
    162 }
    163 
    164 ; CHECK: define void @test3_b22() #0 {
    165 define void @test3_b22() {
    166   call void @test3_b23()
    167   ret void
    168 }
    169 
    170 ; CHECK: define void @test3_b23() #0 {
    171 define void @test3_b23() {
    172   call void @readnone()
    173   br i1 false, label %dead, label %exit
    174 
    175 dead:
    176   call void @test3_a()
    177   br label %exit
    178 
    179 exit:
    180   ret void
    181 }
    182 
    183 ; CHECK: define void @test3_b31() {
    184 define void @test3_b31() {
    185   call void @test3_b32()
    186   ret void
    187 }
    188 
    189 ; CHECK: define void @test3_b32() {
    190 define void @test3_b32() {
    191   call void @test3_b33()
    192   ret void
    193 }
    194 
    195 ; CHECK: define void @test3_b33() {
    196 define void @test3_b33() {
    197   call void @unknown()
    198   br i1 false, label %dead, label %exit
    199 
    200 dead:
    201   call void @test3_a()
    202   br label %exit
    203 
    204 exit:
    205   ret void
    206 }
    207 
    208 ; CHECK: define void @test3_b41() #0 {
    209 define void @test3_b41() {
    210   call void @test3_b42()
    211   ret void
    212 }
    213 
    214 ; CHECK: define void @test3_b42() #0 {
    215 define void @test3_b42() {
    216   call void @test3_b43()
    217   ret void
    218 }
    219 
    220 ; CHECK: define void @test3_b43() #0 {
    221 define void @test3_b43() {
    222   call void @readnone()
    223   br i1 false, label %dead, label %exit
    224 
    225 dead:
    226   call void @test3_a()
    227   br label %exit
    228 
    229 exit:
    230   ret void
    231 }
    232 
    233 
    234 ; The @test4_* functions exercise the same core challenge as the @test2_*
    235 ; functions, but again include long chains instead of single nodes and ensure
    236 ; we traverse the chains in the correct order.
    237 
    238 ; CHECK: define void @test4_a() {
    239 define void @test4_a() {
    240   call void @test4_b11()
    241   call void @test4_b21()
    242   call void @test4_b31()
    243   call void @test4_b41()
    244   ret void
    245 }
    246 
    247 ; CHECK: define void @test4_b11() #0 {
    248 define void @test4_b11() {
    249   call void @test4_b12()
    250   ret void
    251 }
    252 
    253 ; CHECK: define void @test4_b12() #0 {
    254 define void @test4_b12() {
    255   call void @test4_b13()
    256   ret void
    257 }
    258 
    259 ; CHECK: define void @test4_b13() #0 {
    260 define void @test4_b13() {
    261   call void @readnone()
    262   ret void
    263 }
    264 
    265 ; CHECK: define void @test4_b21() #0 {
    266 define void @test4_b21() {
    267   call void @test4_b22()
    268   ret void
    269 }
    270 
    271 ; CHECK: define void @test4_b22() #0 {
    272 define void @test4_b22() {
    273   call void @test4_b23()
    274   ret void
    275 }
    276 
    277 ; CHECK: define void @test4_b23() #0 {
    278 define void @test4_b23() {
    279   call void @reference_function_pointer(void()* @test4_a)
    280   br i1 false, label %dead, label %exit
    281 
    282 dead:
    283   call void @test4_a()
    284   br label %exit
    285 
    286 exit:
    287   ret void
    288 }
    289 
    290 ; CHECK: define void @test4_b31() {
    291 define void @test4_b31() {
    292   call void @test4_b32()
    293   ret void
    294 }
    295 
    296 ; CHECK: define void @test4_b32() {
    297 define void @test4_b32() {
    298   call void @test4_b33()
    299   ret void
    300 }
    301 
    302 ; CHECK: define void @test4_b33() {
    303 define void @test4_b33() {
    304   call void @reference_function_pointer(void()* @test4_a)
    305   call void @unknown()
    306   br i1 false, label %dead, label %exit
    307 
    308 dead:
    309   call void @test4_a()
    310   br label %exit
    311 
    312 exit:
    313   ret void
    314 }
    315 
    316 ; CHECK: define void @test4_b41() #0 {
    317 define void @test4_b41() {
    318   call void @test4_b42()
    319   ret void
    320 }
    321 
    322 ; CHECK: define void @test4_b42() #0 {
    323 define void @test4_b42() {
    324   call void @test4_b43()
    325   ret void
    326 }
    327 
    328 ; CHECK: define void @test4_b43() #0 {
    329 define void @test4_b43() {
    330   call void @reference_function_pointer(void()* @test4_a)
    331   br i1 false, label %dead, label %exit
    332 
    333 dead:
    334   call void @test4_a()
    335   br label %exit
    336 
    337 exit:
    338   ret void
    339 }
    340 
    341 ; CHECK: attributes #0 = { readnone }
    342