Home | History | Annotate | Download | only in Mips
      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-prefixes=ALL,32R2-NO-FP64A-BE
     15 ; RUN: llc -march=mips -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefixes=ALL,32R2-FP64A
     16 ; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,32R2-NO-FP64A-LE
     17 ; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=fp64,nooddspreg < %s | FileCheck %s -check-prefixes=ALL,32R2-FP64A
     18 
     19 ; RUN: llc -march=mips64 -mcpu=mips64 -mattr=fp64 < %s | FileCheck %s -check-prefixes=ALL,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-prefixes=ALL,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:               addiu   $sp, $sp, -8
     42 ; 32R2-FP64A:               sw      $4, 0($sp)
     43 ; 32R2-FP64A:               sw      $5, 4($sp)
     44 ; 32R2-FP64A:               ldc1    $f0, 0($sp)
     45 
     46 ; 64-NO-FP64A:              daddiu  $sp, $sp, -64
     47 ; 64-NO-FP64A:              mov.d   $f0, $f12
     48 }
     49 
     50 define double @call2(i32 %i, double %d) {
     51   ret double %d
     52 
     53 ; ALL-LABEL:        call2:
     54 
     55 ; 32R2-NO-FP64A-LE:     mtc1    $6, $f0
     56 ; 32R2-NO-FP64A-LE:     mthc1   $7, $f0
     57 
     58 ; 32R2-NO-FP64A-BE:     mtc1    $7, $f0
     59 ; 32R2-NO-FP64A-BE:     mthc1   $6, $f0
     60 
     61 ; 32R2-FP64A:           addiu   $sp, $sp, -8
     62 ; 32R2-FP64A:           sw      $6, 0($sp)
     63 ; 32R2-FP64A:           sw      $7, 4($sp)
     64 ; 32R2-FP64A:           ldc1    $f0, 0($sp)
     65 
     66 ; 64-NO-FP64A-NOT:      daddiu  $sp, $sp
     67 ; 64-NO-FP64A:          mov.d   $f0, $f13
     68 }
     69 
     70 define double @call3(float %f1, float %f2, double %d) {
     71   ret double %d
     72 
     73 ; ALL-LABEL:        call3:
     74 
     75 ; 32R2-NO-FP64A-LE:     mtc1    $6, $f0
     76 ; 32R2-NO-FP64A-LE:     mthc1   $7, $f0
     77 
     78 ; 32R2-NO-FP64A-BE:     mtc1    $7, $f0
     79 ; 32R2-NO-FP64A-BE:     mthc1   $6, $f0
     80 
     81 ; 32R2-FP64A:           addiu   $sp, $sp, -8
     82 ; 32R2-FP64A:           sw      $6, 0($sp)
     83 ; 32R2-FP64A:           sw      $7, 4($sp)
     84 ; 32R2-FP64A:           ldc1    $f0, 0($sp)
     85 
     86 ; 64-NO-FP64A-NOT:      daddiu  $sp, $sp
     87 ; 64-NO-FP64A:          mov.d   $f0, $f14
     88 }
     89 
     90 define double @call4(float %f, double %d, ...) {
     91   ret double %d
     92 
     93 ; ALL-LABEL:        call4:
     94 
     95 ; 32R2-NO-FP64A-LE:     mtc1    $6, $f0
     96 ; 32R2-NO-FP64A-LE:     mthc1   $7, $f0
     97 
     98 ; 32R2-NO-FP64A-BE:     mtc1    $7, $f0
     99 ; 32R2-NO-FP64A-BE:     mthc1   $6, $f0
    100 
    101 ; 32R2-FP64A:           addiu   $sp, $sp, -8
    102 ; 32R2-FP64A:           sw      $6, 0($sp)
    103 ; 32R2-FP64A:           sw      $7, 4($sp)
    104 ; 32R2-FP64A:           ldc1    $f0, 0($sp)
    105 
    106 ; 64-NO-FP64A:          daddiu  $sp, $sp, -48
    107 ; 64-NO-FP64A:          mov.d   $f0, $f13
    108 }
    109 
    110 define double @call5(double %a, double %b, ...) {
    111   %1 = fsub double %a, %b
    112   ret double %1
    113 
    114 ; ALL-LABEL:            call5:
    115 
    116 ; 32R2-NO-FP64A-LE-DAG:     mtc1    $4, $[[T0:f[0-9]+]]
    117 ; 32R2-NO-FP64A-LE-DAG:     mthc1   $5, $[[T0:f[0-9]+]]
    118 ; 32R2-NO-FP64A-LE-DAG:     mtc1    $6, $[[T1:f[0-9]+]]
    119 ; 32R2-NO-FP64A-LE-DAG:     mthc1   $7, $[[T1:f[0-9]+]]
    120 ; 32R2-NO-FP64A-LE:         sub.d   $f0, $[[T0]], $[[T1]]
    121 
    122 ; 32R2-NO-FP64A-BE-DAG:     mtc1    $5, $[[T0:f[0-9]+]]
    123 ; 32R2-NO-FP64A-BE-DAG:     mthc1   $4, $[[T0:f[0-9]+]]
    124 ; 32R2-NO-FP64A-BE-DAG:     mtc1    $7, $[[T1:f[0-9]+]]
    125 ; 32R2-NO-FP64A-BE-DAG:     mthc1   $6, $[[T1:f[0-9]+]]
    126 ; 32R2-NO-FP64A-BE:         sub.d   $f0, $[[T0]], $[[T1]]
    127 
    128 ; 32R2-FP64A:               addiu   $sp, $sp, -8
    129 ; 32R2-FP64A:               sw      $6, 0($sp)
    130 ; 32R2-FP64A:               sw      $7, 4($sp)
    131 ; 32R2-FP64A:               ldc1    $[[T1:f[0-9]+]], 0($sp)
    132 ; 32R2-FP64A:               sw      $4, 0($sp)
    133 ; 32R2-FP64A:               sw      $5, 4($sp)
    134 ; 32R2-FP64A:               ldc1    $[[T0:f[0-9]+]], 0($sp)
    135 ; 32R2-FP64A:               sub.d   $f0, $[[T0]], $[[T1]]
    136 
    137 ; 64-NO-FP64A:              sub.d   $f0, $f12, $f13
    138 }
    139 
    140 define double @move_from(double %d) {
    141   %1 = call double @dbl()
    142   %2 = call double @call2(i32 0, double %1)
    143   ret double %2
    144 
    145 ; ALL-LABEL:        move_from:
    146 
    147 ; 32R2-NO-FP64A-LE-DAG: mfc1    $6, $f0
    148 ; 32R2-NO-FP64A-LE-DAG: mfhc1   $7, $f0
    149 
    150 ; 32R2-NO-FP64A-BE-DAG: mfc1    $7, $f0
    151 ; 32R2-NO-FP64A-BE-DAG: mfhc1   $6, $f0
    152 
    153 ; 32R2-FP64A:           addiu   $sp, $sp, -32
    154 ; 32R2-FP64A:           sdc1    $f0, 16($sp)
    155 ; 32R2-FP64A:           lw      $6, 16($sp)
    156 ; FIXME: This store is redundant
    157 ; 32R2-FP64A:           sdc1    $f0, 16($sp)
    158 ; 32R2-FP64A:           lw      $7, 20($sp)
    159 
    160 ; 64-NO-FP64A:          mov.d   $f13, $f0
    161 }
    162