https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100119
Bug ID: 100119 Summary: [x86] Conversion unsigned int -> double produces -0 (-m32 -msse2 -mfpmath=sse) Product: gcc Version: 10.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: chfast at gmail dot com Target Milestone: --- When building for 32-bit x86 but with SSE2 floating-point enabled: -m32 -msse2 -mfpmath=sse the conversion from unsigned int 0 to double produces the result of -0.0 when floating-point rounding mode is set to FE_DOWNWARD. I used -frounding-math and #pragma STDC FENV_ACCESS ON. This bug is not present on x87 nor x86_64 builds. The bug seems to be present at least since GCC 5. #include <fenv.h> #pragma STDC FENV_ACCESS ON __attribute__((noinline)) double u32_to_f64(unsigned x) { return static_cast<double>(x); } int main() { fesetround(FE_DOWNWARD); double d = u32_to_f64(0); return __builtin_signbit(d) != 0; // signbit should be 0 } The assembly: u32_to_f64(unsigned int): sub esp, 12 pxor xmm0, xmm0 mov eax, DWORD PTR [esp+16] add eax, -2147483648 cvtsi2sd xmm0, eax addsd xmm0, QWORD PTR .LC0 movsd QWORD PTR [esp], xmm0 fld QWORD PTR [esp] add esp, 12 ret main: lea ecx, [esp+4] and esp, -16 push DWORD PTR [ecx-4] push ebp mov ebp, esp push ecx sub esp, 32 push 1024 call fesetround mov DWORD PTR [esp], 0 call u32_to_f64(unsigned int) mov ecx, DWORD PTR [ebp-4] add esp, 16 fstp QWORD PTR [ebp-16] movsd xmm0, QWORD PTR [ebp-16] leave lea esp, [ecx-4] movmskpd eax, xmm0 and eax, 1 ret .LC0: .long 0 .long 1105199104 https://godbolt.org/z/rrMWY9jsG