xref: /llvm-project/llvm/test/CodeGen/PowerPC/ppc64-sibcall.ll (revision 5403c59c608c08c8ecd4303763f08eb046eb5e4d)
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