Bug 92164 - Wrong result using builtin rint/rintf optimization in x86_64
Summary: Wrong result using builtin rint/rintf optimization in x86_64
Status: RESOLVED WORKSFORME
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 9.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2019-10-21 10:58 UTC by Steffen Schmidt
Modified: 2021-10-28 13:56 UTC (History)
1 user (show)

See Also:
Host: x86_64-linux-gnu, x86_64-pc-elf, x86_64-w64-mingw32
Target: x86_64-linux-gnu, x86_64-pc-elf, x86_64-w64-mingw32
Build:
Known to work:
Known to fail: 8.2.0, 9.2.0, 9.2.1
Last reconfirmed: 2020-01-29 00:00:00


Attachments
Test source and build script (1.18 KB, application/x-bzip)
2019-10-21 10:58 UTC, Steffen Schmidt
Details
Test result output text. (240 bytes, text/plain)
2019-10-21 11:02 UTC, Steffen Schmidt
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steffen Schmidt 2019-10-21 10:58:34 UTC
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.

Best, Steffen
Comment 1 Steffen Schmidt 2019-10-21 11:02:54 UTC
Created attachment 47072 [details]
Test result output text.
Comment 2 Richard Biener 2019-10-21 11:19:26 UTC
Did you compile with -frounding-math?
Comment 3 Steffen Schmidt 2019-10-21 12:05:34 UTC
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.
Comment 4 Richard Biener 2019-10-21 13:17:02 UTC
(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
> 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.

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).
Comment 5 Richard Biener 2019-10-21 13:21:09 UTC
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)
Comment 6 Richard Biener 2019-10-21 13:22:16 UTC
See PR34678 for issues of -frounding-math.
Comment 7 Richard Biener 2021-10-28 13:56:58 UTC
So it works (with -frounding-math), closing.