public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/60413] New: extra precision not properly removed on assignment of return value
@ 2014-03-04 15:16 desrt at desrt dot ca
  2014-03-04 16:14 ` [Bug c/60413] " jakub at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: desrt at desrt dot ca @ 2014-03-04 15:16 UTC (permalink / raw)
  To: gcc-bugs

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.


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

end of thread, other threads:[~2014-03-04 16:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-04 15:16 [Bug c/60413] New: extra precision not properly removed on assignment of return value desrt at desrt dot ca
2014-03-04 16:14 ` [Bug c/60413] " jakub at gcc dot gnu.org
2014-03-04 16:24 ` desrt at desrt dot ca
2014-03-04 16:28 ` jakub at gcc dot gnu.org
2014-03-04 16:43 ` desrt at desrt dot ca

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).