https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105376

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to jos...@codesourcery.com from comment #3)
> For this transformation to be correct for DFP, you need a 2 with quantum 
> exponent 0.  Converting from either integer or binary floating-point 2 
> will work for that.  However, I note that decimal_to_decnumber has
> 
>     case rvc_normal:
>       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.  */
> 
> so the existing code ought to work as-is.  Maybe there is a problem with 
> padding in REAL_VALUE_TYPE meaning the comparisons don't work as intended?

It ends up as -dconst2 in the end which isn't handled.

(gdb) p *r
$1 = {cl = 1, decimal = 0, sign = 1, signalling = 0, canonical = 0, uexp = 2, 
  sig = {0, 0, 9223372036854775808}}
(gdb) p dconst2
$2 = {cl = 1, decimal = 0, sign = 0, signalling = 0, canonical = 0, uexp = 2, 
  sig = {0, 0, 9223372036854775808}}

So the initial transform of x+x to 2.*x is "OK" in that this "wrong" 2.
is handled but followup transforms rely on 2. being correct, specifically
fold_negate_const just does

    case REAL_CST:
      t = build_real (type, real_value_negate (&TREE_REAL_CST (arg0)));
      break;

without considering that the TREE_REAL_CST isn't appropriate for 'type'.

It looks like using build_real_truncate instead of build_real works as well,
so that's what I am going to do for this PR.  There's a lot of
'build_real .*dconst' in match.pd that would need a similar fix so I wonder
if build_real should special-case those or if we should get rid of the
dconst* REAL_VALUE_TYPE and instead use an overload from int using a
more fancy way of caching.

diff --git a/gcc/match.pd b/gcc/match.pd
index 6d691d302b3..663dccf3289 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3865,7 +3865,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (simplify
  (plus @0 @0)
  (if (SCALAR_FLOAT_TYPE_P (type))
-  (mult @0 { build_real (type, dconst2); })
+  (mult @0 { build_real_truncate (type, dconst2); })
   (if (INTEGRAL_TYPE_P (type))
    (mult @0 { build_int_cst (type, 2); }))))

Reply via email to