Bug 31227 - The value of cos varies with different optimization levels
Summary: The value of cos varies with different optimization levels
Status: RESOLVED NOTABUG
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.28
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-10 01:20 UTC by Kenny
Modified: 2024-01-11 03:20 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kenny 2024-01-10 01:20:49 UTC
I wrote a test case test_cos.c, the context of file test_cos.c as following:

#include <stdio.h>
#include <math.h>

static double dcos(double arg1)
{
    return cos(arg1);
}

int main()
{
    double d = 17.14159265;
    volatile double c = dcos(d);

    printf("cos(d) = %.17f %llx\n", c, *(long long*)&c);

    return 0;
}

When we compiled with different optimization levels, we got different results: 
[root@localhost tmp]# gcc -o test_cos -lm -O test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]# gcc -o test_cos -lm -O0 test_cos.c && ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a
[root@localhost tmp]# gcc -o test_cos -lm -O1 test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]# gcc -o test_cos -lm -O2 test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]# gcc -o test_cos -lm -O3 test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b

When I embed cos in my large program and compile it with -O2 I get the same result as here with -O0
Comment 1 Andreas Schwab 2024-01-10 09:38:06 UTC
When compiling with optimisation the compiler expands the call to cos into a constant, using its own implementation to compute the result.  The difference of one ULP between different implementations is well within the expected bounds.  You can use -fno-builtin-cos to force the use of the implementation in libm.
Comment 2 Kenny 2024-01-11 03:20:25 UTC
(In reply to Andreas Schwab from comment #1)
> When compiling with optimisation the compiler expands the call to cos into a
> constant, using its own implementation to compute the result.  The
> difference of one ULP between different implementations is well within the
> expected bounds.  You can use -fno-builtin-cos to force the use of the
> implementation in libm.

I added -fno-builtin-cos according to your instructions and conducted the test again, and found that the result became stable, but the result of ARM platform was different from that of X86 platform. Is this expected? 

the glibc version of ARM is 2.28, but the X86 is 2.17

[root@localhost tmp]# uname -a
Linux localhost.localdomain 4.19.90-23.32.v2101.ky10.aarch64 #1 SMP Fri
Feb 24 10:12:55 CST 2023 aarch64 aarch64 aarch64 GNU/Linux
[root@localhost tmp]# gcc -o test_cos -lm -g -fno-builtin-cos test_cos.c
&& ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a
[root@localhost tmp]# gcc -o test_cos -lm -g -O -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a
[root@localhost tmp]# gcc -o test_cos -lm -g -O1 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a
[root@localhost tmp]# gcc -o test_cos -lm -g -O2 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a
[root@localhost tmp]# gcc -o test_cos -lm -g -O3 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390940 bfc1809af3cf9a1a

[root@localhost tmp]#  uname -a
Linux xiaozhong-wang 3.10.0-1160.102.1.el7.x86_64 #1 SMP Tue Oct 17
15:42:21 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost tmp]#  gcc -o test_cos -lm -g -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]#  gcc -o test_cos -lm -g -O -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]#  gcc -o test_cos -lm -g -O1 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]#  gcc -o test_cos -lm -g -O2 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b
[root@localhost tmp]#  gcc -o test_cos -lm -g -O3 -fno-builtin-cos
test_cos.c && ./test_cos
cos(d) = -0.13673722176390943 bfc1809af3cf9a1b