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

Oleg Endo <olegendo at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |olegendo at gcc dot gnu.org
   Last reconfirmed|                            |2025-05-11
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Oleg Endo <olegendo at gcc dot gnu.org> ---
(In reply to Paul Cercueil from comment #0)
> With the following code compiled at -Os:
> 
> float sh4_floorf(float x) {
>     float x2 = (float)(int)x;
> 
>     if (x < -1.0f)
>         x2 += -1.0f;
> 
>     return x2;
> }
> 
> GCC generates:
> 
> _sh4_floorf:
>         mova    .L6,r0
>         fmov.s  @r0+,fr1
>         ftrc    fr5,fpul
>         fcmp/gt fr5,fr1
>         bf/s    .L5
>         float   fpul,fr0
>         fldi1   fr1
>         fsub    fr1,fr0
> .L5:
>         rts     
>         nop
> .L6:
>         .long   -1082130432
> 
> Notice how the 1.0f constant is loaded from .L6 using mova + fmov.s, while
> it could be loaded using fldi1 directly.

The test case is somewhat bogus.  Changing the "-1.0f" to "1.0f" will generate
the "fldi1" instruction for the comparison as well.

Based on our previous discussion, I guess you'd expect this case to generate
the sequence "fldi1; fneg" to load the constant -1.0, which would be better in
this case.


> The compiler also does not seem to understand that fr1 contains -1.0f which
> it can add to fr0 directly, and instead it will load 1.0f with fldi1 this
> time and substract it to fr0.

That's because there are two constants in your case "-1" and "1".

If the test case is changed to 

    if (x < -2.0f)
        x2 *= -2.0f;

... then we will see that constants are shared in registers.

Reply via email to