llvm-6502/test/CodeGen/Mips/fpxx.ll
Daniel Sanders c4ce78e261 [mips] For the FP64A ABI, odd-numbered double-precision moves must not use mtc1/mfc1.
Summary:
This is because the FP64A the hardware will redirect 32-bit reads/writes
from/to odd-numbered registers to the upper 32-bits of the corresponding
even register. In effect, simulating FR=0 mode when FR=0 mode is not
available.

Unfortunately, we have to make the decision to avoid mfc1/mtc1 before
register allocation so we currently do this for even registers too.

FPXX has a similar requirement on 32-bit architectures that lack
mfhc1/mthc1 so this patch also handles the affected moves from the FPU for
FPXX too. Moves to the FPU were supported by an earlier commit.

Differential Revision: http://reviews.llvm.org/D4484


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212938 91177308-0d34-0410-b5e6-96231b3b80d8
2014-07-14 13:08:14 +00:00

222 lines
6.8 KiB
LLVM

; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32-NOFPXX
; RUN: llc -march=mipsel -mcpu=mips32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=32-FPXX
; RUN: llc -march=mipsel -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-NOFPXX
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R2-FPXX
; RUN: llc -march=mips64 -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-NOFPXX
; RUN: not llc -march=mips64 -mcpu=mips4 -mattr=fpxx < %s 2>&1 | FileCheck %s -check-prefix=4-FPXX
; RUN: llc -march=mips64 -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-NOFPXX
; RUN: not llc -march=mips64 -mcpu=mips64 -mattr=fpxx < %s 2>&1 | FileCheck %s -check-prefix=64-FPXX
; RUN-TODO: llc -march=mips64 -mcpu=mips4 -mattr=-n64,+o32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-O32-NOFPXX
; RUN-TODO: llc -march=mips64 -mcpu=mips4 -mattr=-n64,+o32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=4-O32-FPXX
; RUN-TODO: llc -march=mips64 -mcpu=mips64 -mattr=-n64,+o32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-O32-NOFPXX
; RUN-TODO: llc -march=mips64 -mcpu=mips64 -mattr=-n64,+o32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-O32-FPXX
declare double @dbl();
; 4-FPXX: LLVM ERROR: FPXX is not permitted for the N32/N64 ABI's.
; 64-FPXX: LLVM ERROR: FPXX is not permitted for the N32/N64 ABI's.
define double @test1(double %d, ...) {
ret double %d
; ALL-LABEL: test1:
; 32-NOFPXX: mtc1 $4, $f0
; 32-NOFPXX: mtc1 $5, $f1
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $4, 0($sp)
; 32-FPXX: sw $5, 4($sp)
; 32-FPXX: ldc1 $f0, 0($sp)
; 32R2-NOFPXX: mtc1 $4, $f0
; 32R2-NOFPXX: mthc1 $5, $f0
; 32R2-FPXX: mtc1 $4, $f0
; 32R2-FPXX: mthc1 $5, $f0
; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used.
; 4-NOFPXX: mov.d $f0, $f12
; 64-NOFPXX: mov.d $f0, $f12
}
define double @test2(i32 %i, double %d) {
ret double %d
; ALL-LABEL: test2:
; 32-NOFPXX: mtc1 $6, $f0
; 32-NOFPXX: mtc1 $7, $f1
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $6, 0($sp)
; 32-FPXX: sw $7, 4($sp)
; 32-FPXX: ldc1 $f0, 0($sp)
; 32R2-NOFPXX: mtc1 $6, $f0
; 32R2-NOFPXX: mthc1 $7, $f0
; 32R2-FPXX: mtc1 $6, $f0
; 32R2-FPXX: mthc1 $7, $f0
; 4-NOFPXX: mov.d $f0, $f13
; 64-NOFPXX: mov.d $f0, $f13
}
define double @test3(float %f1, float %f2, double %d) {
ret double %d
; ALL-LABEL: test3:
; 32-NOFPXX: mtc1 $6, $f0
; 32-NOFPXX: mtc1 $7, $f1
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $6, 0($sp)
; 32-FPXX: sw $7, 4($sp)
; 32-FPXX: ldc1 $f0, 0($sp)
; 32R2-NOFPXX: mtc1 $6, $f0
; 32R2-NOFPXX: mthc1 $7, $f0
; 32R2-FPXX: mtc1 $6, $f0
; 32R2-FPXX: mthc1 $7, $f0
; 4-NOFPXX: mov.d $f0, $f14
; 64-NOFPXX: mov.d $f0, $f14
}
define double @test4(float %f, double %d, ...) {
ret double %d
; ALL-LABEL: test4:
; 32-NOFPXX: mtc1 $6, $f0
; 32-NOFPXX: mtc1 $7, $f1
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $6, 0($sp)
; 32-FPXX: sw $7, 4($sp)
; 32-FPXX: ldc1 $f0, 0($sp)
; 32R2-NOFPXX: mtc1 $6, $f0
; 32R2-NOFPXX: mthc1 $7, $f0
; 32R2-FPXX: mtc1 $6, $f0
; 32R2-FPXX: mthc1 $7, $f0
; 4-NOFPXX: mov.d $f0, $f13
; 64-NOFPXX: mov.d $f0, $f13
}
define double @test5() {
ret double 0.000000e+00
; ALL-LABEL: test5:
; 32-NOFPXX: mtc1 $zero, $f0
; 32-NOFPXX: mtc1 $zero, $f1
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $zero, 0($sp)
; 32-FPXX: sw $zero, 4($sp)
; 32-FPXX: ldc1 $f0, 0($sp)
; 32R2-NOFPXX: mtc1 $zero, $f0
; 32R2-NOFPXX: mthc1 $zero, $f0
; 32R2-FPXX: mtc1 $zero, $f0
; 32R2-FPXX: mthc1 $zero, $f0
; 4-NOFPXX: dmtc1 $zero, $f0
; 64-NOFPXX: dmtc1 $zero, $f0
}
define double @test6(double %a, double %b, ...) {
%1 = fsub double %a, %b
ret double %1
; ALL-LABEL: test6:
; 32-NOFPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]]
; 32-NOFPXX-DAG: mtc1 $5, ${{f[0-9]*[13579]}}
; 32-NOFPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]]
; 32-NOFPXX-DAG: mtc1 $7, ${{f[0-9]*[13579]}}
; 32-NOFPXX: sub.d $f0, $[[T0]], $[[T1]]
; 32-FPXX: addiu $sp, $sp, -8
; 32-FPXX: sw $6, 0($sp)
; 32-FPXX: sw $7, 4($sp)
; 32-FPXX: ldc1 $[[T1:f[0-9]+]], 0($sp)
; 32-FPXX: sw $4, 0($sp)
; 32-FPXX: sw $5, 4($sp)
; 32-FPXX: ldc1 $[[T0:f[0-9]+]], 0($sp)
; 32-FPXX: sub.d $f0, $[[T0]], $[[T1]]
; 32R2-NOFPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]]
; 32R2-NOFPXX-DAG: mthc1 $5, $[[T0]]
; 32R2-NOFPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]]
; 32R2-NOFPXX-DAG: mthc1 $7, $[[T1]]
; 32R2-NOFPXX: sub.d $f0, $[[T0]], $[[T1]]
; 32R2-FPXX-DAG: mtc1 $4, $[[T0:f[0-9]+]]
; 32R2-FPXX-DAG: mthc1 $5, $[[T0]]
; 32R2-FPXX-DAG: mtc1 $6, $[[T1:f[0-9]+]]
; 32R2-FPXX-DAG: mthc1 $7, $[[T1]]
; 32R2-FPXX: sub.d $f0, $[[T0]], $[[T1]]
; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used.
; 4-NOFPXX: sub.d $f0, $f12, $f13
; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used.
; 64-NOFPXX: sub.d $f0, $f12, $f13
}
define double @move_from1(double %d) {
%1 = call double @dbl()
%2 = call double @test2(i32 0, double %1)
ret double %2
; ALL-LABEL: move_from1:
; 32-NOFPXX-DAG: mfc1 $6, $f0
; 32-NOFPXX-DAG: mfc1 $7, $f1
; 32-FPXX: addiu $sp, $sp, -32
; 32-FPXX: sdc1 $f0, 16($sp)
; 32-FPXX: lw $6, 16($sp)
; FIXME: This store is redundant
; 32-FPXX: sdc1 $f0, 16($sp)
; 32-FPXX: lw $7, 20($sp)
; 32R2-NOFPXX-DAG: mfc1 $6, $f0
; 32R2-NOFPXX-DAG: mfhc1 $7, $f0
; 32R2-FPXX-DAG: mfc1 $6, $f0
; 32R2-FPXX-DAG: mfhc1 $7, $f0
; floats/doubles are not passed in integer registers for n64, so dmfc1 is not used.
; We can't use inline assembly to force a copy either because trying to force
; a copy to a GPR this way fails with ; "couldn't allocate input reg for
; constraint 'r'". It therefore seems impossible to test the generation of dmfc1
; in a simple test.
; 4-NOFPXX: mov.d $f13, $f0
; floats/doubles are not passed in integer registers for n64, so dmfc1 is not used.
; We can't use inline assembly to force a copy either because trying to force
; a copy to a GPR this way fails with ; "couldn't allocate input reg for
; constraint 'r'". It therefore seems impossible to test the generation of dmfc1
; in a simple test.
; 64-NOFPXX: mov.d $f13, $f0
}