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.