On Fri, Mar 21, 2025 at 08:25:10PM +0100, Richard Biener wrote:
> > --- gcc/cobol/parse.y.jj    2025-03-21 17:49:43.571440176 +0100
> > +++ gcc/cobol/parse.y       2025-03-21 20:15:24.852414777 +0100
> > @@ -4331,7 +4331,8 @@ value_clause:   VALUE all LITERAL[lit] {
> >                    cbl_field_t *field = current_field();
> >                    auto orig_str = original_number();
> >               REAL_VALUE_TYPE orig_val;
> > -             real_from_string (&orig_val, orig_str);
> > +             real_from_string3 (&orig_val, orig_str,
> > +                                TYPE_MODE (float128_type_node));
> >                    char *initial = NULL;
> >  
> >                    if( real_identical (&orig_val, &$value) ) {
> > @@ -6922,7 +6923,8 @@ cce_expr:       cce_factor
> >  cce_factor:     NUMSTR {
> >                    /* ???  real_from_string does not allow arbitrary radix. 
> >  */
> >                    // $$ = numstr2i($1.string, $1.radix);
> > -             real_from_string (&$$, $1.string);
> > +             real_from_string3 (&$$, $1.string,
> > +                                TYPE_MODE (float128_type_node));
> >                  }
> >                  ;
> >  
> > 
> > The old code was just using _Float128 which has the IEEE quad precision,
> > but REAL_VALUE_TYPE in GCC actually has larger internal precision than that,
> > so if it isn't rounded to the IEEE quad precision first and builds REAL_CST,
> > it isn't the expected 0.0100000000000000000000000000000000002 but
> > 0.009999999999...

Without real_from_string3 (or real_from_string + real_convert, the former is
just a shorthand for that) you can have excess precision in the stored
REAL_VALUE_TYPE, which certainly can't then match what happens when the FE
uses _Float128 directly.

> we've come from initial_from_float128 which does
> 
>       REAL_VALUE_TYPE pow10
>         = real_powi10 (field->data.digits + field->data.rdigits);
>       real_arithmetic (&value, MULT_EXPR, &value, &pow10);
> 
> which produces the 1.0e+0 - do I need to process this to be "normal"?

That real_arithmetic is also supposed to be followed by real_convert,
otherwise again there is an excess precision.  That could be desirable at
times but certainly not if it attempts to work the same as former
_Float128 *= __int128.
Because that computation also rounds.

When fold-const.cc calls real_arithmetic, it does that as well:
      inexact = real_arithmetic (&value, code, &d1, &d2);
      real_convert (&result, mode, &value);

        Jakub

Reply via email to