[gcc(refs/users/aoliva/heads/testbase)] rs6000: Generate _Decimal128 to _Decimal32 hardware conversion instructions

Alexandre Oliva aoliva@gcc.gnu.org
Wed Jul 22 08:20:25 GMT 2020


https://gcc.gnu.org/g:8a8c2573568aa17ada6163f90991701bc4470976

commit 8a8c2573568aa17ada6163f90991701bc4470976
Author: Peter Bergner <bergner@linux.ibm.com>
Date:   Fri Jul 17 21:06:30 2020 -0500

    rs6000: Generate _Decimal128 to _Decimal32 hardware conversion instructions
    
    We do not currently generate hardware conversion instructions when
    converting from _Decimal128 to _Decimal32.  There is no one instruction
    that does the conversion, so we currently call the __dpd_trunctdsd2
    lib function to do the conversion for us.  However, there is a short
    sequence of dfp hardware instructions that will do the conversion
    correctly.
    
    2020-07-17  Peter Bergner  <bergner@linux.ibm.com>
    
    gcc/
            PR target/92488
            * config/rs6000/dfp.md (trunctdsd2): New define_insn.
            * config/rs6000/rs6000.md (define_attr "isa"): Add p9.
            (define_attr "enabled"): Handle p9.
    
    gcc/testsuite/
            PR target/92488
            * gcc.target/powerpc/convert-fp-128.c (bl, drsp, drdpq): Update counts.
            (__dpd_trunctdsd2): Make conditional on !hard_dfp.
            (__dpd_extendsddd2, __dpd_extendsdtd2, __dpd_truncddsd2,
            __dpd_extendddtd2, __dpd_trunctddd2): Use !hard_dfp.
            * gcc.target/powerpc/pr92488.c: New test.

Diff:
---
 gcc/config/rs6000/dfp.md                          | 13 +++++++
 gcc/config/rs6000/rs6000.md                       |  6 +++-
 gcc/testsuite/gcc.target/powerpc/convert-fp-128.c | 18 +++++-----
 gcc/testsuite/gcc.target/powerpc/pr92488.c        | 43 +++++++++++++++++++++++
 4 files changed, 70 insertions(+), 10 deletions(-)

diff --git a/gcc/config/rs6000/dfp.md b/gcc/config/rs6000/dfp.md
index e91d6f581ed..8f822732bac 100644
--- a/gcc/config/rs6000/dfp.md
+++ b/gcc/config/rs6000/dfp.md
@@ -155,6 +155,19 @@
   [(set_attr "type" "dfp")
    (set_attr "length" "8")])
 
+(define_insn "trunctdsd2"
+  [(set (match_operand:SD 0 "gpc_reg_operand" "=d,d")
+	(float_truncate:SD (match_operand:TD 1 "gpc_reg_operand" "d,d")))
+   (clobber (match_scratch:TD 2 "=&d,&d"))
+   (clobber (match_scratch:DF 3 "=&d,&d"))]
+  "TARGET_DFP"
+  "@
+   mffscdrni %3,7\;drdpq %2,%1\;mffscdrn %3,%3\;drsp %0,%2
+   mffs %3\;mtfsfi 7,7,1\;drdpq %2,%1\;mtfsf 0xff,%3,1,0\;drsp %0,%2"
+  [(set_attr "type" "dfp")
+   (set_attr "isa" "p9,*")
+   (set_attr "length" "16,20")])
+
 (define_insn "add<mode>3"
   [(set (match_operand:DDTD 0 "gpc_reg_operand" "=d")
 	(plus:DDTD (match_operand:DDTD 1 "gpc_reg_operand" "%d")
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index c0d9877c715..b3fcb845a38 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -322,7 +322,7 @@
   (const (symbol_ref "(enum attr_cpu) rs6000_tune")))
 
 ;; The ISA we implement.
-(define_attr "isa" "any,p5,p6,p7,p7v,p8v,p9v,p9kf,p9tf,p10"
+(define_attr "isa" "any,p5,p6,p7,p7v,p8v,p9,p9v,p9kf,p9tf,p10"
   (const_string "any"))
 
 ;; Is this alternative enabled for the current CPU/ISA/etc.?
@@ -351,6 +351,10 @@
 	  (match_test "TARGET_P8_VECTOR"))
      (const_int 1)
 
+     (and (eq_attr "isa" "p9")
+	  (match_test "TARGET_MODULO"))
+     (const_int 1)
+
      (and (eq_attr "isa" "p9v")
 	  (match_test "TARGET_P9_VECTOR"))
      (const_int 1)
diff --git a/gcc/testsuite/gcc.target/powerpc/convert-fp-128.c b/gcc/testsuite/gcc.target/powerpc/convert-fp-128.c
index 67896d92c86..5b0ef3b0d49 100644
--- a/gcc/testsuite/gcc.target/powerpc/convert-fp-128.c
+++ b/gcc/testsuite/gcc.target/powerpc/convert-fp-128.c
@@ -34,7 +34,7 @@ conv2
 
 /* { dg-final { scan-assembler-times {\mbl\M} 24 { target { ! hard_dfp } } } } */
 /* { dg-final { scan-assembler-times {\mbl\M} 19 { target { hard_dfp && { ! ppc_float128 } } } } } */
-/* { dg-final { scan-assembler-times {\mbl\M} 31 { target { hard_dfp && { ppc_float128 && { ! ppc_float128_insns } } } } } } */
+/* { dg-final { scan-assembler-times {\mbl\M} 30 { target { hard_dfp && { ppc_float128 && { ! ppc_float128_insns } } } } } } */
 /* { dg-final { scan-assembler-times {\mbl\M} 27 { target { hard_dfp && { ppc_float128 && { ppc_float128_insns } } } } } } */
 
 
@@ -60,20 +60,20 @@ conv2
 /* { dg-final { scan-assembler-times {\mbl __dpd_extendsddf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_extendsdtf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_extendsdkf\M} 1 { target { ppc_float128 } } } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_extendsddd2\M} 1 { target { ! dfp } } } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_extendsdtd2\M} 1 { target { ! dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_extendsddd2\M} 1 { target { ! hard_dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_extendsdtd2\M} 1 { target { ! hard_dfp } } } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_truncddsf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_truncdddf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_extendddtf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_extendddkf\M} 1 { target { ppc_float128 } } } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_truncddsd2\M} 1 { target { ! dfp } } } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_extendddtd2\M} 1 { target { ! dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_truncddsd2\M} 1 { target { ! hard_dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_extendddtd2\M} 1 { target { ! hard_dfp } } } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_trunctdsf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_trunctddf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_trunctdtf\M} 1 } } */
 /* { dg-final { scan-assembler-times {\mbl __dpd_trunctdkf\M} 1 { target { ppc_float128 } } } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_trunctdsd2\M} 1 } } */
-/* { dg-final { scan-assembler-times {\mbl __dpd_trunctddd2\M} 1 { target { ! dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_trunctdsd2\M} 1 { target { ! hard_dfp } } } } */
+/* { dg-final { scan-assembler-times {\mbl __dpd_trunctddd2\M} 1 { target { ! hard_dfp } } } } */
 
 
 /* { dg-final { scan-assembler-times {\mfrsp|xsrsp\M} 2 { target { ! ppc_float128_insns } } } } */
@@ -88,8 +88,8 @@ conv2
 /* { dg-final { scan-assembler-times {\mxxlor|xscpsgndp\M} 3 { target { ppc_float128_insns } } } } */
 
 
-/* { dg-final { scan-assembler-times {\mdrsp\M} 1 { target { hard_dfp } } } } */
-/* { dg-final { scan-assembler-times {\mdrdpq\M} 1 { target { hard_dfp } } } } */
+/* { dg-final { scan-assembler-times {\mdrsp\M} 2 { target { hard_dfp } } } } */
+/* { dg-final { scan-assembler-times {\mdrdpq\M} 2 { target { hard_dfp } } } } */
 /* { dg-final { scan-assembler-times {\mdctdp\M} 2 { target { hard_dfp } } } } */
 /* { dg-final { scan-assembler-times {\mdctqpq\M} 2 { target { hard_dfp } } } } */
 
diff --git a/gcc/testsuite/gcc.target/powerpc/pr92488.c b/gcc/testsuite/gcc.target/powerpc/pr92488.c
new file mode 100644
index 00000000000..3ca575531ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr92488.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-require-effective-target dfprt } */
+/* { dg-options "-O2" } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Runnable test case for testing _Decimal128 to _Decimal32 rounding.
+   The value below when rounded to _Decimal64 would result in the value
+   1.2345675e+00, which if it were rounded to _Decimal32 would result in
+   the value 1.234568e+00.  However, the correct value when rounding from
+   _Decimal128  directly to _Decimal32 is 1.234567e+00.  */
+
+_Decimal128 td = 1.23456749999999999999e+00dl;
+_Decimal32 sd_expected = 1.234567e+00df;
+
+_Decimal32 __attribute__((noinline))
+td2sd (_Decimal128 td)
+{
+  return td;
+}
+
+int
+main (void)
+{
+  _Decimal32 sd = td2sd (td);
+  if (sd != sd_expected)
+    {
+      union {
+	_Decimal32 sd;
+	unsigned int i;
+      } u;
+
+      printf ("cast to _Decimal32 failed:\n");
+      u.sd = sd;
+      printf ("  actual   = 0x%x\n", u.i);
+      u.sd = sd_expected;
+      printf ("  expected = 0x%x\n", u.i);
+      abort ();
+    }
+
+  return 0;
+}


More information about the Gcc-cvs mailing list