aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-11 07:47:47 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-11 07:47:47 +0000
commit5a86d7542dd5dbf676a035eae4c76403eb074efa (patch)
tree254ab4ee7a6889e3d64870fd698a290702b4a966
parent2a2264529ea78519946e4e573e85226c0521ce45 (diff)
S/390: Fix rounding for _Decimal128 to _Decimal32 conversion
We do not have a direct conversion instruction from 128 bit DFP to 32 bit DFP so this needs to be done in two steps. The first needs to be done with the "prepare for shorter precision rounding mode" in order to produce a correct result. gcc/ChangeLog: 2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com> * config/s390/s390.md ("trunctddd2"): Turn former define_insn into define_expand. ("*trunctddd2"): New pattern definition. ("trunctdsd2"): Set prep_for_short_prec rounding mode for the TD->DD truncation. gcc/testsuite/ChangeLog: 2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com> * gcc.target/s390/dfp-1.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@234134 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/s390/s390.md17
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/s390/dfp-1.c23
4 files changed, 49 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0cfc1e2eadd..6e85072e916 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+ * config/s390/s390.md ("trunctddd2"): Turn former define_insn into
+ define_expand.
+ ("*trunctddd2"): New pattern definition.
+ ("trunctdsd2"): Set prep_for_short_prec rounding mode for the
+ TD->DD truncation.
+
+2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
* config/s390/s390.md (BFP_RND_*, DFP_RND_*): Add new constant
definitions for BFP and DFP rounding modes.
("fixuns_truncdddi2", "fixuns_trunctddi2")
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 185a3f8511b..5a9f1c8a606 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -4847,12 +4847,22 @@
; trunctddd2 and truncddsd2 instruction pattern(s).
;
-(define_insn "trunctddd2"
+
+(define_expand "trunctddd2"
+ [(parallel
+ [(set (match_operand:DD 0 "register_operand" "")
+ (float_truncate:DD (match_operand:TD 1 "register_operand" "")))
+ (unspec:DI [(const_int DFP_RND_CURRENT)] UNSPEC_ROUND)
+ (clobber (scratch:TD))])]
+ "TARGET_HARD_DFP")
+
+(define_insn "*trunctddd2"
[(set (match_operand:DD 0 "register_operand" "=f")
(float_truncate:DD (match_operand:TD 1 "register_operand" "f")))
- (clobber (match_scratch:TD 2 "=f"))]
+ (unspec:DI [(match_operand:DI 2 "const_mask_operand" "I")] UNSPEC_ROUND)
+ (clobber (match_scratch:TD 3 "=f"))]
"TARGET_HARD_DFP"
- "ldxtr\t%2,0,%1,0\;ldr\t%0,%2"
+ "ldxtr\t%3,%2,%1,0\;ldr\t%0,%3"
[(set_attr "length" "6")
(set_attr "type" "ftruncdd")])
@@ -4868,6 +4878,7 @@
[(parallel
[(set (match_dup 3)
(float_truncate:DD (match_operand:TD 1 "register_operand" "")))
+ (unspec:DI [(const_int DFP_RND_PREP_FOR_SHORT_PREC)] UNSPEC_ROUND)
(clobber (match_scratch:TD 2 ""))])
(set (match_operand:SD 0 "register_operand" "")
(float_truncate:SD (match_dup 3)))]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index be04568f5dd..254b6bccff3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ * gcc.target/s390/dfp-1.c: New test.
+
2016-03-10 Nick Clifton <nickc@redhat.com>
PR target/70044
diff --git a/gcc/testsuite/gcc.target/s390/dfp-1.c b/gcc/testsuite/gcc.target/s390/dfp-1.c
new file mode 100644
index 00000000000..109d9fb63f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/dfp-1.c
@@ -0,0 +1,23 @@
+/* We do not have a direct conversion instruction from 128 bit DFP to
+ 32 bit DFP so this needs to be done in two steps. The first needs
+ to be done with the "prepare for shorter precision rounding mode"
+ in order to produce a correct result. Otherwise the 8th digit of
+ the number will change from 4 to 5 in the first rounding step which
+ then will turn the last digit of the 32 bit DFP number (the 3) into
+ a 4. Although with direct rounding it would stay a 3. */
+
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch" } */
+
+_Decimal32 __attribute__((noinline))
+foo (_Decimal128 a)
+{
+ return (_Decimal32)a;
+}
+
+int
+main ()
+{
+ if (foo (1.23456349999999999DL) != 1.234563DF)
+ __builtin_abort ();
+}