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