Home | History | Annotate | Download | only in PowerPC
      1 ; RUN: llc < %s -relocation-model=static -O1 -disable-ppc-sco=false -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=CHECK-SCO
      2 ; RUN: llc < %s -relocation-model=static -O1 -disable-ppc-sco=false -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-SCO-HASQPX
      3 ; RUN: llc < %s -relocation-model=static -O1 -disable-ppc-sco=false -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-SCO-HASQPX
      4 ; RUN: llc < %s -relocation-model=static -O1 -disable-ppc-sco=false -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 -code-model=small | FileCheck %s -check-prefix=SCM
      5 
      6 ; No combination of "powerpc64le-unknown-linux-gnu" + "CHECK-SCO", because
      7 ; only Power8 (and later) fully support LE.
      8 
      9 %S_56 = type { [13 x i32], i32 }
     10 %S_64 = type { [15 x i32], i32 }
     11 %S_32 = type { [7 x i32], i32 }
     12 
     13 ; Function Attrs: noinline nounwind
     14 define void @callee_56_copy([7 x i64] %a, %S_56* %b) #0 { ret void }
     15 define void @callee_64_copy([8 x i64] %a, %S_64* %b) #0 { ret void }
     16 
     17 ; Function Attrs: nounwind
     18 define void @caller_56_reorder_copy(%S_56* %b, [7 x i64] %a) #1 {
     19   tail call void @callee_56_copy([7 x i64] %a, %S_56* %b)
     20   ret void
     21 
     22 ; CHECK-SCO-LABEL: caller_56_reorder_copy:
     23 ; CHECK-SCO-NOT: stdu 1
     24 ; CHECK-SCO: TC_RETURNd8 callee_56_copy
     25 }
     26 
     27 define void @caller_64_reorder_copy(%S_64* %b, [8 x i64] %a) #1 {
     28   tail call void @callee_64_copy([8 x i64] %a, %S_64* %b)
     29   ret void
     30 
     31 ; CHECK-SCO-LABEL: caller_64_reorder_copy:
     32 ; CHECK-SCO: bl callee_64_copy
     33 }
     34 
     35 define void @callee_64_64_copy([8 x i64] %a, [8 x i64] %b) #0 { ret void }
     36 define void @caller_64_64_copy([8 x i64] %a, [8 x i64] %b) #1 {
     37   tail call void @callee_64_64_copy([8 x i64] %a, [8 x i64] %b)
     38   ret void
     39 
     40 ; CHECK-SCO-LABEL: caller_64_64_copy:
     41 ; CHECK-SCO: b callee_64_64_copy
     42 }
     43 
     44 define internal fastcc void @callee_64_64_copy_fastcc([8 x i64] %a, [8 x i64] %b) #0 { ret void }
     45 define void @caller_64_64_copy_ccc([8 x i64] %a, [8 x i64] %b) #1 {
     46   tail call fastcc void @callee_64_64_copy_fastcc([8 x i64] %a, [8 x i64] %b)
     47   ret void
     48 ; If caller and callee use different calling convensions, we cannot apply TCO.
     49 ; CHECK-SCO-LABEL: caller_64_64_copy_ccc:
     50 ; CHECK-SCO: bl callee_64_64_copy_fastcc
     51 }
     52 
     53 define void @caller_64_64_reorder_copy([8 x i64] %a, [8 x i64] %b) #1 {
     54   tail call void @callee_64_64_copy([8 x i64] %b, [8 x i64] %a)
     55   ret void
     56 
     57 ; CHECK-SCO-LABEL: caller_64_64_reorder_copy:
     58 ; CHECK-SCO: bl callee_64_64_copy
     59 }
     60 
     61 define void @caller_64_64_undef_copy([8 x i64] %a, [8 x i64] %b) #1 {
     62   tail call void @callee_64_64_copy([8 x i64] %a, [8 x i64] undef)
     63   ret void
     64 
     65 ; CHECK-SCO-LABEL: caller_64_64_undef_copy:
     66 ; CHECK-SCO: b callee_64_64_copy
     67 }
     68 
     69 define void @arg8_callee(
     70   float %a, i32 signext %b, float %c, i32* %d,
     71   i8 zeroext %e, float %f, i32* %g, i32 signext %h)
     72 {
     73   ret void
     74 }
     75 
     76 define void @arg8_caller(float %a, i32 signext %b, i8 zeroext %c, i32* %d) {
     77 entry:
     78   tail call void @arg8_callee(float undef, i32 signext undef, float undef,
     79                               i32* %d, i8 zeroext undef, float undef,
     80                               i32* undef, i32 signext undef)
     81   ret void
     82 
     83 ; CHECK-SCO-LABEL: arg8_caller:
     84 ; CHECK-SCO: b arg8_callee
     85 }
     86 
     87 ; Struct return test
     88 
     89 ; Function Attrs: noinline nounwind
     90 define void @callee_sret_56(%S_56* noalias sret %agg.result) #0 { ret void }
     91 define void @callee_sret_32(%S_32* noalias sret %agg.result) #0 { ret void }
     92 
     93 ; Function Attrs: nounwind
     94 define void @caller_do_something_sret_32(%S_32* noalias sret %agg.result) #1 {
     95   %1 = alloca %S_56, align 4
     96   %2 = bitcast %S_56* %1 to i8*
     97   call void @callee_sret_56(%S_56* nonnull sret %1)
     98   tail call void @callee_sret_32(%S_32* sret %agg.result)
     99   ret void
    100 
    101 ; CHECK-SCO-LABEL: caller_do_something_sret_32:
    102 ; CHECK-SCO: stdu 1
    103 ; CHECK-SCO: bl callee_sret_56
    104 ; CHECK-SCO: addi 1
    105 ; CHECK-SCO: TC_RETURNd8 callee_sret_32
    106 }
    107 
    108 define void @caller_local_sret_32(%S_32* %a) #1 {
    109   %tmp = alloca %S_32, align 4
    110   tail call void @callee_sret_32(%S_32* nonnull sret %tmp)
    111   ret void
    112 
    113 ; CHECK-SCO-LABEL: caller_local_sret_32:
    114 ; CHECK-SCO: bl callee_sret_32
    115 }
    116 
    117 attributes #0 = { noinline nounwind  }
    118 attributes #1 = { nounwind }
    119 
    120 ; vector <4 x i1> test
    121 
    122 define void @callee_v4i1(i8 %a, <4 x i1> %b, <4 x i1> %c) { ret void }
    123 define void @caller_v4i1_reorder(i8 %a, <4 x i1> %b, <4 x i1> %c) {
    124   tail call void @callee_v4i1(i8 %a, <4 x i1> %c, <4 x i1> %b)
    125   ret void
    126 
    127 ; <4 x i1> is 32 bytes aligned, if subtarget doesn't support qpx, then we can't
    128 ; place b, c to qpx register, so we can't do sco on caller_v4i1_reorder
    129 
    130 ; CHECK-SCO-LABEL: caller_v4i1_reorder:
    131 ; CHECK-SCO: bl callee_v4i1
    132 
    133 ; CHECK-SCO-HASQPX-LABEL: caller_v4i1_reorder:
    134 ; CHECK-SCO-HASQPX: b callee_v4i1
    135 }
    136 
    137 define void @f128_callee(i32* %ptr, ppc_fp128 %a, ppc_fp128 %b) { ret void }
    138 define void @f128_caller(i32* %ptr, ppc_fp128 %a, ppc_fp128 %b) {
    139   tail call void @f128_callee(i32* %ptr, ppc_fp128 %a, ppc_fp128 %b)
    140   ret void
    141 
    142 ; CHECK-SCO-LABEL: f128_caller:
    143 ; CHECK-SCO: b f128_callee
    144 }
    145 
    146 ; weak linkage test
    147 %class.T = type { [2 x i8] }
    148 
    149 define weak_odr hidden void @wo_hcallee(%class.T* %this, i8* %c) { ret void }
    150 define void @wo_hcaller(%class.T* %this, i8* %c) {
    151   tail call void @wo_hcallee(%class.T* %this, i8* %c)
    152   ret void
    153 
    154 ; CHECK-SCO-LABEL: wo_hcaller:
    155 ; CHECK-SCO: b wo_hcallee
    156 
    157 ; SCM-LABEL: wo_hcaller:
    158 ; SCM:       bl wo_hcallee
    159 }
    160 
    161 define weak_odr protected void @wo_pcallee(%class.T* %this, i8* %c) { ret void }
    162 define void @wo_pcaller(%class.T* %this, i8* %c) {
    163   tail call void @wo_pcallee(%class.T* %this, i8* %c)
    164   ret void
    165 
    166 ; CHECK-SCO-LABEL: wo_pcaller:
    167 ; CHECK-SCO: b wo_pcallee
    168 
    169 ; SCM-LABEL: wo_pcaller:
    170 ; SCM:       bl wo_pcallee
    171 }
    172 
    173 define weak_odr void @wo_callee(%class.T* %this, i8* %c) { ret void }
    174 define void @wo_caller(%class.T* %this, i8* %c) {
    175   tail call void @wo_callee(%class.T* %this, i8* %c)
    176   ret void
    177 
    178 ; CHECK-SCO-LABEL: wo_caller:
    179 ; CHECK-SCO: b wo_callee
    180 
    181 ; SCM-LABEL: wo_caller:
    182 ; SCM:       bl wo_callee
    183 }
    184 
    185 define weak protected void @w_pcallee(i8* %ptr) { ret void }
    186 define void @w_pcaller(i8* %ptr) {
    187   tail call void @w_pcallee(i8* %ptr)
    188   ret void
    189 
    190 ; CHECK-SCO-LABEL: w_pcaller:
    191 ; CHECK-SCO: b w_pcallee
    192 
    193 ; SCM-LABEL: w_pcaller:
    194 ; SCM:       bl w_pcallee
    195 }
    196 
    197 define weak hidden void @w_hcallee(i8* %ptr) { ret void }
    198 define void @w_hcaller(i8* %ptr) {
    199   tail call void @w_hcallee(i8* %ptr)
    200   ret void
    201 
    202 ; CHECK-SCO-LABEL: w_hcaller:
    203 ; CHECK-SCO: b w_hcallee
    204 
    205 ; SCM-LABEL: w_hcaller:
    206 ; SCM:       bl w_hcallee
    207 }
    208 
    209 define weak void @w_callee(i8* %ptr) { ret void }
    210 define void @w_caller(i8* %ptr) {
    211   tail call void @w_callee(i8* %ptr)
    212   ret void
    213 
    214 ; CHECK-SCO-LABEL: w_caller:
    215 ; CHECK-SCO: b w_callee
    216 
    217 ; SCM-LABEL: w_caller:
    218 ; SCM:       bl w_callee
    219 }
    220 
    221 %struct.byvalTest = type { [8 x i8] }
    222 @byval = common global %struct.byvalTest zeroinitializer
    223 
    224 define void @byval_callee(%struct.byvalTest* byval %ptr) { ret void }
    225 define void @byval_caller() {
    226   tail call void @byval_callee(%struct.byvalTest* byval @byval)
    227   ret void
    228 
    229 ; CHECK-SCO-LABEL: bl byval_callee
    230 ; CHECK-SCO: bl byval_callee
    231 }
    232