[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-15 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #8 from Richard Biener  ---
https://sourceware.org/bugzilla/show_bug.cgi?id=24346

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-15 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

Richard Biener  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |MOVED

--- Comment #7 from Richard Biener  ---
(In reply to jos...@codesourcery.com from comment #6)
> On Thu, 14 Mar 2019, rguenther at suse dot de wrote:
> 
> > I see.  This means the different cases in the testcase in question are
> > not equivalent (when excess precision is involved) and thus the
> > expectation that they produce the same value is wrong which means the
> > bug is INVALID?
> 
> Yes.  With, again, the question of whether glibc should be avoiding 
> returning with excess precision from log and other libm functions (where 
> at present it only tries to avoid excess range, and excess precision for 
> fully-determined IEEE functions such as sqrt).

OK, so there's no GCC bug but forcing the glibc result to double "fixes"
the issue.  I'll re-file a glibc bug then.  For reference, the following
works as intended:

#include 
#include 

int main(int argc, char **argv)
{
  double p = 0.00053447623258905705;
  double inv_log_of_base = 1.41668185;

  volatile double lg = log(p);
  int r = lg * inv_log_of_base;
  printf("a: %d\n", r);

  double gr = log(p) * inv_log_of_base;
  printf("b: %g\n", gr);

  double g = log(p);
  int c = g * inv_log_of_base;
  printf("c: %d\n", c);

  return 0;
}

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-14 Thread joseph at codesourcery dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #6 from joseph at codesourcery dot com  ---
On Thu, 14 Mar 2019, rguenther at suse dot de wrote:

> I see.  This means the different cases in the testcase in question are
> not equivalent (when excess precision is involved) and thus the
> expectation that they produce the same value is wrong which means the
> bug is INVALID?

Yes.  With, again, the question of whether glibc should be avoiding 
returning with excess precision from log and other libm functions (where 
at present it only tries to avoid excess range, and excess precision for 
fully-determined IEEE functions such as sqrt).

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-14 Thread rguenther at suse dot de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #5 from rguenther at suse dot de  ---
On Wed, 13 Mar 2019, joseph at codesourcery dot com wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573
> 
> --- Comment #4 from joseph at codesourcery dot com  dot com> ---
> On Mon, 11 Mar 2019, rguenth at gcc dot gnu.org wrote:
> 
> > > I wouldn't expect such a cast to be generated on the result of the 
> > > multiplication; I'd expect long double to be converted directly to int.  
> > > There is, indeed, a test of that (see test_cast in 
> > > gcc.target/i386/excess-precision-1.c).
> > 
> > Exactly why?  The multiplication result has excess precision here.
> > Do you say an extra rounding step to double precision cannot change
> > the conversion to integer result or do you say such extra rounding step
> > isn't allowed here?  IMHO this is exactly the "issue" pointed out by
> > the testcase.
> 
> The extra rounding step isn't allowed by the language semantics as I 
> understand them.  The result of the double multiplication is represented 
> with the range and precision of long double and must be converted directly 
> to int, not to double and then to int.

I see.  This means the different cases in the testcase in question are
not equivalent (when excess precision is involved) and thus the
expectation that they produce the same value is wrong which means the
bug is INVALID?

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-13 Thread joseph at codesourcery dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #4 from joseph at codesourcery dot com  ---
On Mon, 11 Mar 2019, rguenth at gcc dot gnu.org wrote:

> > I wouldn't expect such a cast to be generated on the result of the 
> > multiplication; I'd expect long double to be converted directly to int.  
> > There is, indeed, a test of that (see test_cast in 
> > gcc.target/i386/excess-precision-1.c).
> 
> Exactly why?  The multiplication result has excess precision here.
> Do you say an extra rounding step to double precision cannot change
> the conversion to integer result or do you say such extra rounding step
> isn't allowed here?  IMHO this is exactly the "issue" pointed out by
> the testcase.

The extra rounding step isn't allowed by the language semantics as I 
understand them.  The result of the double multiplication is represented 
with the range and precision of long double and must be converted directly 
to int, not to double and then to int.

> Note the frontend _does_ originally emit (int) (double) ((long double) log (p)
> * (long double) inv_log_of_base) but the conversion to double is elided

The front end should not be emitting such a conversion to double.  An 
EXCESS_PRECISION_EXPR is not a conversion (and convert_for_assignment 
removes an EXCESS_PRECISION_EXPR very early, before converting to the 
desired type).

> by convert_to_real in the code piece I qouted.

The truncation to double should not be removed because it should fail the 
real_can_shorten_arithmetic test, as well as failing the 
!excess_precision_type (newtype) test (the former is testing whether 
removing such a truncation is valid in the sense of not affecting the 
result, the latter is testing whether the change of type for arithmetic 
would run into the back end not actually having proper arithmetic 
operations for the narrower type).

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-11 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #3 from Richard Biener  ---
(In reply to jos...@codesourcery.com from comment #2)
> On Mon, 4 Mar 2019, rguenth at gcc dot gnu.org wrote:
> 
> > where the first result is off.  The IL looks like
> > 
> > int r = (int) ((long double) log (p) * (long double) inv_log_of_base);
> > 
> > where possibly the missing cast to (double) is elided by bogus optimization
> > (didn't try to track down the issue yet).
> 
> What missing cast to double?
> 
> I wouldn't expect such a cast to be generated on the result of the 
> multiplication; I'd expect long double to be converted directly to int.  
> There is, indeed, a test of that (see test_cast in 
> gcc.target/i386/excess-precision-1.c).

Exactly why?  The multiplication result has excess precision here.
Do you say an extra rounding step to double precision cannot change
the conversion to integer result or do you say such extra rounding step
isn't allowed here?  IMHO this is exactly the "issue" pointed out by
the testcase.

Note the frontend _does_ originally emit (int) (double) ((long double) log (p)
* (long double) inv_log_of_base) but the conversion to double is elided
by convert_to_real in the code piece I qouted.

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-11 Thread joseph at codesourcery dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

--- Comment #2 from joseph at codesourcery dot com  ---
On Mon, 4 Mar 2019, rguenth at gcc dot gnu.org wrote:

> where the first result is off.  The IL looks like
> 
> int r = (int) ((long double) log (p) * (long double) inv_log_of_base);
> 
> where possibly the missing cast to (double) is elided by bogus optimization
> (didn't try to track down the issue yet).

What missing cast to double?

I wouldn't expect such a cast to be generated on the result of the 
multiplication; I'd expect long double to be converted directly to int.  
There is, indeed, a test of that (see test_cast in 
gcc.target/i386/excess-precision-1.c).

You could argue about whether the result of log should be converted to 
double (the GCC IR is unable to represent that a function might return a 
result with excess range and precision, as far as it's concerned the 
return value of log is always representable in double) - but if the issue 
is with the return value of log, that would be a glibc issue, where maybe 
glibc should avoid excess precision in return values (currently it only 
does so for functions with exactly determined IEEE results, and otherwise 
acts to avoid excess range but not excess precision in return values).  In 
the presence of Annex F a function defined by the user cannot return with 
excess range or precision, but that may not apply to standard library 
functions which don't need to behave as if written in standard C.

convert_to_real_1 has a detailed check for when conversions can be removed 
(see the "Sometimes this transformation is safe" comment), but that 
shouldn't be relevant here (it's cases like (float)((double)float * 
(double)float) where removing conversions is safe).

[Bug c/89573] -fexcess-precision=standard doesn't work for conversion to integer of multiplication

2019-03-04 Thread rguenth at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89573

Richard Biener  changed:

   What|Removed |Added

 CC||jsm28 at gcc dot gnu.org

--- Comment #1 from Richard Biener  ---
The FE correctly builds

<<< Unknown tree: excess_precision_expr
  (long double) __builtin_log (p) * (long double) inv_log_of_base >>>

but then convert_for_assignment seems to elide via convert_to_real_1:

/* Convert (outertype)((innertype0)a+(innertype1)b)
   into ((newtype)a+(newtype)b) where newtype
   is the widest mode from all of these.  */
304 case PLUS_EXPR:
305 case MINUS_EXPR:
306 case MULT_EXPR:
307 case RDIV_EXPR:
308{
309  tree arg0 = strip_float_extensions (TREE_OPERAND (expr,
0));
310  tree arg1 = strip_float_extensions (TREE_OPERAND (expr,
1));

where strip_float_extensions makes the comment not true (because we ignore
the casts to long double).

Maybe the code in convert_and_check

1627  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
1628{
1629  tree orig_type = TREE_TYPE (expr);
1630  expr = TREE_OPERAND (expr, 0);
1631  expr_for_warning = convert (orig_type, expr);
1632  if (orig_type == type)
1633return expr_for_warning;

shouldn't use convert here but convert_to_real_1 with fold_p = false?
But then other code may simply elide the conversions (can we really
ignore the extra rounding performed by the outer truncating conversion, ever?)