Home | History | Annotate | Download | only in llvm-ir
      1 ; Test the 'call' instruction and the tailcall variant.
      2 
      3 ; FIXME: We should remove the need for -enable-mips-tail-calls
      4 ; RUN: llc -march=mips   -mcpu=mips32   -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
      5 ; RUN: llc -march=mips   -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
      6 ; RUN: llc -march=mips   -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
      7 ; RUN: llc -march=mips64 -mcpu=mips4    -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
      8 ; RUN: llc -march=mips64 -mcpu=mips64   -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
      9 ; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
     10 ; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
     11 
     12 declare void @extern_void_void()
     13 declare i32 @extern_i32_void()
     14 declare float @extern_float_void()
     15 
     16 define i32 @call_void_void() {
     17 ; ALL-LABEL: call_void_void:
     18 
     19 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     20 
     21 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     22 
     23 ; ALL:           jalr $[[TGT]]
     24 
     25   call void @extern_void_void()
     26   ret i32 0
     27 }
     28 
     29 define i32 @call_i32_void() {
     30 ; ALL-LABEL: call_i32_void:
     31 
     32 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     33 
     34 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     35 
     36 ; ALL:           jalr $[[TGT]]
     37 
     38   %1 = call i32 @extern_i32_void()
     39   %2 = add i32 %1, 1
     40   ret i32 %2
     41 }
     42 
     43 define float @call_float_void() {
     44 ; ALL-LABEL: call_float_void:
     45 
     46 ; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
     47 ;        look into it at some point.
     48 ; O32:           addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
     49 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
     50 
     51 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
     52 
     53 ; ALL:           jalr $[[TGT]]
     54 
     55 ; O32:           move $gp, $[[GP]]
     56 
     57   %1 = call float @extern_float_void()
     58   %2 = fadd float %1, 1.0
     59   ret float %2
     60 }
     61 
     62 define void @musttail_call_void_void() {
     63 ; ALL-LABEL: musttail_call_void_void:
     64 
     65 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     66 
     67 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     68 
     69 ; NOT-R6:        jr $[[TGT]]
     70 ; R6:            r6.jr $[[TGT]]
     71 
     72   musttail call void @extern_void_void()
     73   ret void
     74 }
     75 
     76 define i32 @musttail_call_i32_void() {
     77 ; ALL-LABEL: musttail_call_i32_void:
     78 
     79 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     80 
     81 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     82 
     83 ; NOT-R6:        jr $[[TGT]]
     84 ; R6:            r6.jr $[[TGT]]
     85 
     86   %1 = musttail call i32 @extern_i32_void()
     87   ret i32 %1
     88 }
     89 
     90 define float @musttail_call_float_void() {
     91 ; ALL-LABEL: musttail_call_float_void:
     92 
     93 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
     94 
     95 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
     96 
     97 ; NOT-R6:        jr $[[TGT]]
     98 ; R6:            r6.jr $[[TGT]]
     99 
    100   %1 = musttail call float @extern_float_void()
    101   ret float %1
    102 }
    103 
    104 define i32 @indirect_call_void_void(void ()* %addr) {
    105 ; ALL-LABEL: indirect_call_void_void:
    106 
    107 ; ALL:           move $25, $4
    108 ; ALL:           jalr $25
    109 
    110   call void %addr()
    111   ret i32 0
    112 }
    113 
    114 define i32 @indirect_call_i32_void(i32 ()* %addr) {
    115 ; ALL-LABEL: indirect_call_i32_void:
    116 
    117 ; ALL:           move $25, $4
    118 ; ALL:           jalr $25
    119 
    120   %1 = call i32 %addr()
    121   %2 = add i32 %1, 1
    122   ret i32 %2
    123 }
    124 
    125 define float @indirect_call_float_void(float ()* %addr) {
    126 ; ALL-LABEL: indirect_call_float_void:
    127 
    128 ; ALL:           move $25, $4
    129 ; ALL:           jalr $25
    130 
    131   %1 = call float %addr()
    132   %2 = fadd float %1, 1.0
    133   ret float %2
    134 }
    135 
    136 ; We can't use 'musttail' here because the verifier is too conservative and
    137 ; prohibits any prototype difference.
    138 define void @tail_indirect_call_void_void(void ()* %addr) {
    139 ; ALL-LABEL: tail_indirect_call_void_void:
    140 
    141 ; ALL:           move $25, $4
    142 ; ALL:           jr $25
    143 
    144   tail call void %addr()
    145   ret void
    146 }
    147 
    148 define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
    149 ; ALL-LABEL: tail_indirect_call_i32_void:
    150 
    151 ; ALL:           move $25, $4
    152 ; ALL:           jr $25
    153 
    154   %1 = tail call i32 %addr()
    155   ret i32 %1
    156 }
    157 
    158 define float @tail_indirect_call_float_void(float ()* %addr) {
    159 ; ALL-LABEL: tail_indirect_call_float_void:
    160 
    161 ; ALL:           move $25, $4
    162 ; ALL:           jr $25
    163 
    164   %1 = tail call float %addr()
    165   ret float %1
    166 }
    167