[mips] For the FP64A ABI, odd-numbered double-precision moves must not use mtc1/mfc1.
[oota-llvm.git] / test / CodeGen / Mips / fpxx.ll
index fb75e36059743d767fa101dfd599e79ad0d54f55..7e2ed22e2d805aeb573c9840dd9e23785f247ad0 100644 (file)
 ; 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-TOOD: 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=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-TOOD: llc -march=mips64 -mcpu=mips64 -mattr=-n64,+o32 -mattr=fpxx < %s | FileCheck %s -check-prefix=ALL -check-prefix=64-O32-FPXX
+; 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.
+; 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-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-NOFPXX:   mtc1    $4, $f0
+; 32R2-NOFPXX:   mthc1   $5, $f0
 
-; 32R2-FPXX:    mtc1    $4, $f0
-; 32R2-FPXX:    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
+; 4-NOFPXX:      mov.d   $f0, $f12
 
-; 64-NOFPXX:    mov.d   $f0, $f12
+; 64-NOFPXX:     mov.d   $f0, $f12
 }
 
 define double @test2(i32 %i, double %d) {
@@ -50,23 +51,23 @@ define double @test2(i32 %i, double %d) {
 
 ; ALL-LABEL: test2:
 
-; 32-NOFPXX:    mtc1    $6, $f0
-; 32-NOFPXX:    mtc1    $7, $f1
+; 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-NOFPXX:   mtc1    $6, $f0
+; 32R2-NOFPXX:   mthc1   $7, $f0
 
-; 32R2-FPXX:    mtc1    $6, $f0
-; 32R2-FPXX:    mthc1   $7, $f0
+; 32R2-FPXX:     mtc1    $6, $f0
+; 32R2-FPXX:     mthc1   $7, $f0
 
-; 4-NOFPXX:    mov.d   $f0, $f13
+; 4-NOFPXX:      mov.d   $f0, $f13
 
-; 64-NOFPXX:    mov.d   $f0, $f13
+; 64-NOFPXX:     mov.d   $f0, $f13
 }
 
 define double @test3(float %f1, float %f2, double %d) {
@@ -74,23 +75,23 @@ define double @test3(float %f1, float %f2, double %d) {
 
 ; ALL-LABEL: test3:
 
-; 32-NOFPXX:    mtc1    $6, $f0
-; 32-NOFPXX:    mtc1    $7, $f1
+; 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-NOFPXX:   mtc1    $6, $f0
+; 32R2-NOFPXX:   mthc1   $7, $f0
 
-; 32R2-FPXX:    mtc1    $6, $f0
-; 32R2-FPXX:    mthc1   $7, $f0
+; 32R2-FPXX:     mtc1    $6, $f0
+; 32R2-FPXX:     mthc1   $7, $f0
 
-; 4-NOFPXX:    mov.d   $f0, $f14
+; 4-NOFPXX:      mov.d   $f0, $f14
 
-; 64-NOFPXX:    mov.d   $f0, $f14
+; 64-NOFPXX:     mov.d   $f0, $f14
 }
 
 define double @test4(float %f, double %d, ...) {
@@ -98,23 +99,23 @@ define double @test4(float %f, double %d, ...) {
 
 ; ALL-LABEL: test4:
 
-; 32-NOFPXX:    mtc1    $6, $f0
-; 32-NOFPXX:    mtc1    $7, $f1
+; 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-NOFPXX:   mtc1    $6, $f0
+; 32R2-NOFPXX:   mthc1   $7, $f0
 
-; 32R2-FPXX:    mtc1    $6, $f0
-; 32R2-FPXX:    mthc1   $7, $f0
+; 32R2-FPXX:     mtc1    $6, $f0
+; 32R2-FPXX:     mthc1   $7, $f0
 
-; 4-NOFPXX:    mov.d   $f0, $f13
+; 4-NOFPXX:      mov.d   $f0, $f13
 
-; 64-NOFPXX:    mov.d   $f0, $f13
+; 64-NOFPXX:     mov.d   $f0, $f13
 }
 
 define double @test5() {
@@ -122,21 +123,99 @@ define double @test5() {
 
 ; ALL-LABEL: test5:
 
-; 32-NOFPXX:    mtc1    $zero, $f0
-; 32-NOFPXX:    mtc1    $zero, $f1
+; 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)
+; 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
 
-; 32R2-NOFPXX:    mtc1    $zero, $f0
-; 32R2-NOFPXX:    mthc1   $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]]
 
-; 32R2-FPXX:    mtc1    $zero, $f0
-; 32R2-FPXX:    mthc1   $zero, $f0
+; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used.
+; 4-NOFPXX:          sub.d   $f0, $f12, $f13
 
-; 4-NOFPXX:    dmtc1 $zero, $f0
+; floats/doubles are not passed in integer registers for n64, so dmtc1 is not used.
+; 64-NOFPXX:         sub.d   $f0, $f12, $f13
+}
 
-; 64-NOFPXX:    dmtc1 $zero, $f0
+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
 }