Home | History | Annotate | Download | only in XCore
      1 ; RUN: llc < %s -march=xcore | FileCheck %s
      2 ; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP
      3 
      4 declare i8* @llvm.frameaddress(i32) nounwind readnone
      5 declare i8* @llvm.returnaddress(i32) nounwind
      6 declare i8* @llvm.eh.dwarf.cfa(i32) nounwind
      7 declare void @llvm.eh.return.i32(i32, i8*) nounwind
      8 declare void @llvm.eh.unwind.init() nounwind
      9 
     10 define i8* @FA0() nounwind {
     11 entry:
     12 ; CHECK-LABEL: FA0
     13 ; CHECK: ldaw r0, sp[0]
     14 ; CHECK-NEXT: retsp 0
     15   %0 = call i8* @llvm.frameaddress(i32 0)
     16   ret i8* %0
     17 }
     18 
     19 define i8* @FA1() nounwind {
     20 entry:
     21 ; CHECK-LABEL: FA1
     22 ; CHECK: entsp 100
     23 ; CHECK-NEXT: ldaw r0, sp[0]
     24 ; CHECK-NEXT: retsp 100
     25   %0 = alloca [100 x i32]
     26   %1 = call i8* @llvm.frameaddress(i32 0)
     27   ret i8* %1
     28 }
     29 
     30 define i8* @RA0() nounwind {
     31 entry:
     32 ; CHECK-LABEL: RA0
     33 ; CHECK: stw lr, sp[0]
     34 ; CHECK-NEXT: ldw r0, sp[0]
     35 ; CHECK-NEXT: ldw lr, sp[0]
     36 ; CHECK-NEXT: retsp 0
     37   %0 = call i8* @llvm.returnaddress(i32 0)
     38   ret i8* %0
     39 }
     40 
     41 define i8* @RA1() nounwind {
     42 entry:
     43 ; CHECK-LABEL: RA1
     44 ; CHECK: entsp 100
     45 ; CHECK-NEXT: ldw r0, sp[100]
     46 ; CHECK-NEXT: retsp 100
     47   %0 = alloca [100 x i32]
     48   %1 = call i8* @llvm.returnaddress(i32 0)
     49   ret i8* %1
     50 }
     51 
     52 ; test FRAME_TO_ARGS_OFFSET lowering
     53 define i8* @FTAO0() nounwind {
     54 entry:
     55 ; CHECK-LABEL: FTAO0
     56 ; CHECK: ldc r0, 0
     57 ; CHECK-NEXT: ldaw r1, sp[0]
     58 ; CHECK-NEXT: add r0, r1, r0
     59 ; CHECK-NEXT: retsp 0
     60   %0 = call i8* @llvm.eh.dwarf.cfa(i32 0)
     61   ret i8* %0
     62 }
     63 
     64 define i8* @FTAO1() nounwind {
     65 entry:
     66 ; CHECK-LABEL: FTAO1
     67 ; CHECK: entsp 100
     68 ; CHECK-NEXT: ldc r0, 400
     69 ; CHECK-NEXT: ldaw r1, sp[0]
     70 ; CHECK-NEXT: add r0, r1, r0
     71 ; CHECK-NEXT: retsp 100
     72   %0 = alloca [100 x i32]
     73   %1 = call i8* @llvm.eh.dwarf.cfa(i32 0)
     74   ret i8* %1
     75 }
     76 
     77 define i8* @EH0(i32 %offset, i8* %handler) {
     78 entry:
     79 ; CHECK-LABEL: EH0
     80 ; CHECK: entsp 2
     81 ; CHECK: .cfi_def_cfa_offset 8
     82 ; CHECK: .cfi_offset 15, 0
     83 ; CHECK: .cfi_offset 1, -8
     84 ; CHECK: .cfi_offset 0, -4
     85 ; CHECK: ldc r2, 8
     86 ; CHECK-NEXT: ldaw r3, sp[0]
     87 ; CHECK-NEXT: add r2, r3, r2
     88 ; CHECK-NEXT: add r2, r2, r0
     89 ; CHECK-NEXT: mov r3, r1
     90 ; CHECK-NEXT: ldw r1, sp[0]
     91 ; CHECK-NEXT: ldw r0, sp[1]
     92 ; CHECK-NEXT: set sp, r2
     93 ; CHECK-NEXT: bau r3
     94   call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
     95   unreachable
     96 }
     97 
     98 declare void @foo(...)
     99 define i8* @EH1(i32 %offset, i8* %handler) {
    100 entry:
    101 ; CHECK-LABEL: EH1
    102 ; CHECK: entsp 5
    103 ; CHECK: .cfi_def_cfa_offset 20
    104 ; CHECK: .cfi_offset 15, 0
    105 ; CHECK: .cfi_offset 1, -16
    106 ; CHECK: .cfi_offset 0, -12
    107 ; CHECK: stw r4, sp[4]
    108 ; CHECK: .cfi_offset 4, -4
    109 ; CHECK: stw r5, sp[3]
    110 ; CHECK: .cfi_offset 5, -8
    111 ; CHECK: mov r4, r1
    112 ; CHECK-NEXT: mov r5, r0
    113 ; CHECK-NEXT: bl foo
    114 ; CHECK-NEXT: ldc r0, 20
    115 ; CHECK-NEXT: ldaw r1, sp[0]
    116 ; CHECK-NEXT: add r0, r1, r0
    117 ; CHECK-NEXT: add r2, r0, r5
    118 ; CHECK-NEXT: mov r3, r4
    119 ; CHECK-NEXT: ldw r5, sp[3]
    120 ; CHECK-NEXT: ldw r4, sp[4]
    121 ; CHECK-NEXT: ldw r1, sp[1]
    122 ; CHECK-NEXT: ldw r0, sp[2]
    123 ; CHECK-NEXT: set sp, r2
    124 ; CHECK-NEXT: bau r3
    125   call void (...) @foo()
    126   call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
    127   unreachable
    128 }
    129 
    130 @offset = external constant i32
    131 @handler = external constant i8
    132 define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) {
    133 entry:
    134 ; CHECK-LABEL: EH2
    135 ; CHECK: entsp 3
    136 ; CHECK: bl foo
    137 ; CHECK-NEXT: ldw r0, dp[offset]
    138 ; CHECK-NEXT: ldc r1, 12
    139 ; CHECK-NEXT: ldaw r2, sp[0]
    140 ; CHECK-NEXT: add r1, r2, r1
    141 ; CHECK-NEXT: add r2, r1, r0
    142 ; CHECK-NEXT: ldaw r3, dp[handler]
    143 ; CHECK-NEXT: ldw r1, sp[1]
    144 ; CHECK-NEXT: ldw r0, sp[2]
    145 ; CHECK-NEXT: set sp, r2
    146 ; CHECK-NEXT: bau r3
    147   call void (...) @foo()
    148   %0 = load i32, i32* @offset
    149   call void @llvm.eh.return.i32(i32 %0, i8* @handler)
    150   unreachable
    151 }
    152 
    153 
    154 ; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6
    155 ; But we dont actually spill or restore R0:1
    156 ; CHECKFP-LABEL: Unwind0:
    157 ; CHECKFP: entsp 10
    158 ; CHECKFP: stw r10, sp[1]
    159 ; CHECKFP: ldaw r10, sp[0]
    160 ; CHECKFP: stw r4, r10[9]
    161 ; CHECKFP: stw r5, r10[8]
    162 ; CHECKFP: stw r6, r10[7]
    163 ; CHECKFP: stw r7, r10[6]
    164 ; CHECKFP: stw r8, r10[5]
    165 ; CHECKFP: stw r9, r10[4]
    166 ; CHECKFP: ldw r9, r10[4]
    167 ; CHECKFP: ldw r8, r10[5]
    168 ; CHECKFP: ldw r7, r10[6]
    169 ; CHECKFP: ldw r6, r10[7]
    170 ; CHECKFP: ldw r5, r10[8]
    171 ; CHECKFP: ldw r4, r10[9]
    172 ; CHECKFP: set sp, r10
    173 ; CHECKFP: ldw r10, sp[1]
    174 ; CHECKFP: retsp 10
    175 ;
    176 ; !FP: spill R0:1+R4:10 = entsp 2+7
    177 ; But we dont actually spill or restore R0:1
    178 ; CHECK-LABEL: Unwind0:
    179 ; CHECK: entsp 9
    180 ; CHECK: stw r4, sp[8]
    181 ; CHECK: stw r5, sp[7]
    182 ; CHECK: stw r6, sp[6]
    183 ; CHECK: stw r7, sp[5]
    184 ; CHECK: stw r8, sp[4]
    185 ; CHECK: stw r9, sp[3]
    186 ; CHECK: stw r10, sp[2]
    187 ; CHECK: ldw r10, sp[2]
    188 ; CHECK: ldw r9, sp[3]
    189 ; CHECK: ldw r8, sp[4]
    190 ; CHECK: ldw r7, sp[5]
    191 ; CHECK: ldw r6, sp[6]
    192 ; CHECK: ldw r5, sp[7]
    193 ; CHECK: ldw r4, sp[8]
    194 ; CHECK: retsp 9
    195 define void @Unwind0() {
    196   call void @llvm.eh.unwind.init()
    197   ret void
    198 }
    199 
    200 
    201 ; FP: spill FP+SR+R0:1+R4:9+LR = entsp 2+2+6 + extsp 1
    202 ; But we dont actually spill or restore R0:1
    203 ; CHECKFP-LABEL: Unwind1:
    204 ; CHECKFP: entsp 10
    205 ; CHECKFP: stw r10, sp[1]
    206 ; CHECKFP: ldaw r10, sp[0]
    207 ; CHECKFP: stw r4, r10[9]
    208 ; CHECKFP: stw r5, r10[8]
    209 ; CHECKFP: stw r6, r10[7]
    210 ; CHECKFP: stw r7, r10[6]
    211 ; CHECKFP: stw r8, r10[5]
    212 ; CHECKFP: stw r9, r10[4]
    213 ; CHECKFP: extsp 1
    214 ; CHECKFP: bl foo
    215 ; CHECKFP: ldaw sp, sp[1]
    216 ; CHECKFP: ldw r9, r10[4]
    217 ; CHECKFP: ldw r8, r10[5]
    218 ; CHECKFP: ldw r7, r10[6]
    219 ; CHECKFP: ldw r6, r10[7]
    220 ; CHECKFP: ldw r5, r10[8]
    221 ; CHECKFP: ldw r4, r10[9]
    222 ; CHECKFP: set sp, r10
    223 ; CHECKFP: ldw r10, sp[1]
    224 ; CHECKFP: retsp 10
    225 ;
    226 ; !FP: spill R0:1+R4:10+LR = entsp 2+7+1
    227 ; But we dont actually spill or restore R0:1
    228 ; CHECK-LABEL: Unwind1:
    229 ; CHECK: entsp 10
    230 ; CHECK: stw r4, sp[9]
    231 ; CHECK: stw r5, sp[8]
    232 ; CHECK: stw r6, sp[7]
    233 ; CHECK: stw r7, sp[6]
    234 ; CHECK: stw r8, sp[5]
    235 ; CHECK: stw r9, sp[4]
    236 ; CHECK: stw r10, sp[3]
    237 ; CHECK: bl foo
    238 ; CHECK: ldw r10, sp[3]
    239 ; CHECK: ldw r9, sp[4]
    240 ; CHECK: ldw r8, sp[5]
    241 ; CHECK: ldw r7, sp[6]
    242 ; CHECK: ldw r6, sp[7]
    243 ; CHECK: ldw r5, sp[8]
    244 ; CHECK: ldw r4, sp[9]
    245 ; CHECK: retsp 10
    246 define void @Unwind1() {
    247   call void (...) @foo()
    248   call void @llvm.eh.unwind.init()
    249   ret void
    250 }
    251 
    252 ; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6
    253 ; We dont spill R0:1
    254 ; We only restore R0:1 during eh.return
    255 ; CHECKFP-LABEL: UnwindEH:
    256 ; CHECKFP: entsp 10
    257 ; CHECKFP: .cfi_def_cfa_offset 40
    258 ; CHECKFP: .cfi_offset 15, 0
    259 ; CHECKFP: stw r10, sp[1]
    260 ; CHECKFP: .cfi_offset 10, -36
    261 ; CHECKFP: ldaw r10, sp[0]
    262 ; CHECKFP: .cfi_def_cfa_register 10
    263 ; CHECKFP: .cfi_offset 1, -32
    264 ; CHECKFP: .cfi_offset 0, -28
    265 ; CHECKFP: stw r4, r10[9]
    266 ; CHECKFP: .cfi_offset 4, -4
    267 ; CHECKFP: stw r5, r10[8]
    268 ; CHECKFP: .cfi_offset 5, -8
    269 ; CHECKFP: stw r6, r10[7]
    270 ; CHECKFP: .cfi_offset 6, -12
    271 ; CHECKFP: stw r7, r10[6]
    272 ; CHECKFP: .cfi_offset 7, -16
    273 ; CHECKFP: stw r8, r10[5]
    274 ; CHECKFP: .cfi_offset 8, -20
    275 ; CHECKFP: stw r9, r10[4]
    276 ; CHECKFP: .cfi_offset 9, -24
    277 ; CHECKFP: bt r0, .LBB{{[0-9_]+}}
    278 ; CHECKFP: ldw r9, r10[4]
    279 ; CHECKFP-NEXT: ldw r8, r10[5]
    280 ; CHECKFP-NEXT: ldw r7, r10[6]
    281 ; CHECKFP-NEXT: ldw r6, r10[7]
    282 ; CHECKFP-NEXT: ldw r5, r10[8]
    283 ; CHECKFP-NEXT: ldw r4, r10[9]
    284 ; CHECKFP-NEXT: set sp, r10
    285 ; CHECKFP-NEXT: ldw r10, sp[1]
    286 ; CHECKFP-NEXT: retsp 10
    287 ; CHECKFP: .LBB{{[0-9_]+}}
    288 ; CHECKFP-NEXT: ldc r2, 40
    289 ; CHECKFP-NEXT: add r2, r10, r2
    290 ; CHECKFP-NEXT: add r2, r2, r0
    291 ; CHECKFP-NEXT: mov r3, r1
    292 ; CHECKFP-NEXT: ldw r9, r10[4]
    293 ; CHECKFP-NEXT: ldw r8, r10[5]
    294 ; CHECKFP-NEXT: ldw r7, r10[6]
    295 ; CHECKFP-NEXT: ldw r6, r10[7]
    296 ; CHECKFP-NEXT: ldw r5, r10[8]
    297 ; CHECKFP-NEXT: ldw r4, r10[9]
    298 ; CHECKFP-NEXT: ldw r1, sp[2]
    299 ; CHECKFP-NEXT: ldw r0, sp[3]
    300 ; CHECKFP-NEXT: set sp, r2
    301 ; CHECKFP-NEXT: bau r3
    302 ;
    303 ; !FP: spill R0:1+R4:10 = entsp 2+7
    304 ; We dont spill R0:1
    305 ; We only restore R0:1 during eh.return
    306 ; CHECK-LABEL: UnwindEH:
    307 ; CHECK: entsp 9
    308 ; CHECK: .cfi_def_cfa_offset 36
    309 ; CHECK: .cfi_offset 15, 0
    310 ; CHECK: .cfi_offset 1, -36
    311 ; CHECK: .cfi_offset 0, -32
    312 ; CHECK: stw r4, sp[8]
    313 ; CHECK: .cfi_offset 4, -4
    314 ; CHECK: stw r5, sp[7]
    315 ; CHECK: .cfi_offset 5, -8
    316 ; CHECK: stw r6, sp[6]
    317 ; CHECK: .cfi_offset 6, -12
    318 ; CHECK: stw r7, sp[5]
    319 ; CHECK: .cfi_offset 7, -16
    320 ; CHECK: stw r8, sp[4]
    321 ; CHECK: .cfi_offset 8, -20
    322 ; CHECK: stw r9, sp[3]
    323 ; CHECK: .cfi_offset 9, -24
    324 ; CHECK: stw r10, sp[2]
    325 ; CHECK: .cfi_offset 10, -28
    326 ; CHECK: bt r0, .LBB{{[0-9_]+}}
    327 ; CHECK: ldw r10, sp[2]
    328 ; CHECK-NEXT: ldw r9, sp[3]
    329 ; CHECK-NEXT: ldw r8, sp[4]
    330 ; CHECK-NEXT: ldw r7, sp[5]
    331 ; CHECK-NEXT: ldw r6, sp[6]
    332 ; CHECK-NEXT: ldw r5, sp[7]
    333 ; CHECK-NEXT: ldw r4, sp[8]
    334 ; CHECK-NEXT: retsp 9
    335 ; CHECK: .LBB{{[0-9_]+}}
    336 ; CHECK-NEXT: ldc r2, 36
    337 ; CHECK-NEXT: ldaw r3, sp[0]
    338 ; CHECK-NEXT: add r2, r3, r2
    339 ; CHECK-NEXT: add r2, r2, r0
    340 ; CHECK-NEXT: mov r3, r1
    341 ; CHECK-NEXT: ldw r10, sp[2]
    342 ; CHECK-NEXT: ldw r9, sp[3]
    343 ; CHECK-NEXT: ldw r8, sp[4]
    344 ; CHECK-NEXT: ldw r7, sp[5]
    345 ; CHECK-NEXT: ldw r6, sp[6]
    346 ; CHECK-NEXT: ldw r5, sp[7]
    347 ; CHECK-NEXT: ldw r4, sp[8]
    348 ; CHECK-NEXT: ldw r1, sp[0]
    349 ; CHECK-NEXT: ldw r0, sp[1]
    350 ; CHECK-NEXT: set sp, r2
    351 ; CHECK-NEXT: bau r3
    352 define void @UnwindEH(i32 %offset, i8* %handler) {
    353   call void @llvm.eh.unwind.init()
    354   %cmp = icmp eq i32 %offset, 0
    355   br i1 %cmp, label %normal, label %eh
    356 eh:
    357   call void @llvm.eh.return.i32(i32 %offset, i8* %handler)
    358   unreachable
    359 normal:
    360   ret void
    361 }
    362