Home | History | Annotate | Download | only in X86
      1 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -asm-verbose=false | FileCheck %s
      2 
      3 ; These tests check for loop branching structure, and that the loop align
      4 ; directive is placed in the expected place.
      5 
      6 ; CodeGen should insert a branch into the middle of the loop in
      7 ; order to avoid a branch within the loop.
      8 
      9 ; CHECK-LABEL: simple:
     10 ;      CHECK:   jmp   .LBB0_1
     11 ; CHECK-NEXT:   align
     12 ; CHECK-NEXT: .LBB0_2:
     13 ; CHECK-NEXT:   callq loop_latch
     14 ; CHECK-NEXT: .LBB0_1:
     15 ; CHECK-NEXT:   callq loop_header
     16 
     17 define void @simple() nounwind {
     18 entry:
     19   br label %loop
     20 
     21 loop:
     22   call void @loop_header()
     23   %t0 = tail call i32 @get()
     24   %t1 = icmp slt i32 %t0, 0
     25   br i1 %t1, label %done, label %bb
     26 
     27 bb:
     28   call void @loop_latch()
     29   br label %loop
     30 
     31 done:
     32   call void @exit()
     33   ret void
     34 }
     35 
     36 ; CodeGen should move block_a to the top of the loop so that it
     37 ; falls through into the loop, avoiding a branch within the loop.
     38 
     39 ; CHECK-LABEL: slightly_more_involved:
     40 ;      CHECK:   jmp .LBB1_1
     41 ; CHECK-NEXT:   align
     42 ; CHECK-NEXT: .LBB1_4:
     43 ; CHECK-NEXT:   callq bar99
     44 ; CHECK-NEXT: .LBB1_1:
     45 ; CHECK-NEXT:   callq body
     46 
     47 define void @slightly_more_involved() nounwind {
     48 entry:
     49   br label %loop
     50 
     51 loop:
     52   call void @body()
     53   %t0 = call i32 @get()
     54   %t1 = icmp slt i32 %t0, 2
     55   br i1 %t1, label %block_a, label %bb
     56 
     57 bb:
     58   %t2 = call i32 @get()
     59   %t3 = icmp slt i32 %t2, 99
     60   br i1 %t3, label %exit, label %loop
     61 
     62 block_a:
     63   call void @bar99()
     64   br label %loop
     65 
     66 exit:
     67   call void @exit()
     68   ret void
     69 }
     70 
     71 ; Same as slightly_more_involved, but block_a is now a CFG diamond with
     72 ; fallthrough edges which should be preserved.
     73 ; "callq block_a_merge_func" is tail duped.
     74 
     75 ; CHECK-LABEL: yet_more_involved:
     76 ;      CHECK:   jmp .LBB2_1
     77 ; CHECK-NEXT:   align
     78 ; CHECK-NEXT: .LBB2_5:
     79 ; CHECK-NEXT:   callq block_a_true_func
     80 ; CHECK-NEXT:   callq block_a_merge_func
     81 ; CHECK-NEXT: .LBB2_1:
     82 ; CHECK-NEXT:   callq body
     83 ;
     84 ; LBB2_4
     85 ;      CHECK:   callq bar99
     86 ; CHECK-NEXT:   callq get
     87 ; CHECK-NEXT:   cmpl $2999, %eax
     88 ; CHECK-NEXT:   jle .LBB2_5
     89 ; CHECK-NEXT:   callq block_a_false_func
     90 ; CHECK-NEXT:   callq block_a_merge_func
     91 ; CHECK-NEXT:   jmp .LBB2_1
     92 
     93 define void @yet_more_involved() nounwind {
     94 entry:
     95   br label %loop
     96 
     97 loop:
     98   call void @body()
     99   %t0 = call i32 @get()
    100   %t1 = icmp slt i32 %t0, 2
    101   br i1 %t1, label %block_a, label %bb
    102 
    103 bb:
    104   %t2 = call i32 @get()
    105   %t3 = icmp slt i32 %t2, 99
    106   br i1 %t3, label %exit, label %loop
    107 
    108 block_a:
    109   call void @bar99()
    110   %z0 = call i32 @get()
    111   %z1 = icmp slt i32 %z0, 3000
    112   br i1 %z1, label %block_a_true, label %block_a_false
    113 
    114 block_a_true:
    115   call void @block_a_true_func()
    116   br label %block_a_merge
    117 
    118 block_a_false:
    119   call void @block_a_false_func()
    120   br label %block_a_merge
    121 
    122 block_a_merge:
    123   call void @block_a_merge_func()
    124   br label %loop
    125 
    126 exit:
    127   call void @exit()
    128   ret void
    129 }
    130 
    131 ; CodeGen should move the CFG islands that are part of the loop but don't
    132 ; conveniently fit anywhere so that they are at least contiguous with the
    133 ; loop.
    134 
    135 ; CHECK-LABEL: cfg_islands:
    136 ;      CHECK:   jmp     .LBB3_1
    137 ; CHECK-NEXT:   align
    138 ; CHECK-NEXT: .LBB3_7:
    139 ; CHECK-NEXT:   callq   bar100
    140 ; CHECK-NEXT: .LBB3_1:
    141 ; CHECK-NEXT:   callq   loop_header
    142 ;      CHECK:   jl .LBB3_7
    143 ;      CHECK:   jge .LBB3_3
    144 ; CHECK-NEXT:   callq   bar101
    145 ; CHECK-NEXT:   jmp     .LBB3_1
    146 ; CHECK-NEXT:   align
    147 ; CHECK-NEXT: .LBB3_3:
    148 ;      CHECK:   jge .LBB3_4
    149 ; CHECK-NEXT:   callq   bar102
    150 ; CHECK-NEXT:   jmp     .LBB3_1
    151 ; CHECK-NEXT: .LBB3_4:
    152 ;      CHECK:   jl .LBB3_6
    153 ; CHECK-NEXT:   callq   loop_latch
    154 ; CHECK-NEXT:   jmp     .LBB3_1
    155 ; CHECK-NEXT: .LBB3_6:
    156 
    157 define void @cfg_islands() nounwind {
    158 entry:
    159   br label %loop
    160 
    161 loop:
    162   call void @loop_header()
    163   %t0 = call i32 @get()
    164   %t1 = icmp slt i32 %t0, 100
    165   br i1 %t1, label %block100, label %bb
    166 
    167 bb:
    168   %t2 = call i32 @get()
    169   %t3 = icmp slt i32 %t2, 101
    170   br i1 %t3, label %block101, label %bb1
    171 
    172 bb1:
    173   %t4 = call i32 @get()
    174   %t5 = icmp slt i32 %t4, 102
    175   br i1 %t5, label %block102, label %bb2
    176 
    177 bb2:
    178   %t6 = call i32 @get()
    179   %t7 = icmp slt i32 %t6, 103
    180   br i1 %t7, label %exit, label %bb3
    181 
    182 bb3:
    183   call void @loop_latch()
    184   br label %loop
    185 
    186 exit:
    187   call void @exit()
    188   ret void
    189 
    190 block100:
    191   call void @bar100()
    192   br label %loop
    193 
    194 block101:
    195   call void @bar101()
    196   br label %loop
    197 
    198 block102:
    199   call void @bar102()
    200   br label %loop
    201 }
    202 
    203 declare void @bar99() nounwind
    204 declare void @bar100() nounwind
    205 declare void @bar101() nounwind
    206 declare void @bar102() nounwind
    207 declare void @body() nounwind
    208 declare void @exit() nounwind
    209 declare void @loop_header() nounwind
    210 declare void @loop_latch() nounwind
    211 declare i32 @get() nounwind
    212 declare void @block_a_true_func() nounwind
    213 declare void @block_a_false_func() nounwind
    214 declare void @block_a_merge_func() nounwind
    215