[Bug c/60413] New: extra precision not properly removed on assignment of return value
desrt at desrt dot ca
gcc-bugzilla@gcc.gnu.org
Tue Mar 4 15:16:00 GMT 2014
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60413
Bug ID: 60413
Summary: extra precision not properly removed on assignment of
return value
Product: gcc
Version: 4.8.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: desrt at desrt dot ca
This problem has been seen with at least:
gcc version 4.8.2 20131212 (Red Hat 4.8.2-7) (GCC)
and
gcc version 4.8.2 (Ubuntu 4.8.2-16ubuntu4)
so I believe it to be an upstream problem.
This problem has only been observed to happen on 32bit compilations. There
doesn't seem to be a problem with 64bit.
Consider this code:
==> get-value.h <==
double get_value (void);
==> get-value.c <==
#include "get-value.h"
#include <stdint.h>
int x = 1;
double
get_value (void)
{
return x / 1e6;
}
==> main.c <==
#include "get-value.h"
#include <stdlib.h>
int
main (void)
{
double a, b;
a = get_value ();
b = get_value ();
if (a != b)
abort ();
return 0;
}
and build it with -O2 -m32.
You will get an abort.
The reason for this is because the return value of the get_value() function
comes via a floating point register. These registers have a higher precision
than IEEE double. The spec permits "extra range and precision":
"""
8 Except for assignment and cast (which remove all extra range and precision),
the values of operations with floating operands and values subject to the usual
arithmetic conversions and of floating constants are evaluated to a format
whose range and precision may be greater than required by the type.
"""
It seems that GCC is failing to remove the extra precision on the assignment "b
= get_value();".
Indeed, looking at the code that is output:
call get_value
movsd %xmm0, 8(%rsp)
call get_value
movsd 8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
we see that the first call has the return value stored in memory, but the
comparison uses the value from the second call directly, without truncating the
precision.
Adding 'volatile' to the local variables involved is an effective workaround
for the problem.
More information about the Gcc-bugs
mailing list