From 8a8c2573568aa17ada6163f90991701bc4470976 Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Fri, 17 Jul 2020 21:06:30 -0500 Subject: [PATCH] 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 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. --- gcc/config/rs6000/dfp.md | 13 ++++++ gcc/config/rs6000/rs6000.md | 6 ++- .../gcc.target/powerpc/convert-fp-128.c | 18 ++++---- gcc/testsuite/gcc.target/powerpc/pr92488.c | 43 +++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr92488.c 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 "add3" [(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 +#include + +/* 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; +} -- 2.30.2