Created attachment 47071 [details]
Test source and build script
Dear GCC team,
we've found that the usage of GCCs builtin rint() or rintf() functions on x86_64 platforms, as are introduced with optimization -O1 and above results in a change of the runtime result of those functions.
When compiling the attached testprogram with "-O0" or using "-O1 -fno-builtin-rint" the results are as expected as defined by the API. Using GCCs builtin some of the results differ from the expected values.
It seems operations using FE_DOWNWARD and FE_UPWARD are behaving contrarily for negative floating point inputs to rint/rintf using builtin rint functions, resulting in the wrongly rounded value.
The behaviour was reproduced on x86_64 platforms Ubuntu Linux 19.10, MSys2 and bare metal x86_64 toolchains with GCC compilers 8.2, 9.1, 9.2.1.
Please find attached the bzipped test program (rinttest.tar.bz2), including build.sh script to compile and run. This should provide a similar output as in attached text file (rinttest_output.txt).
Please let me know if I can assist any further.
Created attachment 47072 [details]
Test result output text.
Did you compile with -frounding-math?
Thanks for the quick reply.
Just tested using -frounding-math and it seems to fix the issue.
Sorry, I was not aware of this option, according to GCCs manual it is experimental.
Please correct me if I'm wrong, but my expectation would be, assuming a correct program, switching from -O0 to -O1 should not influence the runtime result.
(In reply to Steffen Schmidt from comment #3)
> Thanks for the quick reply.
> Just tested using -frounding-math and it seems to fix the issue.
> Sorry, I was not aware of this option, according to GCCs manual it is
> Please correct me if I'm wrong, but my expectation would be, assuming a
> correct program, switching from -O0 to -O1 should not influence the runtime
GCC assumes you do not mess with the floating-point state but round-to-nearest
is in effect. You have to use -frounding-math to remove this assumption but
then still correct operation isn't guaranteed (thus the "experimental" tag
for this option).
Note that if GCC would be standards-conforming here your program would still need
#pragma STDC FENV_ACCESS ON
since you are accessing and modifying the floating-point state (where the
pragma has no effect for GCC)
See PR34678 for issues of -frounding-math.
So it works (with -frounding-math), closing.