Home | History | Annotate | Download | only in SimplifyCFG
      1 ; RUN: opt -simplifycfg -S -o - < %s | FileCheck %s
      2 
      3 declare void @helper(i32)
      4 
      5 define void @test1(i1 %a, i1 %b) {
      6 ; CHECK-LABEL: @test1(
      7 entry:
      8   br i1 %a, label %Y, label %X, !prof !0
      9 ; CHECK: br i1 %or.cond, label %Z, label %Y, !prof !0
     10 
     11 X:
     12   %c = or i1 %b, false
     13   br i1 %c, label %Z, label %Y, !prof !1
     14 
     15 Y:
     16   call void @helper(i32 0)
     17   ret void
     18 
     19 Z:
     20   call void @helper(i32 1)
     21   ret void
     22 }
     23 
     24 define void @test2(i1 %a, i1 %b) {
     25 ; CHECK-LABEL: @test2(
     26 entry:
     27   br i1 %a, label %X, label %Y, !prof !1
     28 ; CHECK: br i1 %or.cond, label %Z, label %Y, !prof !1
     29 ; CHECK-NOT: !prof
     30 
     31 X:
     32   %c = or i1 %b, false
     33   br i1 %c, label %Z, label %Y, !prof !2
     34 
     35 Y:
     36   call void @helper(i32 0)
     37   ret void
     38 
     39 Z:
     40   call void @helper(i32 1)
     41   ret void
     42 }
     43 
     44 define void @test3(i1 %a, i1 %b) {
     45 ; CHECK-LABEL: @test3(
     46 ; CHECK-NOT: !prof
     47 entry:
     48   br i1 %a, label %X, label %Y, !prof !1
     49 
     50 X:
     51   %c = or i1 %b, false
     52   br i1 %c, label %Z, label %Y
     53 
     54 Y:
     55   call void @helper(i32 0)
     56   ret void
     57 
     58 Z:
     59   call void @helper(i32 1)
     60   ret void
     61 }
     62 
     63 define void @test4(i1 %a, i1 %b) {
     64 ; CHECK-LABEL: @test4(
     65 ; CHECK-NOT: !prof
     66 entry:
     67   br i1 %a, label %X, label %Y
     68 
     69 X:
     70   %c = or i1 %b, false
     71   br i1 %c, label %Z, label %Y, !prof !1
     72 
     73 Y:
     74   call void @helper(i32 0)
     75   ret void
     76 
     77 Z:
     78   call void @helper(i32 1)
     79   ret void
     80 }
     81 
     82 ;; test5 - The case where it jumps to the default target will be removed.
     83 define void @test5(i32 %M, i32 %N) nounwind uwtable {
     84 entry:
     85   switch i32 %N, label %sw2 [
     86     i32 1, label %sw2
     87     i32 2, label %sw.bb
     88     i32 3, label %sw.bb1
     89   ], !prof !3
     90 ; CHECK: test5
     91 ; CHECK: switch i32 %N, label %sw2 [
     92 ; CHECK: i32 3, label %sw.bb1
     93 ; CHECK: i32 2, label %sw.bb
     94 ; CHECK: ], !prof !2
     95 
     96 sw.bb:
     97   call void @helper(i32 0)
     98   br label %sw.epilog
     99 
    100 sw.bb1:
    101   call void @helper(i32 1)
    102   br label %sw.epilog
    103 
    104 sw2:
    105   call void @helper(i32 2)
    106   br label %sw.epilog
    107 
    108 sw.epilog:
    109   ret void
    110 }
    111 
    112 ;; test6 - Some cases of the second switch are pruned during optimization.
    113 ;; Then the second switch will be converted to a branch, finally, the first
    114 ;; switch and the branch will be merged into a single switch.
    115 define void @test6(i32 %M, i32 %N) nounwind uwtable {
    116 entry:
    117   switch i32 %N, label %sw2 [
    118     i32 1, label %sw2
    119     i32 2, label %sw.bb
    120     i32 3, label %sw.bb1
    121   ], !prof !4
    122 ; CHECK: test6
    123 ; CHECK: switch i32 %N, label %sw.epilog
    124 ; CHECK: i32 3, label %sw.bb1
    125 ; CHECK: i32 2, label %sw.bb
    126 ; CHECK: i32 4, label %sw.bb5
    127 ; CHECK: ], !prof !3
    128 
    129 sw.bb:
    130   call void @helper(i32 0)
    131   br label %sw.epilog
    132 
    133 sw.bb1:
    134   call void @helper(i32 1)
    135   br label %sw.epilog
    136 
    137 sw2:
    138 ;; Here "case 2" is invalidated since the default case of the first switch
    139 ;; does not include "case 2".
    140   switch i32 %N, label %sw.epilog [
    141     i32 2, label %sw.bb4
    142     i32 4, label %sw.bb5
    143   ], !prof !5
    144 
    145 sw.bb4:
    146   call void @helper(i32 2)
    147   br label %sw.epilog
    148 
    149 sw.bb5:
    150   call void @helper(i32 3)
    151   br label %sw.epilog
    152 
    153 sw.epilog:
    154   ret void
    155 }
    156 
    157 ;; This test is based on test1 but swapped the targets of the second branch.
    158 define void @test1_swap(i1 %a, i1 %b) {
    159 ; CHECK-LABEL: @test1_swap(
    160 entry:
    161   br i1 %a, label %Y, label %X, !prof !0
    162 ; CHECK: br i1 %or.cond, label %Y, label %Z, !prof !4
    163 
    164 X:
    165   %c = or i1 %b, false
    166   br i1 %c, label %Y, label %Z, !prof !1
    167 
    168 Y:
    169   call void @helper(i32 0)
    170   ret void
    171 
    172 Z:
    173   call void @helper(i32 1)
    174   ret void
    175 }
    176 
    177 define void @test7(i1 %a, i1 %b) {
    178 ; CHECK-LABEL: @test7(
    179 entry:
    180   %c = or i1 %b, false
    181   br i1 %a, label %Y, label %X, !prof !0
    182 ; CHECK: br i1 %brmerge, label %Y, label %Z, !prof !5
    183 
    184 X:
    185   br i1 %c, label %Y, label %Z, !prof !6
    186 
    187 Y:
    188   call void @helper(i32 0)
    189   ret void
    190 
    191 Z:
    192   call void @helper(i32 1)
    193   ret void
    194 }
    195 
    196 ; Test basic folding to a conditional branch.
    197 define void @test8(i64 %x, i64 %y) nounwind {
    198 ; CHECK-LABEL: @test8(
    199 entry:
    200     %lt = icmp slt i64 %x, %y
    201 ; CHECK: br i1 %lt, label %a, label %b, !prof !6
    202     %qux = select i1 %lt, i32 0, i32 2
    203     switch i32 %qux, label %bees [
    204         i32 0, label %a
    205         i32 1, label %b
    206         i32 2, label %b
    207     ], !prof !7
    208 a:
    209     call void @helper(i32 0) nounwind
    210     ret void
    211 b:
    212     call void @helper(i32 1) nounwind
    213     ret void
    214 bees:
    215     call void @helper(i32 2) nounwind
    216     ret void
    217 }
    218 
    219 ; Test edge splitting when the default target has icmp and unconditinal
    220 ; branch
    221 define i1 @test9(i32 %x, i32 %y) nounwind {
    222 ; CHECK-LABEL: @test9(
    223 entry:
    224     switch i32 %x, label %bees [
    225         i32 0, label %a
    226         i32 1, label %end
    227         i32 2, label %end
    228     ], !prof !7
    229 ; CHECK: switch i32 %x, label %bees [
    230 ; CHECK: i32 0, label %a
    231 ; CHECK: i32 1, label %end
    232 ; CHECK: i32 2, label %end
    233 ; CHECK: i32 92, label %end
    234 ; CHECK: ], !prof !7
    235 
    236 a:
    237     call void @helper(i32 0) nounwind
    238     %reta = icmp slt i32 %x, %y
    239     ret i1 %reta
    240 
    241 bees:
    242     %tmp = icmp eq i32 %x, 92
    243     br label %end
    244 
    245 end:
    246 ; CHECK: end:
    247 ; CHECK: %ret = phi i1 [ true, %entry ], [ false, %bees ], [ true, %entry ], [ true, %entry ]
    248     %ret = phi i1 [ true, %entry ], [%tmp, %bees], [true, %entry]
    249     call void @helper(i32 2) nounwind
    250     ret i1 %ret
    251 }
    252 
    253 define void @test10(i32 %x) nounwind readnone ssp noredzone {
    254 entry:
    255  switch i32 %x, label %lor.rhs [
    256    i32 2, label %lor.end
    257    i32 1, label %lor.end
    258    i32 3, label %lor.end
    259  ], !prof !7
    260 
    261 lor.rhs:
    262  call void @helper(i32 1) nounwind
    263  ret void
    264 
    265 lor.end:
    266  call void @helper(i32 0) nounwind
    267  ret void
    268 
    269 ; CHECK: test10
    270 ; CHECK: %x.off = add i32 %x, -1
    271 ; CHECK: %switch = icmp ult i32 %x.off, 3
    272 ; CHECK: br i1 %switch, label %lor.end, label %lor.rhs, !prof !8
    273 }
    274 
    275 ; Remove dead cases from the switch.
    276 define void @test11(i32 %x) nounwind {
    277   %i = shl i32 %x, 1
    278   switch i32 %i, label %a [
    279     i32 21, label %b
    280     i32 24, label %c
    281   ], !prof !8
    282 ; CHECK: %cond = icmp eq i32 %i, 24
    283 ; CHECK: br i1 %cond, label %c, label %a, !prof !9
    284 
    285 a:
    286  call void @helper(i32 0) nounwind
    287  ret void
    288 b:
    289  call void @helper(i32 1) nounwind
    290  ret void
    291 c:
    292  call void @helper(i32 2) nounwind
    293  ret void
    294 }
    295 
    296 !0 = metadata !{metadata !"branch_weights", i32 3, i32 5}
    297 !1 = metadata !{metadata !"branch_weights", i32 1, i32 1}
    298 !2 = metadata !{metadata !"branch_weights", i32 1, i32 2}
    299 !3 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1}
    300 !4 = metadata !{metadata !"branch_weights", i32 4, i32 3, i32 2, i32 1}
    301 !5 = metadata !{metadata !"branch_weights", i32 7, i32 6, i32 5}
    302 !6 = metadata !{metadata !"branch_weights", i32 1, i32 3}
    303 !7 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8, i32 7}
    304 !8 = metadata !{metadata !"branch_weights", i32 33, i32 9, i32 8}
    305 
    306 ; CHECK: !0 = metadata !{metadata !"branch_weights", i32 5, i32 11}
    307 ; CHECK: !1 = metadata !{metadata !"branch_weights", i32 1, i32 5}
    308 ; CHECK: !2 = metadata !{metadata !"branch_weights", i32 7, i32 1, i32 2}
    309 ; CHECK: !3 = metadata !{metadata !"branch_weights", i32 49, i32 12, i32 24, i32 35}
    310 ; CHECK: !4 = metadata !{metadata !"branch_weights", i32 11, i32 5}
    311 ; CHECK: !5 = metadata !{metadata !"branch_weights", i32 17, i32 15} 
    312 ; CHECK: !6 = metadata !{metadata !"branch_weights", i32 9, i32 7}
    313 ; CHECK: !7 = metadata !{metadata !"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17}
    314 ; CHECK: !8 = metadata !{metadata !"branch_weights", i32 24, i32 33}
    315 ; CHECK: !9 = metadata !{metadata !"branch_weights", i32 8, i32 33}
    316 ; CHECK-NOT: !9
    317