• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; Test the 'call' instruction and the tailcall variant.
2
3; RUN: llc -march=mips   -mcpu=mips32   -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
4; RUN: llc -march=mips   -mcpu=mips32r2 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
5; RUN: llc -march=mips   -mcpu=mips32r3 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
6; RUN: llc -march=mips   -mcpu=mips32r5 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,NOT-R6C
7; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C
8; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,O32,R6C
9; RUN: llc -march=mips64 -mcpu=mips4    -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
10; RUN: llc -march=mips64 -mcpu=mips64   -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
11; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
12; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
13; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,NOT-R6C
14; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic  -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefixes=ALL,N64,R6C
15; RUN: llc -march=mips   -mcpu=mips32   -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
16; RUN: llc -march=mips   -mcpu=mips32r2 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
17; RUN: llc -march=mips   -mcpu=mips32r3 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
18; RUN: llc -march=mips   -mcpu=mips32r5 -relocation-model=pic  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=NOT-R6C
19; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
20; RUN: llc -march=mips   -mcpu=mips32r6 -relocation-model=pic -mattr=+fp64,+nooddspreg -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 -check-prefix=R6C
21; RUN: llc -march=mips64 -mcpu=mips4    -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
22; RUN: llc -march=mips64 -mcpu=mips64   -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
23; RUN: llc -march=mips64 -mcpu=mips64r2 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
24; RUN: llc -march=mips64 -mcpu=mips64r3 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
25; RUN: llc -march=mips64 -mcpu=mips64r5 -relocation-model=pic   -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NOT-R6C
26; RUN: llc -march=mips64 -mcpu=mips64r6 -relocation-model=pic  -disable-mips-delay-filler  -mips-tail-calls=1 < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=R6C
27
28declare void @extern_void_void()
29declare i32 @extern_i32_void()
30declare float @extern_float_void()
31
32define i32 @call_void_void() {
33; ALL-LABEL: call_void_void:
34
35; O32:           lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
36
37; N64:           ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
38
39; NOT-R6C:       jalr $[[TGT]]
40; R6C:           jalrc $[[TGT]]
41
42  call void @extern_void_void()
43; R6C:           jrc $ra
44  ret i32 0
45}
46
47define i32 @call_i32_void() {
48; ALL-LABEL: call_i32_void:
49
50; O32:           lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
51
52; N64:           ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
53
54; NOT-R6C:       jalr $[[TGT]]
55; R6C:           jalrc $[[TGT]]
56
57  %1 = call i32 @extern_i32_void()
58  %2 = add i32 %1, 1
59; R6C:           jrc $ra
60  ret i32 %2
61}
62
63define float @call_float_void() {
64; ALL-LABEL: call_float_void:
65
66; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
67;        look into it at some point.
68; O32:           addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
69; O32:           lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
70
71; N64:           ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
72
73; NOT-R6C:       jalr $[[TGT]]
74; R6C:           jalrc $[[TGT]]
75
76
77  %1 = call float @extern_float_void()
78  %2 = fadd float %1, 1.0
79; R6C:           jrc $ra
80  ret float %2
81}
82
83define i32 @indirect_call_void_void(void ()* %addr) {
84; ALL-LABEL: indirect_call_void_void:
85
86; ALL:           move $25, $4
87; NOT-R6C:       jalr $25
88; R6C:           jalrc $25
89
90  call void %addr()
91; R6C:           jrc $ra
92  ret i32 0
93}
94
95define i32 @indirect_call_i32_void(i32 ()* %addr) {
96; ALL-LABEL: indirect_call_i32_void:
97
98; ALL:           move $25, $4
99; NOT-R6C:       jalr $25
100; R6C:           jalrc $25
101
102
103  %1 = call i32 %addr()
104  %2 = add i32 %1, 1
105; R6C:           jrc $ra
106  ret i32 %2
107}
108
109define float @indirect_call_float_void(float ()* %addr) {
110; ALL-LABEL: indirect_call_float_void:
111
112; ALL:           move $25, $4
113; NOT-R6C:       jalr $25
114; R6C:           jalrc $25
115
116
117  %1 = call float %addr()
118  %2 = fadd float %1, 1.0
119; R6C:           jrc $ra
120  ret float %2
121}
122
123; We can't use 'musttail' here because the verifier is too conservative and
124; prohibits any prototype difference.
125define void @tail_indirect_call_void_void(void ()* %addr) {
126; ALL-LABEL: tail_indirect_call_void_void:
127
128; ALL:           move $25, $4
129; NOT-R6C:       jr   $[[TGT]]
130; R6C:           jrc  $[[TGT]]
131
132  tail call void %addr()
133  ret void
134}
135
136define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
137; ALL-LABEL: tail_indirect_call_i32_void:
138
139; ALL:           move $25, $4
140; NOT-R6C:       jr   $[[TGT]]
141; R6C:           jrc  $[[TGT]]
142
143  %1 = tail call i32 %addr()
144  ret i32 %1
145}
146
147define float @tail_indirect_call_float_void(float ()* %addr) {
148; ALL-LABEL: tail_indirect_call_float_void:
149
150; ALL:           move $25, $4
151; NOT-R6C:       jr   $[[TGT]]
152; R6C:           jrc  $[[TGT]]
153
154  %1 = tail call float %addr()
155  ret float %1
156}
157
158; Check that passing undef as a double value doesn't cause machine code errors
159; for FP64.
160declare hidden void @undef_double(i32 %this, double %volume) unnamed_addr align 2
161
162define hidden void @thunk_undef_double(i32 %this, double %volume) unnamed_addr align 2 {
163; ALL-LABEL: thunk_undef_double:
164; O32: # implicit-def: $a2
165; O32: # implicit-def: $a3
166; NOT-R6C:    jr   $[[TGT]]
167; R6C:        jrc  $[[TGT]]
168
169  tail call void @undef_double(i32 undef, double undef) #8
170  ret void
171}
172
173; Check that immediate addresses do not use jal.
174define i32 @jal_only_allows_symbols() {
175; ALL-LABEL: jal_only_allows_symbols:
176
177; ALL-NOT:       {{jal }}
178; ALL:           addiu $[[TGT:[0-9]+]], $zero, 1234
179; ALL-NOT:       {{jal }}
180; NOT-R6C:       jalr $[[TGT]]
181; R6C:           jalrc $[[TGT]]
182; ALL-NOT:       {{jal }}
183
184  call void () inttoptr (i32 1234 to void ()*)()
185; R6C:           jrc $ra
186  ret i32 0
187}
188
189