blob: 112ab8ee8c7fea9bfad276f038638fa3f78cac4e [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
4; RUN: llc -march=mips -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
5; RUN: llc -march=mips -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
Daniel Sanders17793142015-02-18 16:24:50 +00006; RUN: llc -march=mips -mcpu=mips32r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
7; RUN: llc -march=mips -mcpu=mips32r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +00008; RUN: llc -march=mips -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
Daniel Sanders20c82ee42014-07-04 15:16:14 +00009; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
10; RUN: llc -march=mips64 -mcpu=mips64 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000011; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
Daniel Sanders17793142015-02-18 16:24:50 +000012; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
13; RUN: llc -march=mips64 -mcpu=mips64r5 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000014; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
Daniel Sanders20c82ee42014-07-04 15:16:14 +000015
16declare void @extern_void_void()
17declare i32 @extern_i32_void()
18declare float @extern_float_void()
19
20define i32 @call_void_void() {
21; ALL-LABEL: call_void_void:
22
23; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
24
25; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
26
27; ALL: jalr $[[TGT]]
28
29 call void @extern_void_void()
30 ret i32 0
31}
32
33define i32 @call_i32_void() {
34; ALL-LABEL: call_i32_void:
35
36; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
37
38; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
39
40; ALL: jalr $[[TGT]]
41
42 %1 = call i32 @extern_i32_void()
43 %2 = add i32 %1, 1
44 ret i32 %2
45}
46
47define float @call_float_void() {
48; ALL-LABEL: call_float_void:
49
50; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
51; look into it at some point.
52; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
53; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
54
55; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
56
57; ALL: jalr $[[TGT]]
58
59; O32: move $gp, $[[GP]]
60
61 %1 = call float @extern_float_void()
62 %2 = fadd float %1, 1.0
63 ret float %2
64}
65
66define void @musttail_call_void_void() {
67; ALL-LABEL: musttail_call_void_void:
68
69; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
70
71; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
72
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000073; NOT-R6: jr $[[TGT]]
74; R6: r6.jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +000075
76 musttail call void @extern_void_void()
77 ret void
78}
79
80define i32 @musttail_call_i32_void() {
81; ALL-LABEL: musttail_call_i32_void:
82
83; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
84
85; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
86
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000087; NOT-R6: jr $[[TGT]]
88; R6: r6.jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +000089
90 %1 = musttail call i32 @extern_i32_void()
91 ret i32 %1
92}
93
94define float @musttail_call_float_void() {
95; ALL-LABEL: musttail_call_float_void:
96
97; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
98
99; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
100
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +0000101; NOT-R6: jr $[[TGT]]
102; R6: r6.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
112; ALL: jalr $25
113
114 call void %addr()
115 ret i32 0
116}
117
118define i32 @indirect_call_i32_void(i32 ()* %addr) {
119; ALL-LABEL: indirect_call_i32_void:
120
121; ALL: move $25, $4
122; ALL: jalr $25
123
124 %1 = call i32 %addr()
125 %2 = add i32 %1, 1
126 ret i32 %2
127}
128
129define float @indirect_call_float_void(float ()* %addr) {
130; ALL-LABEL: indirect_call_float_void:
131
132; ALL: move $25, $4
133; ALL: jalr $25
134
135 %1 = call float %addr()
136 %2 = fadd float %1, 1.0
137 ret float %2
138}
139
140; We can't use 'musttail' here because the verifier is too conservative and
141; prohibits any prototype difference.
142define void @tail_indirect_call_void_void(void ()* %addr) {
143; ALL-LABEL: tail_indirect_call_void_void:
144
145; ALL: move $25, $4
146; ALL: jr $25
147
148 tail call void %addr()
149 ret void
150}
151
152define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
153; ALL-LABEL: tail_indirect_call_i32_void:
154
155; ALL: move $25, $4
156; ALL: jr $25
157
158 %1 = tail call i32 %addr()
159 ret i32 %1
160}
161
162define float @tail_indirect_call_float_void(float ()* %addr) {
163; ALL-LABEL: tail_indirect_call_float_void:
164
165; ALL: move $25, $4
166; ALL: jr $25
167
168 %1 = tail call float %addr()
169 ret float %1
170}