public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
@ 2024-01-31  8:40 dilyan.palauzov at aegee dot org
  2024-01-31  8:44 ` [Bug target/113679] " pinskia at gcc dot gnu.org
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: dilyan.palauzov at aegee dot org @ 2024-01-31  8:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

            Bug ID: 113679
           Summary: long long minus double with gcc -m32 produces
                    different results than other compilers or gcc -m64
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dilyan.palauzov at aegee dot org
  Target Milestone: ---

diff.c is:

#include <stdio.h>
int main(void) {
  long long l = 9223372036854775806;
  double d = 9223372036854775808.0;
  printf("%f\n", (double)l - d);
  return 0;
}


With gcc (GCC) 13.2.1 20231205 (Red Hat 13.2.1-6), gcc (Ubuntu
9.4.0-1ubuntu1~20.04.2) 9.4.0, clang 16.0.4 and clang 17.0.5:

$ gcc -m64 -o diff diff.c && ./diff
0.000000
$ gcc -m32 -o diff diff.c && ./diff
-2.000000
$ clang -m64 -o diff diff.c && ./diff
0.000000
$ clang -m32 -o diff diff.c && ./diff
0.000000

With cl.exe 19.29.3015319.29.30153 (first is x84 - 32 bit, second is 64 bit)
C:\> CALL "C:\Program Files (x86)\Microsoft Visual
Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 10.0.17763.0
C:\> cl diff.c >nul 2>nul & .\diff.exe
0.000000

C:\> CALL "C:\Program Files (x86)\Microsoft Visual
Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 10.0.17763.0
C:\> cl diff.c >nul 2>nul & .\diff.exe
0.000000

gcc -m32 produces a different result, compared to gcc -m64, clang 17 (32 and
64bit), and MSCV Visual Studio 2019 (32 and 64bit).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
@ 2024-01-31  8:44 ` pinskia at gcc dot gnu.org
  2024-01-31  8:45 ` dilyan.palauzov at aegee dot org
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-01-31  8:44 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|c                           |target

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I suspect the issue is excessive precision with x87 fp.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
  2024-01-31  8:44 ` [Bug target/113679] " pinskia at gcc dot gnu.org
@ 2024-01-31  8:45 ` dilyan.palauzov at aegee dot org
  2024-01-31  8:52 ` pinskia at gcc dot gnu.org
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: dilyan.palauzov at aegee dot org @ 2024-01-31  8:45 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #2 from Дилян Палаузов <dilyan.palauzov at aegee dot org> ---
This happens only without optimizations:

$  gcc -O0 -m32 -o diff diff.c && ./diff
-2.000000
$  gcc -O1 -m32 -o diff diff.c && ./diff
0.000000
$  gcc -O2 -m32 -o diff diff.c && ./diff
0.000000
$  gcc -O3 -m32 -o diff diff.c && ./diff
0.000000

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
  2024-01-31  8:44 ` [Bug target/113679] " pinskia at gcc dot gnu.org
  2024-01-31  8:45 ` dilyan.palauzov at aegee dot org
@ 2024-01-31  8:52 ` pinskia at gcc dot gnu.org
  2024-01-31  8:53 ` jakub at gcc dot gnu.org
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-01-31  8:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |DUPLICATE

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---

[apinski@xeond2 gcc]$ ~/upstream-gcc/bin/gcc -m32  tr56.c
[apinski@xeond2 gcc]$ ./a.out
-2.000000
[apinski@xeond2 gcc]$ ~/upstream-gcc/bin/gcc -m32  tr56.c
-fexcess-precision=standard
[apinski@xeond2 gcc]$ ./a.out
0.000000
[apinski@xeond2 gcc]$ ~/upstream-gcc/bin/gcc -m32  tr56.c -msse2 -mfpmath=sse
[apinski@xeond2 gcc]$ ./a.out
0.000000


Yes it is due to excessive precision of x87. Use either
`-fexcess-precision=standard` or `-msse2 -mfpmath=sse` if you don't want to use
the execessive precision of the x87 FP.

*** This bug has been marked as a duplicate of bug 323 ***

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (2 preceding siblings ...)
  2024-01-31  8:52 ` pinskia at gcc dot gnu.org
@ 2024-01-31  8:53 ` jakub at gcc dot gnu.org
  2024-01-31  9:58 ` dilyan.palauzov at aegee dot org
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-01-31  8:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Yeah, it is, that is how excess precision behaves.
Due to the cast applying just to l rather than l - d it returns 0.0 with
-fexcess-precision=standard, but if you change it to (double)(l - d) then it
will return -2.0
at all optimization levels with -fexcess-precision=standard. 
-fexcess-precision=fast
behaves depending on what instructions are actually used and where the
conversions to float or double happen due to storing of expressions or
subexpressions into memory as documented.
If you don't like excess precision and have SSE2, you can use -msse2
-mfpmath=sse.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (3 preceding siblings ...)
  2024-01-31  8:53 ` jakub at gcc dot gnu.org
@ 2024-01-31  9:58 ` dilyan.palauzov at aegee dot org
  2024-01-31 10:02 ` pinskia at gcc dot gnu.org
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: dilyan.palauzov at aegee dot org @ 2024-01-31  9:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #5 from Дилян Палаузов <dilyan.palauzov at aegee dot org> ---
gcc -m64 -fexcess-precision=fast -o diff diff.c && ./diff
0.000000
gcc -m32 -fexcess-precision=fast -o diff diff.c && ./diff
-2.000000
clang -m32 -fexcess-precision=fast -o diff diff.c && ./diff
0.000000
clang -m64 -fexcess-precision=fast -o diff diff.c && ./diff
0.000000
gcc -m64 -fexcess-precision=standard -o diff diff.c && ./diff
0.000000
gcc -m32 -fexcess-precision=standard -o diff diff.c && ./diff
0.000000
clang -m32 -fexcess-precision=standard -o diff diff.c && ./diff
0.000000
clang -m64 -fexcess-precision=standard -o diff diff.c && ./diff
0.000000

If this excess precision has justification, why are the results different for
32 and 64bit code?  With

  printf("%f\n", (double)l - d);
  printf("%f\n", (double)(l - d));

there is indeed a difference:
$ gcc -m32 -fexcess-precision=standard -o diff diff.c && ./diff
0.000000
-2.000000

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (4 preceding siblings ...)
  2024-01-31  9:58 ` dilyan.palauzov at aegee dot org
@ 2024-01-31 10:02 ` pinskia at gcc dot gnu.org
  2024-01-31 10:26 ` jakub at gcc dot gnu.org
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-01-31 10:02 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #6 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Because 64bit uses the SSE2 fp instructions rather than x87 fp instructions.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (5 preceding siblings ...)
  2024-01-31 10:02 ` pinskia at gcc dot gnu.org
@ 2024-01-31 10:26 ` jakub at gcc dot gnu.org
  2024-01-31 14:32 ` dilyan.palauzov at aegee dot org
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-01-31 10:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
And while SSE/SSE2 has instructions for performing arithmetics in IEEE754
single and double formats, x87 does not, everything is done in extended
precision (unless the FPU is configured to use smaller precision but then it
doesn't support the extended precision long double on the other side) and
conversions to IEEE754 single/double have to be done when storing the extended
precision registers into memory.
So, it is impossible to achieve the expected IEEE754 single and double
arithmetics behavior, one can get only something close to it (but with double
rounding problems) if all the temporaries are immediately stored into memory
and loaded from it again.
The -ffloat-store option does it to a limited extent (doesn't convert
everything though), but still, the performance is terrible.
C allows extended precision and specifies how to should behave, that is the
-fexcess-precision=standard model (e.g. enabled by default for
-std=c{99,11,...} options as opposed to -std=gnu..., then it is consistently
using the excess precision with some casts/assignments mandating rounding to
lower precisions, while -fexcess-precision=fast is what gcc has been
implementing before it has been introduced, excess precision is used there as
long as something is kept in the FPU registers and conversions are done when it
needs to be spilled to memory.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (6 preceding siblings ...)
  2024-01-31 10:26 ` jakub at gcc dot gnu.org
@ 2024-01-31 14:32 ` dilyan.palauzov at aegee dot org
  2024-01-31 14:35 ` jakub at gcc dot gnu.org
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: dilyan.palauzov at aegee dot org @ 2024-01-31 14:32 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #8 from Дилян Палаузов <dilyan.palauzov at aegee dot org> ---
-fexcess-precision=standard does not ensure consistent behaviour between gcc
13.2.1 20231205 (Red Hat 13.2.1-6) and clang 17.0.5.  -msse2 -mfpmath=sse does
for diff.c:

#include <stdio.h>
#include <math.h>
int main(void) {
  long long l = 9223372036854775806;
  double d = 9223372036854775808.0;
  printf("%f\n", (double)l - d);
  printf("%i\n", pow(3.3, 4.4) == 191.18831051580915);
  return 0;
}


$ gcc -lm -fexcess-precision=standard -m32 -o diff diff.c && ./diff
0.000000
0
$ clang -lm -fexcess-precision=standard -m32 -o diff diff.c && ./diff
0.000000
1
$ gcc -lm -fexcess-precision=standard -m64 -o diff diff.c && ./diff
0.000000
1
$ clang -lm -fexcess-precision=standard -m64 -o diff diff.c && ./diff
0.000000
1
$ gcc -lm -fexcess-precision=fast -m32 -o diff diff.c && ./diff
-2.000000
1
$ clang -lm -fexcess-precision=fast -m32 -o diff diff.c && ./diff
0.000000
1
$ gcc -lm -fexcess-precision=fast -m64 -o diff diff.c && ./diff
0.000000
1
$ clang -lm -fexcess-precision=fast -m64 -o diff diff.c && ./diff
0.000000
1
$ gcc -lm -msse2 -mfpmath=sse -m32 -o diff diff.c && ./diff
0.000000
1
$ clang -lm -msse2 -mfpmath=sse -m32 -o diff diff.c && ./diff
0.000000
1
$ gcc -lm -msse2 -mfpmath=sse -m64 -o diff diff.c && ./diff
0.000000
1
$ clang -lm -msse2 -mfpmath=sse -m64 -o diff diff.c && ./diff
0.000000
1

cl.exe also prints 0.000000 and 1

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (7 preceding siblings ...)
  2024-01-31 14:32 ` dilyan.palauzov at aegee dot org
@ 2024-01-31 14:35 ` jakub at gcc dot gnu.org
  2024-01-31 14:38 ` jakub at gcc dot gnu.org
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-01-31 14:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That is not what I read from what you've posted, -fexcess-precision=standard is
consistent between the compilers, -fexcess-precision=fast is not (and doesn't
have to be), neither between different compilers, nor between different
optimization levels etc.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (8 preceding siblings ...)
  2024-01-31 14:35 ` jakub at gcc dot gnu.org
@ 2024-01-31 14:38 ` jakub at gcc dot gnu.org
  2024-01-31 15:53 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-01-31 14:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Oh, you mean the pow equality comparison.  I think you should study something
about floating point, errors, why equality comparisons of floating point values
are usually a bad idea etc.
There is no gcc bug, just bad user expectations.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (9 preceding siblings ...)
  2024-01-31 14:38 ` jakub at gcc dot gnu.org
@ 2024-01-31 15:53 ` jakub at gcc dot gnu.org
  2024-02-07  5:55 ` egallager at gcc dot gnu.org
  2024-02-10 14:32 ` dilyan.palauzov at aegee dot org
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-01-31 15:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Anyway, seems clang is buggy:
clang -O2 -m32 -mno-sse -mfpmath=387 -fexcess-precision=standard
#include <float.h>

int
main ()
{
#if FLT_EVAL_METHOD == 2 && LDBL_MANT_DIG == 64 && DBL_MANT_DIG == 53
  if ((double) 191.18831051580915 == 191.18831051580915)
    __builtin_abort ();
#endif
}
should always succeed, because if FLT_EVAL_METHOD is 2, it ought to be
evaluated
as (long double) (double) 191.18831051580915L == 191.18831051580915L and
(double) 191.18831051580915L is 0x1.7e606a3c65c95p+7 while
191.18831051580915L is 0x1.7e606a3c65c9503ap+7L, so they aren't equal.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (10 preceding siblings ...)
  2024-01-31 15:53 ` jakub at gcc dot gnu.org
@ 2024-02-07  5:55 ` egallager at gcc dot gnu.org
  2024-02-10 14:32 ` dilyan.palauzov at aegee dot org
  12 siblings, 0 replies; 14+ messages in thread
From: egallager at gcc dot gnu.org @ 2024-02-07  5:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

Eric Gallager <egallager at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |egallager at gcc dot gnu.org

--- Comment #12 from Eric Gallager <egallager at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #10)
> Oh, you mean the pow equality comparison.  I think you should study
> something about floating point, errors, why equality comparisons of floating
> point values are usually a bad idea etc.
> There is no gcc bug, just bad user expectations.

This is why gcc has the -Wfloat-equal warning flag, isn't it?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug target/113679] long long minus double with gcc -m32 produces different results than other compilers or gcc -m64
  2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
                   ` (11 preceding siblings ...)
  2024-02-07  5:55 ` egallager at gcc dot gnu.org
@ 2024-02-10 14:32 ` dilyan.palauzov at aegee dot org
  12 siblings, 0 replies; 14+ messages in thread
From: dilyan.palauzov at aegee dot org @ 2024-02-10 14:32 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679

--- Comment #13 from Дилян Палаузов <dilyan.palauzov at aegee dot org> ---
For clang being buggy from
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113679#c11 I filled
https://github.com/llvm/llvm-project/issues/81358 .

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-02-10 14:32 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-31  8:40 [Bug c/113679] New: long long minus double with gcc -m32 produces different results than other compilers or gcc -m64 dilyan.palauzov at aegee dot org
2024-01-31  8:44 ` [Bug target/113679] " pinskia at gcc dot gnu.org
2024-01-31  8:45 ` dilyan.palauzov at aegee dot org
2024-01-31  8:52 ` pinskia at gcc dot gnu.org
2024-01-31  8:53 ` jakub at gcc dot gnu.org
2024-01-31  9:58 ` dilyan.palauzov at aegee dot org
2024-01-31 10:02 ` pinskia at gcc dot gnu.org
2024-01-31 10:26 ` jakub at gcc dot gnu.org
2024-01-31 14:32 ` dilyan.palauzov at aegee dot org
2024-01-31 14:35 ` jakub at gcc dot gnu.org
2024-01-31 14:38 ` jakub at gcc dot gnu.org
2024-01-31 15:53 ` jakub at gcc dot gnu.org
2024-02-07  5:55 ` egallager at gcc dot gnu.org
2024-02-10 14:32 ` dilyan.palauzov at aegee dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).