Patchwork Fix dfp issue with dconst{1,2,m1,half} (PR debug/48928)

login
register
mail settings
Submitter Jakub Jelinek
Date May 9, 2011, 7:11 p.m.
Message ID <20110509191159.GX17079@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/94918/
State New
Headers show

Comments

Jakub Jelinek - May 9, 2011, 7:11 p.m.
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  <jakub@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.


	Jakub

Patch

--- 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;
+}