IBM Z: Fix long double <-> DFP conversions

When switching the s390 backend to store long doubles in vector
registers, the patterns for long double <-> DFP conversions were
forgotten.  This did not cause observable problems so far, because
libdfp calls are emitted instead of pfpo.  However, when building
libdfp itself, this leads to infinite recursion.

gcc/ChangeLog:

	PR target/99134
	* config/s390/vector.md (trunctf<DFP_ALL:mode>2_vr): New
	pattern.
	(trunctf<DFP_ALL:mode>2): Likewise.
	(trunctdtf2_vr): Likewise.
	(trunctdtf2): Likewise.
	(extend<DFP_ALL:mode>tf2_vr): Likewise.
	(extend<DFP_ALL:mode>tf2): Likewise.
	(extendtftd2_vr): Likewise.
	(extendtftd2): Likewise.

gcc/testsuite/ChangeLog:

	PR target/99134
	* gcc.target/s390/vector/long-double-from-decimal128.c: New test.
	* gcc.target/s390/vector/long-double-from-decimal32.c: New test.
	* gcc.target/s390/vector/long-double-from-decimal64.c: New test.
	* gcc.target/s390/vector/long-double-to-decimal128.c: New test.
	* gcc.target/s390/vector/long-double-to-decimal32.c: New test.
	* gcc.target/s390/vector/long-double-to-decimal64.c: New test.
This commit is contained in:
Ilya Leoshkevich 2021-02-17 14:40:03 +01:00
parent a974b8a592
commit b6e446cb58
7 changed files with 189 additions and 0 deletions

View File

@ -2480,6 +2480,42 @@
"HAVE_TF (trunctfsf2)"
{ EXPAND_TF (trunctfsf2, 2); })
(define_expand "trunctf<DFP_ALL:mode>2_vr"
[(match_operand:DFP_ALL 0 "nonimmediate_operand" "")
(match_operand:TF 1 "nonimmediate_operand" "")]
"TARGET_HARD_DFP
&& GET_MODE_SIZE (TFmode) > GET_MODE_SIZE (<DFP_ALL:MODE>mode)
&& TARGET_VXE"
{
rtx fprx2 = gen_reg_rtx (FPRX2mode);
emit_insn (gen_tf_to_fprx2 (fprx2, operands[1]));
emit_insn (gen_truncfprx2<DFP_ALL:mode>2 (operands[0], fprx2));
DONE;
})
(define_expand "trunctf<DFP_ALL:mode>2"
[(match_operand:DFP_ALL 0 "nonimmediate_operand" "")
(match_operand:TF 1 "nonimmediate_operand" "")]
"HAVE_TF (trunctf<DFP_ALL:mode>2)"
{ EXPAND_TF (trunctf<DFP_ALL:mode>2, 2); })
(define_expand "trunctdtf2_vr"
[(match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:TD 1 "nonimmediate_operand" "")]
"TARGET_HARD_DFP && TARGET_VXE"
{
rtx fprx2 = gen_reg_rtx (FPRX2mode);
emit_insn (gen_trunctdfprx22 (fprx2, operands[1]));
emit_insn (gen_fprx2_to_tf (operands[0], fprx2));
DONE;
})
(define_expand "trunctdtf2"
[(match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:TD 1 "nonimmediate_operand" "")]
"HAVE_TF (trunctdtf2)"
{ EXPAND_TF (trunctdtf2, 2); })
; load lengthened
(define_insn "extenddftf2_vr"
@ -2511,6 +2547,42 @@
"HAVE_TF (extendsftf2)"
{ EXPAND_TF (extendsftf2, 2); })
(define_expand "extend<DFP_ALL:mode>tf2_vr"
[(match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:DFP_ALL 1 "nonimmediate_operand" "")]
"TARGET_HARD_DFP
&& GET_MODE_SIZE (<DFP_ALL:MODE>mode) < GET_MODE_SIZE (TFmode)
&& TARGET_VXE"
{
rtx fprx2 = gen_reg_rtx (FPRX2mode);
emit_insn (gen_extend<DFP_ALL:mode>fprx22 (fprx2, operands[1]));
emit_insn (gen_fprx2_to_tf (operands[0], fprx2));
DONE;
})
(define_expand "extend<DFP_ALL:mode>tf2"
[(match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:DFP_ALL 1 "nonimmediate_operand" "")]
"HAVE_TF (extend<DFP_ALL:mode>tf2)"
{ EXPAND_TF (extend<DFP_ALL:mode>tf2, 2); })
(define_expand "extendtftd2_vr"
[(match_operand:TD 0 "nonimmediate_operand" "")
(match_operand:TF 1 "nonimmediate_operand" "")]
"TARGET_HARD_DFP && TARGET_VXE"
{
rtx fprx2 = gen_reg_rtx (FPRX2mode);
emit_insn (gen_tf_to_fprx2 (fprx2, operands[1]));
emit_insn (gen_extendfprx2td2 (operands[0], fprx2));
DONE;
})
(define_expand "extendtftd2"
[(match_operand:TD 0 "nonimmediate_operand" "")
(match_operand:TF 1 "nonimmediate_operand" "")]
"HAVE_TF (extendtftd2)"
{ EXPAND_TF (extendtftd2, 2); })
; test data class
(define_expand "signbittf2_vr"

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
#include <stdint.h>
__attribute__ ((noipa)) static long double
long_double_from_decimal128 (_Decimal128 x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_from_decimal128 ((_Decimal128) 42) == 42.L);
assert (long_double_from_decimal128 ((_Decimal128) -42) == -42.L);
}

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
#include <stdint.h>
__attribute__ ((noipa)) static long double
long_double_from_decimal32 (_Decimal32 x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_from_decimal32 ((_Decimal32) 42) == 42.L);
assert (long_double_from_decimal32 ((_Decimal32) -42) == -42.L);
}

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
#include <stdint.h>
__attribute__ ((noipa)) static long double
long_double_from_decimal64 (_Decimal64 x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_from_decimal64 ((_Decimal64) 42) == 42.L);
assert (long_double_from_decimal64 ((_Decimal64) -42) == -42.L);
}

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
__attribute__ ((noipa)) static _Decimal128
long_double_to_decimal128 (long double x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_to_decimal128 (42.L) == (_Decimal128) 42.);
assert (long_double_to_decimal128 (-42.L) == (_Decimal128) -42.);
}

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
__attribute__ ((noipa)) static _Decimal32
long_double_to_decimal32 (long double x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_to_decimal32 (42.L) == (_Decimal32) 42.);
assert (long_double_to_decimal32 (-42.L) == (_Decimal32) -42.);
}

View File

@ -0,0 +1,19 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=z14 -mzarch --save-temps" } */
/* { dg-do run { target { s390_z14_hw } } } */
#include <assert.h>
__attribute__ ((noipa)) static _Decimal64
long_double_to_decimal64 (long double x)
{
return x;
}
/* { dg-final { scan-assembler-times {\n\tpfpo\n} 1 } } */
int
main (void)
{
assert (long_double_to_decimal64 (42.L) == (_Decimal64) 42.);
assert (long_double_to_decimal64 (-42.L) == (_Decimal64) -42.);
}