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 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 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 14define dso_local void @callee_56_copy([7 x i64] %a, ptr %b) #0 { ret void } 15define dso_local void @callee_64_copy([8 x i64] %a, ptr %b) #0 { ret void } 16 17; Function Attrs: nounwind 18define dso_local void @caller_56_reorder_copy(ptr %b, [7 x i64] %a) #1 { 19 tail call void @callee_56_copy([7 x i64] %a, ptr %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 27define dso_local void @caller_64_reorder_copy(ptr %b, [8 x i64] %a) #1 { 28 tail call void @callee_64_copy([8 x i64] %a, ptr %b) 29 ret void 30 31; CHECK-SCO-LABEL: caller_64_reorder_copy: 32; CHECK-SCO: bl callee_64_copy 33} 34 35define dso_local void @callee_64_64_copy([8 x i64] %a, [8 x i64] %b) #0 { ret void } 36define dso_local 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 44define internal fastcc void @callee_64_64_copy_fastcc([8 x i64] %a, [8 x i64] %b) #0 { ret void } 45define dso_local 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 53define dso_local 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 61define dso_local 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 69define dso_local void @arg8_callee( 70 float %a, i32 signext %b, float %c, ptr %d, 71 i8 zeroext %e, float %f, ptr %g, i32 signext %h) 72{ 73 ret void 74} 75 76define dso_local void @arg8_caller(float %a, i32 signext %b, i8 zeroext %c, ptr %d) { 77entry: 78 tail call void @arg8_callee(float undef, i32 signext undef, float undef, 79 ptr %d, i8 zeroext undef, float undef, 80 ptr 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 90define dso_local void @callee_sret_56(ptr noalias sret(%S_56) %agg.result) #0 { ret void } 91define dso_local void @callee_sret_32(ptr noalias sret(%S_32) %agg.result) #0 { ret void } 92 93; Function Attrs: nounwind 94define dso_local void @caller_do_something_sret_32(ptr noalias sret(%S_32) %agg.result) #1 { 95 %1 = alloca %S_56, align 4 96 call void @callee_sret_56(ptr nonnull sret(%S_56) %1) 97 tail call void @callee_sret_32(ptr sret(%S_32) %agg.result) 98 ret void 99 100; CHECK-SCO-LABEL: caller_do_something_sret_32: 101; CHECK-SCO: stdu 1 102; CHECK-SCO: bl callee_sret_56 103; CHECK-SCO: addi 1 104; CHECK-SCO: TC_RETURNd8 callee_sret_32 105} 106 107define dso_local void @caller_local_sret_32(ptr %a) #1 { 108 %tmp = alloca %S_32, align 4 109 tail call void @callee_sret_32(ptr nonnull sret(%S_32) %tmp) 110 ret void 111 112; CHECK-SCO-LABEL: caller_local_sret_32: 113; CHECK-SCO: bl callee_sret_32 114} 115 116attributes #0 = { noinline nounwind } 117attributes #1 = { nounwind } 118 119define dso_local void @f128_callee(ptr %ptr, ppc_fp128 %a, ppc_fp128 %b) { ret void } 120define dso_local void @f128_caller(ptr %ptr, ppc_fp128 %a, ppc_fp128 %b) { 121 tail call void @f128_callee(ptr %ptr, ppc_fp128 %a, ppc_fp128 %b) 122 ret void 123 124; CHECK-SCO-LABEL: f128_caller: 125; CHECK-SCO: b f128_callee 126} 127 128; weak linkage test 129%class.T = type { [2 x i8] } 130 131define weak_odr hidden void @wo_hcallee(ptr %this, ptr %c) { ret void } 132define dso_local void @wo_hcaller(ptr %this, ptr %c) { 133 tail call void @wo_hcallee(ptr %this, ptr %c) 134 ret void 135 136; CHECK-SCO-LABEL: wo_hcaller: 137; CHECK-SCO: bl wo_hcallee 138 139; SCM-LABEL: wo_hcaller: 140; SCM: bl wo_hcallee 141} 142 143define weak_odr protected void @wo_pcallee(ptr %this, ptr %c) { ret void } 144define dso_local void @wo_pcaller(ptr %this, ptr %c) { 145 tail call void @wo_pcallee(ptr %this, ptr %c) 146 ret void 147 148; CHECK-SCO-LABEL: wo_pcaller: 149; CHECK-SCO: bl wo_pcallee 150 151; SCM-LABEL: wo_pcaller: 152; SCM: bl wo_pcallee 153} 154 155define weak_odr void @wo_callee(ptr %this, ptr %c) { ret void } 156define dso_local void @wo_caller(ptr %this, ptr %c) { 157 tail call void @wo_callee(ptr %this, ptr %c) 158 ret void 159 160; CHECK-SCO-LABEL: wo_caller: 161; CHECK-SCO: bl wo_callee 162 163; SCM-LABEL: wo_caller: 164; SCM: bl wo_callee 165} 166 167define weak protected void @w_pcallee(ptr %ptr) { ret void } 168define dso_local void @w_pcaller(ptr %ptr) { 169 tail call void @w_pcallee(ptr %ptr) 170 ret void 171 172; CHECK-SCO-LABEL: w_pcaller: 173; CHECK-SCO: bl w_pcallee 174 175; SCM-LABEL: w_pcaller: 176; SCM: bl w_pcallee 177} 178 179define weak hidden void @w_hcallee(ptr %ptr) { ret void } 180define dso_local void @w_hcaller(ptr %ptr) { 181 tail call void @w_hcallee(ptr %ptr) 182 ret void 183 184; CHECK-SCO-LABEL: w_hcaller: 185; CHECK-SCO: bl w_hcallee 186 187; SCM-LABEL: w_hcaller: 188; SCM: bl w_hcallee 189} 190 191define weak void @w_callee(ptr %ptr) { ret void } 192define dso_local void @w_caller(ptr %ptr) { 193 tail call void @w_callee(ptr %ptr) 194 ret void 195 196; CHECK-SCO-LABEL: w_caller: 197; CHECK-SCO: bl w_callee 198 199; SCM-LABEL: w_caller: 200; SCM: bl w_callee 201} 202 203%struct.byvalTest = type { [8 x i8] } 204@byval = common global %struct.byvalTest zeroinitializer 205 206define dso_local void @byval_callee(ptr byval(%struct.byvalTest) %ptr) { ret void } 207define dso_local void @byval_caller() { 208 tail call void @byval_callee(ptr byval(%struct.byvalTest) @byval) 209 ret void 210 211; CHECK-SCO-LABEL: bl byval_callee 212; CHECK-SCO: bl byval_callee 213} 214