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.