Home | History | Annotate | Download | only in llvm-ir
      1 ; Test the 'call' instruction and the tailcall variant.
      2 
      3 ; RUN: llc -march=mips   -mcpu=mips32   -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
      4 ; RUN: llc -march=mips   -mcpu=mips32r2 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
      5 ; RUN: llc -march=mips   -mcpu=mips32r3 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
      6 ; RUN: llc -march=mips   -mcpu=mips32r5 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
      7 ; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C
      8 ; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C
      9 ; RUN: llc -march=mips64 -mcpu=mips4    -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
     10 ; RUN: llc -march=mips64 -mcpu=mips64   -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
     11 ; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
     12 ; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
     13 ; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
     14 ; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic  -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,R6C
     15 ; RUN: llc -march=mips   -mcpu=mips32   -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
     16 ; RUN: llc -march=mips   -mcpu=mips32r2 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
     17 ; RUN: llc -march=mips   -mcpu=mips32r3 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
     18 ; RUN: llc -march=mips   -mcpu=mips32r5 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
     19 ; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
     20 ; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
     21 ; RUN: llc -march=mips64 -mcpu=mips4    -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
     22 ; RUN: llc -march=mips64 -mcpu=mips64   -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
     23 ; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
     24 ; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
     25 ; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
     26 ; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic  -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=R6C
     27 
     28 declare void @extern_void_void()
     29 declare i32 @extern_i32_void()
     30 declare float @extern_float_void()
     31 
     32 define i32 @call_void_void() {
     33 ; ALL-LABEL: call_void_void:
     34 
     35 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     36 
     37 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
     38 
     39 ; NOT-R6C:       jalr $[[TGT]]
     40 ; R6C:           jalrc $[[TGT]]
     41 
     42   call void @extern_void_void()
     43 ; R6C:           jrc $ra
     44   ret i32 0
     45 }
     46 
     47 define i32 @call_i32_void() {
     48 ; ALL-LABEL: call_i32_void:
     49 
     50 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     51 
     52 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
     53 
     54 ; NOT-R6C:       jalr $[[TGT]]
     55 ; R6C:           jalrc $[[TGT]]
     56 
     57   %1 = call i32 @extern_i32_void()
     58   %2 = add i32 %1, 1
     59 ; R6C:           jrc $ra
     60   ret i32 %2
     61 }
     62 
     63 define float @call_float_void() {
     64 ; ALL-LABEL: call_float_void:
     65 
     66 ; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
     67 ;        look into it at some point.
     68 ; O32:           addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
     69 ; O32:           lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
     70 
     71 ; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
     72 
     73 ; NOT-R6C:       jalr $[[TGT]]
     74 ; R6C:           jalrc $[[TGT]]
     75 
     76 
     77   %1 = call float @extern_float_void()
     78   %2 = fadd float %1, 1.0
     79 ; R6C:           jrc $ra
     80   ret float %2
     81 }
     82 
     83 define i32 @indirect_call_void_void(void ()* %addr) {
     84 ; ALL-LABEL: indirect_call_void_void:
     85 
     86 ; ALL:           move $25, $4
     87 ; NOT-R6C:       jalr $25
     88 ; R6C:           jalrc $25
     89 
     90   call void %addr()
     91 ; R6C:           jrc $ra
     92   ret i32 0
     93 }
     94 
     95 define i32 @indirect_call_i32_void(i32 ()* %addr) {
     96 ; ALL-LABEL: indirect_call_i32_void:
     97 
     98 ; ALL:           move $25, $4
     99 ; NOT-R6C:       jalr $25
    100 ; R6C:           jalrc $25
    101 
    102 
    103   %1 = call i32 %addr()
    104   %2 = add i32 %1, 1
    105 ; R6C:           jrc $ra
    106   ret i32 %2
    107 }
    108 
    109 define float @indirect_call_float_void(float ()* %addr) {
    110 ; ALL-LABEL: indirect_call_float_void:
    111 
    112 ; ALL:           move $25, $4
    113 ; NOT-R6C:       jalr $25
    114 ; R6C:           jalrc $25
    115 
    116 
    117   %1 = call float %addr()
    118   %2 = fadd float %1, 1.0
    119 ; R6C:           jrc $ra
    120   ret float %2
    121 }
    122 
    123 ; We can't use 'musttail' here because the verifier is too conservative and
    124 ; prohibits any prototype difference.
    125 define void @tail_indirect_call_void_void(void ()* %addr) {
    126 ; ALL-LABEL: tail_indirect_call_void_void:
    127 
    128 ; ALL:           move $25, $4
    129 ; NOT-R6C:       jr   $[[TGT]]
    130 ; R6C:           jrc  $[[TGT]]
    131 
    132   tail call void %addr()
    133   ret void
    134 }
    135 
    136 define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
    137 ; ALL-LABEL: tail_indirect_call_i32_void:
    138 
    139 ; ALL:           move $25, $4
    140 ; NOT-R6C:       jr   $[[TGT]]
    141 ; R6C:           jrc  $[[TGT]]
    142 
    143   %1 = tail call i32 %addr()
    144   ret i32 %1
    145 }
    146 
    147 define float @tail_indirect_call_float_void(float ()* %addr) {
    148 ; ALL-LABEL: tail_indirect_call_float_void:
    149 
    150 ; ALL:           move $25, $4
    151 ; NOT-R6C:       jr   $[[TGT]]
    152 ; R6C:           jrc  $[[TGT]]
    153 
    154   %1 = tail call float %addr()
    155   ret float %1
    156 }
    157 
    158 ; Check that passing undef as a double value doesn't cause machine code errors
    159 ; for FP64.
    160 declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2
    161 
    162 define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 {
    163 ; ALL-LABEL: thunk_undef_double:
    164 ; O32: # implicit-def: $a2
    165 ; O32: # implicit-def: $a3
    166 ; NOT-R6C:    jr   $[[TGT]]
    167 ; R6C:        jrc  $[[TGT]]
    168 
    169   tail call void @undef_double(i32 undef, double undef) #8
    170   ret void
    171 }
    172 
    173 ; Check that immediate addresses do not use jal.
    174 define i32 @jal_only_allows_symbols() {
    175 ; ALL-LABEL: jal_only_allows_symbols:
    176 
    177 ; ALL-NOT:       {{jal }}
    178 ; ALL:           addiu $[[TGT:[0-9]+]], $zero, 1234
    179 ; ALL-NOT:       {{jal }}
    180 ; NOT-R6C:       jalr $[[TGT]]
    181 ; R6C:           jalrc $[[TGT]]
    182 ; ALL-NOT:       {{jal }}
    183 
    184   call void () inttoptr (i32 1234 to void ()*)()
    185 ; R6C:           jrc $ra
    186   ret i32 0
    187 }
    188 
    189