Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Nov 2015 20:37:24 +0000
From:      bugzilla-noreply@freebsd.org
To:        freebsd-bugs@FreeBSD.org
Subject:   [Bug 204671] clang floating point wrong around Inf (i386)
Message-ID:  <bug-204671-8-kMVwFWIOER@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-204671-8@https.bugs.freebsd.org/bugzilla/>
References:  <bug-204671-8@https.bugs.freebsd.org/bugzilla/>

next in thread | previous in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=204671

Jilles Tjoelker <jilles@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jilles@FreeBSD.org

--- Comment #2 from Jilles Tjoelker <jilles@FreeBSD.org> ---
This is related to the strangeness that is the x87 FPU. Internally, the x87
performs calculations in extended precision. Even if the precision control is
set to double precision, like FreeBSD and Windows do by default but Linux and
Solaris do not, the x87 registers still have greater range than double
precision.

As a result, the addition 1e308 + 1e308 does not overflow, but produces a
result of approximately 2e308 in an x87 register. When this result is stored to
memory in double precision format, overflow or rounding will occur.

What happens in t1.c is that the conversion from extended to double precision
happens two times. The conversion for printing the bytes happens directly after
the calculation and therefore uses the modified rounding mode. The conversion
for printf happens during the inlined fesetround() call, after setting the x87
rounding mode and before calling a function __test_sse to check whether SSE is
available. (After that, the value is stored and loaded again a few times.)
Therefore, the conversion for printf uses an incorrect rounding mode.

Global variables force the compiler to store values to memory more often and
may therefore reduce x87 weirdnesses.

Following the C standard, you would have to use  #pragma STDC FENV_ACCESS on 
to make this work reliably. However, neither gcc nor clang support this pragma.
They follow an ad hoc approach to floating point exceptions and modes. In gcc
you can use -frounding-math to prevent some problematic optimizations but clang
doesn't even support that. Clang has a bug about the pragma,
https://llvm.org/bugs/show_bug.cgi?id=8100, which has been open for five years
with various duplicates but no other significant action.

You will generally have fewer problems with weirdly changing floating point
results if you use SSE instead of the x87 FPU, assuming your CPUs are new
enough. SSE performs calculations in the precision specified by the program
(single or double), so it does not matter when or if a value is spilled to
memory. As noted above, GCC and clang are still ignorant about the side effects
with the floating point exceptions and modes, though.

-- 
You are receiving this mail because:
You are the assignee for the bug.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-204671-8-kMVwFWIOER>