User account creation filtered due to spam.

Bug 47990 - Missed promotion of double precision constants to single precision for -funsafe-math-optimizations
Summary: Missed promotion of double precision constants to single precision for -funsa...
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2011-03-04 14:42 UTC by Richard Biener
Modified: 2011-08-01 13:07 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2011-03-04 14:42:27 UTC
In 482.sphinx3 we have code like

float foo (float x, float y)
{
  return ((int)(x/y + 0.5)) * y;
}

where the addition of 0.5 is performed in double precision.  With
-funsafe-math-optimizations we can demote 0.5 to single precision
(its exactly representable) also because the result of the addition
does not take part of further floating point computation but is
immediately converted to int.

The unsafe part of this optimization occurs when x/y is FLT_MAX
and we'd truncate to a 64bit integer type.  For 32bit integers
it would probably be safe to do this optimization unconditionally.
Comment 1 joseph@codesourcery.com 2011-03-04 15:42:39 UTC
On Fri, 4 Mar 2011, rguenth at gcc dot gnu.org wrote:

> In 482.sphinx3 we have code like
> 
> float foo (float x, float y)
> {
>   return ((int)(x/y + 0.5)) * y;
> }
> 
> where the addition of 0.5 is performed in double precision.  With
> -funsafe-math-optimizations we can demote 0.5 to single precision
> (its exactly representable) also because the result of the addition
> does not take part of further floating point computation but is
> immediately converted to int.
> 
> The unsafe part of this optimization occurs when x/y is FLT_MAX
> and we'd truncate to a 64bit integer type.  For 32bit integers
> it would probably be safe to do this optimization unconditionally.

No, that's not safe unconditionally; consider x/y == 0x800001p0f, for 
example (so adding 0.5f and converting to float results in rounding up to 
the next integer in the default round-to-nearest mode, whereas conversion 
from floating point to integer in C always rounds towards zero).
Comment 2 Richard Biener 2011-08-01 13:07:00 UTC
The intel compiler does not perform this optimization even at -fast.  It does
perform the demotion on

float foo (float x, float y)
{
  return (int)((float)(x/y + 0.5)) * y;
}

though, even with default optimization (also with the conversion to
int removed or associated to apply to the first operand of the
multiplication only).

So they leave alone what looks like a usual "rounding" pattern.

My original idea was to fold (int)((double)(x/y) + 0.5) to (int)(x/y + 0.5f),
similar to (float)((double)(x/y) + 0.5) to (x/y + 0.5f) which we already
do (at -O0, in convert_to_real).