Re-apply r214881: Fix return sequence on armv4 thumb
[oota-llvm.git] / test / CodeGen / Mips / fp64a.ll
1 ; 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
26 declare double @dbl();
27
28 define 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
55 define 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
80 define 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
105 define 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
130 define 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
169 define 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 }