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.
This commit is contained in:
parent
ab660b01c3
commit
8a8c257356
4 changed files with 70 additions and 10 deletions
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 } } } } */
|
||||
|
||||
|
|
43
gcc/testsuite/gcc.target/powerpc/pr92488.c
Normal file
43
gcc/testsuite/gcc.target/powerpc/pr92488.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue