blob: 5c2c87373a322276826122ed8eca1cfd5c9ae61b [file] [log] [blame]
Daniel Sanders7ddb0ab2014-07-14 13:08:14 +00001; Test that the FP64A ABI performs double precision moves via a spill/reload.
2; The requirement is really that odd-numbered double precision registers do not
3; use mfc1/mtc1 to move the bottom 32-bits (because the hardware will redirect
4; this to the top 32-bits of the even register) but we have to make the decision
5; before register allocation so we do this for all double-precision values.
6
7; We don't test MIPS32r1 since support for 64-bit coprocessors (such as a 64-bit
8; FPU) on a 32-bit architecture was added in MIPS32r2.
9; FIXME: We currently don't test that attempting to use FP64 on MIPS32r1 is an
10; error either. This is because a large number of CodeGen tests are
11; incorrectly using this case. We should fix those test cases then add
12; this check here.
13
14; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-BE
15; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A-BE
16; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NO-FP64A-LE
17; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FP64A-LE
18
19; RUN: llc -march=mips64 -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A
20; RUN: not llc -march=mips64 -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A
21; RUN: llc -march=mips64el -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NO-FP64A
22; RUN: not llc -march=mips64el -mcpu=mips64 -mattr=fp64,nooddspreg < %s 2>&1 | FileCheck %s -check-prefix=64-FP64A
23
24; 64-FP64A: LLVM ERROR: -mattr=+nooddspreg requires the O32 ABI.
25
26declare double @dbl();
27
28define double @call1(double %d, ...) {
29 ret double %d
30
31; ALL-LABEL: call1:
32
33; 32R2-NO-FP64A-LE-NOT: addiu $sp, $sp
34; 32R2-NO-FP64A-LE: mtc1 $4, $f0
35; 32R2-NO-FP64A-LE: mthc1 $5, $f0
36
37; 32R2-NO-FP64A-BE-NOT: addiu $sp, $sp
38; 32R2-NO-FP64A-BE: mtc1 $5, $f0
39; 32R2-NO-FP64A-BE: mthc1 $4, $f0
40
41; 32R2-FP64A-LE: addiu $sp, $sp, -8
42; 32R2-FP64A-LE: sw $4, 0($sp)
43; 32R2-FP64A-LE: sw $5, 4($sp)
44; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
45
46; 32R2-FP64A-BE: addiu $sp, $sp, -8
47; 32R2-FP64A-BE: sw $5, 0($sp)
48; 32R2-FP64A-BE: sw $4, 4($sp)
49; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
50
51; 64-NO-FP64A: daddiu $sp, $sp, -64
52; 64-NO-FP64A: mov.d $f0, $f12
53}
54
55define double @call2(i32 %i, double %d) {
56 ret double %d
57
58; ALL-LABEL: call2:
59
60; 32R2-NO-FP64A-LE: mtc1 $6, $f0
61; 32R2-NO-FP64A-LE: mthc1 $7, $f0
62
63; 32R2-NO-FP64A-BE: mtc1 $7, $f0
64; 32R2-NO-FP64A-BE: mthc1 $6, $f0
65
66; 32R2-FP64A-LE: addiu $sp, $sp, -8
67; 32R2-FP64A-LE: sw $6, 0($sp)
68; 32R2-FP64A-LE: sw $7, 4($sp)
69; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
70
71; 32R2-FP64A-BE: addiu $sp, $sp, -8
72; 32R2-FP64A-BE: sw $7, 0($sp)
73; 32R2-FP64A-BE: sw $6, 4($sp)
74; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
75
76; 64-NO-FP64A-NOT: daddiu $sp, $sp
77; 64-NO-FP64A: mov.d $f0, $f13
78}
79
80define double @call3(float %f1, float %f2, double %d) {
81 ret double %d
82
83; ALL-LABEL: call3:
84
85; 32R2-NO-FP64A-LE: mtc1 $6, $f0
86; 32R2-NO-FP64A-LE: mthc1 $7, $f0
87
88; 32R2-NO-FP64A-BE: mtc1 $7, $f0
89; 32R2-NO-FP64A-BE: mthc1 $6, $f0
90
91; 32R2-FP64A-LE: addiu $sp, $sp, -8
92; 32R2-FP64A-LE: sw $6, 0($sp)
93; 32R2-FP64A-LE: sw $7, 4($sp)
94; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
95
96; 32R2-FP64A-BE: addiu $sp, $sp, -8
97; 32R2-FP64A-BE: sw $7, 0($sp)
98; 32R2-FP64A-BE: sw $6, 4($sp)
99; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
100
101; 64-NO-FP64A-NOT: daddiu $sp, $sp
102; 64-NO-FP64A: mov.d $f0, $f14
103}
104
105define double @call4(float %f, double %d, ...) {
106 ret double %d
107
108; ALL-LABEL: call4:
109
110; 32R2-NO-FP64A-LE: mtc1 $6, $f0
111; 32R2-NO-FP64A-LE: mthc1 $7, $f0
112
113; 32R2-NO-FP64A-BE: mtc1 $7, $f0
114; 32R2-NO-FP64A-BE: mthc1 $6, $f0
115
116; 32R2-FP64A-LE: addiu $sp, $sp, -8
117; 32R2-FP64A-LE: sw $6, 0($sp)
118; 32R2-FP64A-LE: sw $7, 4($sp)
119; 32R2-FP64A-LE: ldc1 $f0, 0($sp)
120
121; 32R2-FP64A-BE: addiu $sp, $sp, -8
122; 32R2-FP64A-BE: sw $7, 0($sp)
123; 32R2-FP64A-BE: sw $6, 4($sp)
124; 32R2-FP64A-BE: ldc1 $f0, 0($sp)
125
126; 64-NO-FP64A: daddiu $sp, $sp, -48
127; 64-NO-FP64A: mov.d $f0, $f13
128}
129
130define double @call5(double %a, double %b, ...) {
131 %1 = fsub double %a, %b
132 ret double %1
133
134; ALL-LABEL: call5:
135
136; 32R2-NO-FP64A-LE-DAG: mtc1 $4, $[[T0:f[0-9]+]]
137; 32R2-NO-FP64A-LE-DAG: mthc1 $5, $[[T0:f[0-9]+]]
138; 32R2-NO-FP64A-LE-DAG: mtc1 $6, $[[T1:f[0-9]+]]
139; 32R2-NO-FP64A-LE-DAG: mthc1 $7, $[[T1:f[0-9]+]]
140; 32R2-NO-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]]
141
142; 32R2-NO-FP64A-BE-DAG: mtc1 $5, $[[T0:f[0-9]+]]
143; 32R2-NO-FP64A-BE-DAG: mthc1 $4, $[[T0:f[0-9]+]]
144; 32R2-NO-FP64A-BE-DAG: mtc1 $7, $[[T1:f[0-9]+]]
145; 32R2-NO-FP64A-BE-DAG: mthc1 $6, $[[T1:f[0-9]+]]
146; 32R2-NO-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]]
147
148; 32R2-FP64A-LE: addiu $sp, $sp, -8
149; 32R2-FP64A-LE: sw $6, 0($sp)
150; 32R2-FP64A-LE: sw $7, 4($sp)
151; 32R2-FP64A-LE: ldc1 $[[T1:f[0-9]+]], 0($sp)
152; 32R2-FP64A-LE: sw $4, 0($sp)
153; 32R2-FP64A-LE: sw $5, 4($sp)
154; 32R2-FP64A-LE: ldc1 $[[T0:f[0-9]+]], 0($sp)
155; 32R2-FP64A-LE: sub.d $f0, $[[T0]], $[[T1]]
156
157; 32R2-FP64A-BE: addiu $sp, $sp, -8
158; 32R2-FP64A-BE: sw $7, 0($sp)
159; 32R2-FP64A-BE: sw $6, 4($sp)
160; 32R2-FP64A-BE: ldc1 $[[T1:f[0-9]+]], 0($sp)
161; 32R2-FP64A-BE: sw $5, 0($sp)
162; 32R2-FP64A-BE: sw $4, 4($sp)
163; 32R2-FP64A-BE: ldc1 $[[T0:f[0-9]+]], 0($sp)
164; 32R2-FP64A-BE: sub.d $f0, $[[T0]], $[[T1]]
165
166; 64-NO-FP64A: sub.d $f0, $f12, $f13
167}
168
169define double @move_from(double %d) {
170 %1 = call double @dbl()
171 %2 = call double @call2(i32 0, double %1)
172 ret double %2
173
174; ALL-LABEL: move_from:
175
176; 32R2-NO-FP64A-LE-DAG: mfc1 $6, $f0
177; 32R2-NO-FP64A-LE-DAG: mfhc1 $7, $f0
178
179; 32R2-NO-FP64A-BE-DAG: mfc1 $7, $f0
180; 32R2-NO-FP64A-BE-DAG: mfhc1 $6, $f0
181
182; 32R2-FP64A-LE: addiu $sp, $sp, -32
183; 32R2-FP64A-LE: sdc1 $f0, 16($sp)
184; 32R2-FP64A-LE: lw $6, 16($sp)
185; FIXME: This store is redundant
186; 32R2-FP64A-LE: sdc1 $f0, 16($sp)
187; 32R2-FP64A-LE: lw $7, 20($sp)
188
189; 32R2-FP64A-BE: addiu $sp, $sp, -32
190; 32R2-FP64A-BE: sdc1 $f0, 16($sp)
191; 32R2-FP64A-BE: lw $6, 20($sp)
192; FIXME: This store is redundant
193; 32R2-FP64A-BE: sdc1 $f0, 16($sp)
194; 32R2-FP64A-BE: lw $7, 16($sp)
195
196; 64-NO-FP64A: mov.d $f13, $f0
197}