• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -march=mipsel -relocation-model=pic -enable-mips-tail-calls \
2; RUN:     -verify-machineinstrs < %s | FileCheck %s -check-prefix=PIC32
3; RUN: llc -march=mipsel -relocation-model=static -enable-mips-tail-calls \
4; RUN:     -verify-machineinstrs < %s | FileCheck %s -check-prefix=STATIC32
5; RUN: llc -march=mips64el -mcpu=mips64r2 -enable-mips-tail-calls \
6; RUN:     -verify-machineinstrs < %s | FileCheck %s -check-prefix=N64
7; RUN: llc -march=mipsel -mattr=mips16 -relocation-model=pic \
8; RUN:     -enable-mips-tail-calls -verify-machineinstrs < %s | \
9; RUN:     FileCheck %s -check-prefix=PIC16
10
11@g0 = common global i32 0, align 4
12@g1 = common global i32 0, align 4
13@g2 = common global i32 0, align 4
14@g3 = common global i32 0, align 4
15@g4 = common global i32 0, align 4
16@g5 = common global i32 0, align 4
17@g6 = common global i32 0, align 4
18@g7 = common global i32 0, align 4
19@g8 = common global i32 0, align 4
20@g9 = common global i32 0, align 4
21
22define i32 @caller1(i32 %a0) nounwind {
23entry:
24; PIC32-NOT: jalr
25; STATIC32-NOT: jal
26; N64-NOT: jalr
27; PIC16: jalrc
28
29  %call = tail call i32 @callee1(i32 1, i32 1, i32 1, i32 %a0) nounwind
30  ret i32 %call
31}
32
33declare i32 @callee1(i32, i32, i32, i32)
34
35define i32 @caller2(i32 %a0, i32 %a1, i32 %a2, i32 %a3) nounwind {
36entry:
37; PIC32: jalr
38; STATIC32: jal
39; N64-NOT: jalr
40; PIC16: jalrc
41
42  %call = tail call i32 @callee2(i32 1, i32 %a0, i32 %a1, i32 %a2, i32 %a3) nounwind
43  ret i32 %call
44}
45
46declare i32 @callee2(i32, i32, i32, i32, i32)
47
48define i32 @caller3(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4) nounwind {
49entry:
50; PIC32: jalr
51; STATIC32: jal
52; N64-NOT: jalr
53; PIC16: jalrc
54
55  %call = tail call i32 @callee3(i32 1, i32 1, i32 1, i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4) nounwind
56  ret i32 %call
57}
58
59declare i32 @callee3(i32, i32, i32, i32, i32, i32, i32, i32)
60
61define i32 @caller4(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7) nounwind {
62entry:
63; PIC32: jalr
64; STATIC32: jal
65; N64: jalr
66; PIC16: jalrc
67
68  %call = tail call i32 @callee4(i32 1, i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7) nounwind
69  ret i32 %call
70}
71
72declare i32 @callee4(i32, i32, i32, i32, i32, i32, i32, i32, i32)
73
74define i32 @caller5() nounwind readonly {
75entry:
76; PIC32: .ent caller5
77; PIC32-NOT: jalr
78; PIC32: .end caller5
79; STATIC32: .ent caller5
80; STATIC32-NOT: jal
81; STATIC32: .end caller5
82; N64: .ent caller5
83; N64-NOT: jalr
84; N64: .end caller5
85; PIC16: .ent caller5
86; PIC16: jalrc
87; PIC16: .end caller5
88
89  %0 = load i32, i32* @g0, align 4
90  %1 = load i32, i32* @g1, align 4
91  %2 = load i32, i32* @g2, align 4
92  %3 = load i32, i32* @g3, align 4
93  %4 = load i32, i32* @g4, align 4
94  %5 = load i32, i32* @g5, align 4
95  %6 = load i32, i32* @g6, align 4
96  %7 = load i32, i32* @g7, align 4
97  %8 = load i32, i32* @g8, align 4
98  %9 = load i32, i32* @g9, align 4
99  %call = tail call fastcc i32 @callee5(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9)
100  ret i32 %call
101}
102
103define internal fastcc i32 @callee5(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9) nounwind readnone noinline {
104entry:
105  %add = add nsw i32 %a1, %a0
106  %add1 = add nsw i32 %add, %a2
107  %add2 = add nsw i32 %add1, %a3
108  %add3 = add nsw i32 %add2, %a4
109  %add4 = add nsw i32 %add3, %a5
110  %add5 = add nsw i32 %add4, %a6
111  %add6 = add nsw i32 %add5, %a7
112  %add7 = add nsw i32 %add6, %a8
113  %add8 = add nsw i32 %add7, %a9
114  ret i32 %add8
115}
116
117declare i32 @callee8(i32, ...)
118
119define i32 @caller8_0() nounwind {
120entry:
121  %call = tail call fastcc i32 @caller8_1()
122  ret i32 %call
123}
124
125define internal fastcc i32 @caller8_1() nounwind noinline {
126entry:
127; PIC32: .ent caller8_1
128; PIC32: jalr
129; PIC32: .end caller8_1
130; STATIC32: .ent caller8_1
131; STATIC32: jal
132; STATIC32: .end caller8_1
133; N64: .ent caller8_1
134; N64-NOT: jalr
135; N64: .end caller8_1
136; PIC16: .ent caller8_1
137; PIC16: jalrc
138; PIC16: .end caller8_1
139
140  %call = tail call i32 (i32, ...) @callee8(i32 2, i32 1) nounwind
141  ret i32 %call
142}
143
144%struct.S = type { [2 x i32] }
145
146@gs1 = external global %struct.S
147
148declare i32 @callee9(%struct.S* byval)
149
150define i32 @caller9_0() nounwind {
151entry:
152  %call = tail call fastcc i32 @caller9_1()
153  ret i32 %call
154}
155
156define internal fastcc i32 @caller9_1() nounwind noinline {
157entry:
158; PIC32: .ent caller9_1
159; PIC32: jalr
160; PIC32: .end caller9_1
161; STATIC32: .ent caller9_1
162; STATIC32: jal
163; STATIC32: .end caller9_1
164; N64: .ent caller9_1
165; N64: jalr
166; N64: .end caller9_1
167; PIC16: .ent caller9_1
168; PIC16: jalrc
169; PIC16: .end caller9_1
170
171  %call = tail call i32 @callee9(%struct.S* byval @gs1) nounwind
172  ret i32 %call
173}
174
175declare i32 @callee10(i32, i32, i32, i32, i32, i32, i32, i32, i32)
176
177define i32 @caller10(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8) nounwind {
178entry:
179; PIC32: .ent caller10
180; PIC32-NOT: jalr
181; STATIC32: .ent caller10
182; STATIC32-NOT: jal
183; N64: .ent caller10
184; N64-NOT: jalr
185; PIC16: .ent caller10
186; PIC16: jalrc
187
188  %call = tail call i32 @callee10(i32 %a8, i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7) nounwind
189  ret i32 %call
190}
191
192declare i32 @callee11(%struct.S* byval)
193
194define i32 @caller11() nounwind noinline {
195entry:
196; PIC32: .ent caller11
197; PIC32: jalr
198; STATIC32: .ent caller11
199; STATIC32: jal
200; N64: .ent caller11
201; N64: jalr
202; PIC16: .ent caller11
203; PIC16: jalrc
204
205  %call = tail call i32 @callee11(%struct.S* byval @gs1) nounwind
206  ret i32 %call
207}
208
209declare i32 @callee12()
210
211declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
212
213define i32 @caller12(%struct.S* nocapture byval %a0) nounwind {
214entry:
215; PIC32: .ent caller12
216; PIC32: jalr
217; STATIC32: .ent caller12
218; STATIC32: jal
219; N64: .ent caller12
220; N64: jalr
221; PIC16: .ent caller12
222; PIC16: jalrc
223
224  %0 = bitcast %struct.S* %a0 to i8*
225  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct.S* @gs1 to i8*), i8* %0, i32 8, i32 4, i1 false)
226  %call = tail call i32 @callee12() nounwind
227  ret i32 %call
228}
229
230declare i32 @callee13(i32, ...)
231
232define i32 @caller13() nounwind {
233entry:
234; PIC32: .ent caller13
235; PIC32-NOT: jalr
236; STATIC32: .ent caller13
237; STATIC32-NOT: jal
238; N64: .ent caller13
239; N64-NOT: jalr
240; PIC16: .ent caller13
241; PIC16: jalrc
242
243  %call = tail call i32 (i32, ...) @callee13(i32 1, i32 2) nounwind
244  ret i32 %call
245}
246
247; Check that there is a chain edge between the load and store nodes.
248;
249; PIC32-LABEL: caller14:
250; PIC32: lw ${{[0-9]+}}, 16($sp)
251; PIC32: sw $4, 16($sp)
252
253define void @caller14(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
254entry:
255  tail call void @callee14(i32 %e, i32 %b, i32 %c, i32 %d, i32 %a)
256  ret void
257}
258
259declare void @callee14(i32, i32, i32, i32, i32)
260