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