IBM Z: Fix long double <-> DFP conversions
authorIlya Leoshkevich <iii@linux.ibm.com>
Wed, 17 Feb 2021 13:40:03 +0000 (14:40 +0100)
committerIlya Leoshkevich <iii@linux.ibm.com>
Sat, 20 Feb 2021 00:49:35 +0000 (01:49 +0100)
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.

gcc/config/s390/vector.md
gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal128.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal32.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal64.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal128.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal32.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal64.c [new file with mode: 0644]

index e48c965db0024454f248290713ead5f59df586eb..bc52211c55e5f7c7a568bd7593a1ba6abd2c6878 100644 (file)
   "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"
   "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"
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal128.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal128.c
new file mode 100644 (file)
index 0000000..3cd2c68
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal32.c
new file mode 100644 (file)
index 0000000..84e3c4b
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-from-decimal64.c
new file mode 100644 (file)
index 0000000..f855e4b
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal128.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal128.c
new file mode 100644 (file)
index 0000000..5f7833a
--- /dev/null
@@ -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.);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal32.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal32.c
new file mode 100644 (file)
index 0000000..f09288a
--- /dev/null
@@ -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.);
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal64.c b/gcc/testsuite/gcc.target/s390/vector/long-double-to-decimal64.c
new file mode 100644 (file)
index 0000000..08aecfe
--- /dev/null
@@ -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.);
+}