Hi!

The folder/middle-end/tree passes/rtl passes apparently use
dconst{1,2,m1,half} and/or const_tiny_rtx[{1,2}][{S,D,T}Dmode]
in various places.  E.g.
          /* Convert x+x into x*2.0.  */
          if (operand_equal_p (arg0, arg1, 0)
              && SCALAR_FLOAT_TYPE_P (type))
            return fold_build2_loc (loc, MULT_EXPR, type, arg0,
                                    build_real (type, dconst2));
Unfortunately, dconst{1,2,m1,half} are binary REAL_FORMATs, not decimal.
In most places real.c or dfp.c just converts constants to decimal,
but when doing decimal_to_decnumber on such constants it fails with an
assertion failure.
While we perhaps could add code to handle decimal stuff in all places
where dconst{1,2,m1,half} is mentioned, say create dconstdfp{1,2,m1,half},
I think it would just make all the code harder to maintain, so instead
of that this patch just magically converts those binary tiny predefined
constants to decimal.  Instead of calling decimal_from_binary
which converts it to string and then from string back to dn the patch
just converts strings to dn.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-05-09  Jakub Jelinek  <ja...@redhat.com>

        PR debug/48928
        * dfp.c (decimal_to_decnumber): Handle conversion from
        dconst{1,2,m1,half}.

        * gcc.dg/dfp/pr48928.c: New test.

--- gcc/dfp.c.jj        2010-12-02 11:51:32.000000000 +0100
+++ gcc/dfp.c   2011-05-09 11:08:43.000000000 +0200
@@ -110,7 +110,33 @@ decimal_to_decnumber (const REAL_VALUE_T
         decNumberFromString (dn, "nan", &set);
       break;
     case rvc_normal:
-      gcc_assert (r->decimal);
+      if (!r->decimal)
+       {
+         /* dconst{1,2,m1,half} are used in various places in
+            the middle-end and optimizers, allow them here
+            as an exception by converting them to decimal.  */
+         if (memcmp (r, &dconst1, sizeof (*r)) == 0)
+           {
+             decNumberFromString (dn, "1", &set);
+             break;
+           }
+         if (memcmp (r, &dconst2, sizeof (*r)) == 0)
+           {
+             decNumberFromString (dn, "2", &set);
+             break;
+           }
+         if (memcmp (r, &dconstm1, sizeof (*r)) == 0)
+           {
+             decNumberFromString (dn, "-1", &set);
+             break;
+           }
+         if (memcmp (r, &dconsthalf, sizeof (*r)) == 0)
+           {
+             decNumberFromString (dn, "0.5", &set);
+             break;
+           }
+         gcc_unreachable ();
+       }
       decimal128ToNumber ((const decimal128 *) r->sig, dn);
       break;
     default:
--- gcc/testsuite/gcc.dg/dfp/pr48928.c.jj       2011-05-09 11:23:59.000000000 
+0200
+++ gcc/testsuite/gcc.dg/dfp/pr48928.c  2011-05-09 11:23:24.000000000 +0200
@@ -0,0 +1,10 @@
+/* PR debug/48928 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2" } */
+
+_Decimal32
+foo (_Decimal32 x)
+{
+  _Decimal32 y = (x + x) / (9.DF * x);
+  return y;
+}

        Jakub

Reply via email to