blob: 9b46d3b0960d294a2037c82abc318872e2a075bd [file] [log] [blame]
Daniel Sanders20c82ee42014-07-04 15:16:14 +00001; Test the 'call' instruction and the tailcall variant.
2
3; FIXME: We should remove the need for -enable-mips-tail-calls
Simon Dardisd9d41f52016-04-05 12:50:29 +00004; RUN: llc -march=mips -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
5; RUN: llc -march=mips -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
6; RUN: llc -march=mips -mcpu=mips32r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
7; RUN: llc -march=mips -mcpu=mips32r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
8; RUN: llc -march=mips -mcpu=mips32r6 -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
9; RUN: llc -march=mips -mcpu=mips32r6 -mattr=+fp64,+nooddspreg -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
10; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
11; RUN: llc -march=mips64 -mcpu=mips64 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
12; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
13; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
14; RUN: llc -march=mips64 -mcpu=mips64r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
15; RUN: llc -march=mips64 -mcpu=mips64r6 -disable-mips-delay-filler -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=R6C
Daniel Sanders20c82ee42014-07-04 15:16:14 +000016
17declare void @extern_void_void()
18declare i32 @extern_i32_void()
19declare float @extern_float_void()
20
21define i32 @call_void_void() {
22; ALL-LABEL: call_void_void:
23
24; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
25
26; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
27
Simon Dardisd9d41f52016-04-05 12:50:29 +000028; NOT-R6C: jalr $[[TGT]]
29; R6C: jialc $[[TGT]], 0
Daniel Sanders20c82ee42014-07-04 15:16:14 +000030
31 call void @extern_void_void()
32 ret i32 0
33}
34
35define i32 @call_i32_void() {
36; ALL-LABEL: call_i32_void:
37
38; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
39
40; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
41
Simon Dardisd9d41f52016-04-05 12:50:29 +000042; NOT-R6C: jalr $[[TGT]]
43; R6C: jialc $[[TGT]], 0
Daniel Sanders20c82ee42014-07-04 15:16:14 +000044
45 %1 = call i32 @extern_i32_void()
46 %2 = add i32 %1, 1
47 ret i32 %2
48}
49
50define float @call_float_void() {
51; ALL-LABEL: call_float_void:
52
53; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
54; look into it at some point.
55; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
56; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
57
58; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
59
Simon Dardisd9d41f52016-04-05 12:50:29 +000060; NOT-R6C: jalr $[[TGT]]
61; R6C: jialc $[[TGT]], 0
Daniel Sanders20c82ee42014-07-04 15:16:14 +000062
Daniel Sanders20c82ee42014-07-04 15:16:14 +000063
64 %1 = call float @extern_float_void()
65 %2 = fadd float %1, 1.0
66 ret float %2
67}
68
69define void @musttail_call_void_void() {
70; ALL-LABEL: musttail_call_void_void:
71
72; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
73
74; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
75
Simon Dardisd9d41f52016-04-05 12:50:29 +000076; ALL: jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +000077
78 musttail call void @extern_void_void()
79 ret void
80}
81
82define i32 @musttail_call_i32_void() {
83; ALL-LABEL: musttail_call_i32_void:
84
85; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
86
87; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
88
Simon Dardisd9d41f52016-04-05 12:50:29 +000089; ALL: jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +000090
91 %1 = musttail call i32 @extern_i32_void()
92 ret i32 %1
93}
94
95define float @musttail_call_float_void() {
96; ALL-LABEL: musttail_call_float_void:
97
98; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
99
100; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
101
Simon Dardisd9d41f52016-04-05 12:50:29 +0000102; ALL: jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +0000103
104 %1 = musttail call float @extern_float_void()
105 ret float %1
106}
107
108define i32 @indirect_call_void_void(void ()* %addr) {
109; ALL-LABEL: indirect_call_void_void:
110
111; ALL: move $25, $4
Simon Dardisd9d41f52016-04-05 12:50:29 +0000112; NOT-R6C: jalr $25
113; R6C: jialc $25, 0
114
Daniel Sanders20c82ee42014-07-04 15:16:14 +0000115
116 call void %addr()
117 ret i32 0
118}
119
120define i32 @indirect_call_i32_void(i32 ()* %addr) {
121; ALL-LABEL: indirect_call_i32_void:
122
123; ALL: move $25, $4
Simon Dardisd9d41f52016-04-05 12:50:29 +0000124; NOT-R6C: jalr $25
125; R6C: jialc $25, 0
126
Daniel Sanders20c82ee42014-07-04 15:16:14 +0000127
128 %1 = call i32 %addr()
129 %2 = add i32 %1, 1
130 ret i32 %2
131}
132
133define float @indirect_call_float_void(float ()* %addr) {
134; ALL-LABEL: indirect_call_float_void:
135
136; ALL: move $25, $4
Simon Dardisd9d41f52016-04-05 12:50:29 +0000137; NOT-R6C: jalr $25
138; R6C: jialc $25, 0
139
Daniel Sanders20c82ee42014-07-04 15:16:14 +0000140
141 %1 = call float %addr()
142 %2 = fadd float %1, 1.0
143 ret float %2
144}
145
146; We can't use 'musttail' here because the verifier is too conservative and
147; prohibits any prototype difference.
148define void @tail_indirect_call_void_void(void ()* %addr) {
149; ALL-LABEL: tail_indirect_call_void_void:
150
151; ALL: move $25, $4
152; ALL: jr $25
153
154 tail call void %addr()
155 ret void
156}
157
158define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
159; ALL-LABEL: tail_indirect_call_i32_void:
160
161; ALL: move $25, $4
162; ALL: jr $25
163
164 %1 = tail call i32 %addr()
165 ret i32 %1
166}
167
168define float @tail_indirect_call_float_void(float ()* %addr) {
169; ALL-LABEL: tail_indirect_call_float_void:
170
171; ALL: move $25, $4
172; ALL: jr $25
173
174 %1 = tail call float %addr()
175 ret float %1
176}
Daniel Sanders2fb85642015-10-12 13:55:44 +0000177
178; Check that passing undef as a double value doesn't cause machine code errors
179; for FP64.
180declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2
181
182define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 {
183; ALL-LABEL: thunk_undef_double:
Dan Gohman7aa4aba2015-11-17 16:01:28 +0000184; O32: # implicit-def: %A2
185; O32: # implicit-def: %A3
Simon Dardisd9d41f52016-04-05 12:50:29 +0000186; ALL: jr $25
187
Daniel Sanders2fb85642015-10-12 13:55:44 +0000188 tail call void @undef_double(i32 undef, double undef) #8
189 ret void
190}
Daniel Sanders4d323002016-01-11 15:57:46 +0000191
192; Check that immediate addresses do not use jal.
193define i32 @jal_only_allows_symbols() {
194; ALL-LABEL: jal_only_allows_symbols:
195
196; ALL-NOT: {{jal }}
197; ALL: addiu $[[TGT:[0-9]+]], $zero, 1234
198; ALL-NOT: {{jal }}
Simon Dardisd9d41f52016-04-05 12:50:29 +0000199; NOT-R6C: jalr $[[TGT]]
200; R6C: jialc $[[TGT]], 0
Daniel Sanders4d323002016-01-11 15:57:46 +0000201; ALL-NOT: {{jal }}
202
203 call void () inttoptr (i32 1234 to void ()*)()
204 ret i32 0
205}
206