[mips] Handle undef when extracting subregs from FP64 registers.
[oota-llvm.git] / test / CodeGen / Mips / llvm-ir / call.ll
1 ; 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
6 ; 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
8 ; RUN: llc -march=mips   -mcpu=mips32r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
9 ; RUN: llc -march=mips   -mcpu=mips32r6 -mattr=+fp64,+nooddspreg -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
10 ; 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
12 ; RUN: llc -march=mips64 -mcpu=mips64r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
13 ; 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
15 ; RUN: llc -march=mips64 -mcpu=mips64r6 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
16
17 declare void @extern_void_void()
18 declare i32 @extern_i32_void()
19 declare float @extern_float_void()
20
21 define 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
34 define 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
48 define 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
67 define 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
74 ; NOT-R6:        jr $[[TGT]]
75 ; R6:            r6.jr $[[TGT]]
76
77   musttail call void @extern_void_void()
78   ret void
79 }
80
81 define 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
88 ; NOT-R6:        jr $[[TGT]]
89 ; R6:            r6.jr $[[TGT]]
90
91   %1 = musttail call i32 @extern_i32_void()
92   ret i32 %1
93 }
94
95 define 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
102 ; NOT-R6:        jr $[[TGT]]
103 ; R6:            r6.jr $[[TGT]]
104
105   %1 = musttail call float @extern_float_void()
106   ret float %1
107 }
108
109 define 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
119 define 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
130 define 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.
143 define 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
153 define 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
163 define 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 }
172
173 ; Check that passing undef as a double value doesn't cause machine code errors
174 ; for FP64.
175 declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2
176
177 define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 {
178 ; ALL-LABEL: thunk_undef_double:
179 ; O32: # implicit-def: A2
180 ; O32: # implicit-def: A3
181 ; ALL: jr $25
182   tail call void @undef_double(i32 undef, double undef) #8
183   ret void
184 }