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