blob: 22a44da0b069690b98d563e7e58a6e8277211515 [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 Sanders2fb85642015-10-12 13:55:44 +00009; RUN: llc -march=mips -mcpu=mips32r6 -mattr=+fp64,+nooddspreg -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
Daniel Sanders20c82ee42014-07-04 15:16:14 +000010; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
11; 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 +000012; 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 +000013; RUN: llc -march=mips64 -mcpu=mips64r3 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
14; 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 +000015; 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 +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
28; ALL: jalr $[[TGT]]
29
30 call void @extern_void_void()
31 ret i32 0
32}
33
34define i32 @call_i32_void() {
35; ALL-LABEL: call_i32_void:
36
37; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
38
39; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
40
41; ALL: jalr $[[TGT]]
42
43 %1 = call i32 @extern_i32_void()
44 %2 = add i32 %1, 1
45 ret i32 %2
46}
47
48define float @call_float_void() {
49; ALL-LABEL: call_float_void:
50
51; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
52; look into it at some point.
53; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
54; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
55
56; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
57
58; ALL: jalr $[[TGT]]
59
60; O32: move $gp, $[[GP]]
61
62 %1 = call float @extern_float_void()
63 %2 = fadd float %1, 1.0
64 ret float %2
65}
66
67define void @musttail_call_void_void() {
68; ALL-LABEL: musttail_call_void_void:
69
70; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
71
72; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
73
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000074; NOT-R6: jr $[[TGT]]
75; R6: r6.jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +000076
77 musttail call void @extern_void_void()
78 ret void
79}
80
81define i32 @musttail_call_i32_void() {
82; ALL-LABEL: musttail_call_i32_void:
83
84; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
85
86; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
87
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +000088; NOT-R6: jr $[[TGT]]
89; R6: r6.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
Daniel Sandersf5a5fbd2014-07-09 10:21:59 +0000102; NOT-R6: jr $[[TGT]]
103; R6: r6.jr $[[TGT]]
Daniel Sanders20c82ee42014-07-04 15:16:14 +0000104
105 %1 = musttail call float @extern_float_void()
106 ret float %1
107}
108
109define i32 @indirect_call_void_void(void ()* %addr) {
110; ALL-LABEL: indirect_call_void_void:
111
112; ALL: move $25, $4
113; ALL: jalr $25
114
115 call void %addr()
116 ret i32 0
117}
118
119define i32 @indirect_call_i32_void(i32 ()* %addr) {
120; ALL-LABEL: indirect_call_i32_void:
121
122; ALL: move $25, $4
123; ALL: jalr $25
124
125 %1 = call i32 %addr()
126 %2 = add i32 %1, 1
127 ret i32 %2
128}
129
130define float @indirect_call_float_void(float ()* %addr) {
131; ALL-LABEL: indirect_call_float_void:
132
133; ALL: move $25, $4
134; ALL: jalr $25
135
136 %1 = call float %addr()
137 %2 = fadd float %1, 1.0
138 ret float %2
139}
140
141; We can't use 'musttail' here because the verifier is too conservative and
142; prohibits any prototype difference.
143define void @tail_indirect_call_void_void(void ()* %addr) {
144; ALL-LABEL: tail_indirect_call_void_void:
145
146; ALL: move $25, $4
147; ALL: jr $25
148
149 tail call void %addr()
150 ret void
151}
152
153define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
154; ALL-LABEL: tail_indirect_call_i32_void:
155
156; ALL: move $25, $4
157; ALL: jr $25
158
159 %1 = tail call i32 %addr()
160 ret i32 %1
161}
162
163define float @tail_indirect_call_float_void(float ()* %addr) {
164; ALL-LABEL: tail_indirect_call_float_void:
165
166; ALL: move $25, $4
167; ALL: jr $25
168
169 %1 = tail call float %addr()
170 ret float %1
171}
Daniel Sanders2fb85642015-10-12 13:55:44 +0000172
173; Check that passing undef as a double value doesn't cause machine code errors
174; for FP64.
175declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2
176
177define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 {
178; ALL-LABEL: thunk_undef_double:
Dan Gohman7aa4aba2015-11-17 16:01:28 +0000179; O32: # implicit-def: %A2
180; O32: # implicit-def: %A3
Daniel Sanders2fb85642015-10-12 13:55:44 +0000181; ALL: jr $25
182 tail call void @undef_double(i32 undef, double undef) #8
183 ret void
184}