User account creation filtered due to spam.

Bug 38960 - Wrong floating point reorder
Summary: Wrong floating point reorder
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2009-01-24 14:57 UTC by Abramo Bagnara
Modified: 2009-01-24 15:43 UTC (History)
3 users (show)

See Also:
Target: i486-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2009-01-24 15:43:40

Assembler generated by gcc -S -O2 bug.c (476 bytes, text/plain)
2009-01-24 15:14 UTC, Abramo Bagnara

Note You need to log in before you can comment on or make changes to this bug.
Description Abramo Bagnara 2009-01-24 14:57:40 UTC
The program below show that gcc reorder floating point instructions in such a way to make inexact checking fruitless.

Reading generated assembler I see two problems:

1) the cast to float in x assignment is executed *after* fetestexcept and not before as it's written (and needed to get the correct result). This infringes C99 standard sequence point rules.

2) the second division is not recomputed (because CSE), then inexact flag is not changed after feclearexcept

I guess that the latter is due to missing #pragma STDC FENV_ACCESS implementation, but the former undermine the whole fetestexcept usability.

$ cat bug.c
#include <fenv.h>
#include <stdio.h>

double vf = 0x0fffffff;
double vg = 0x10000000;

/* vf/vg is exactly representable as IEC559 64 bit floating point,
   while it's not representable exactly as a 32 bit one */

int main() {
  double a = vf;
  double b = vg;

  float x;
  x = a / b;
  printf("%i %.1000g\n", fetestexcept(FE_INEXACT), x);

  double y;
  y = a / b;
  printf("%i %.1000g\n", fetestexcept(FE_INEXACT), y);
  return 0;
$ gcc -O2 bug.c -lm
$ ./a.out
0 1
0 0.9999999962747097015380859375
Comment 1 Abramo Bagnara 2009-01-24 15:14:18 UTC
Created attachment 17176 [details]
Assembler generated by gcc -S -O2 bug.c
Comment 2 Richard Biener 2009-01-24 15:43:40 UTC
It is both due to missing #pragma STDC FENV_ACCESS

GCC does not have a way to represent use/def of floating-point status, so
the call to fetestexcept is not a barrier for moving floating-point
operations.  In fact, it will be hard to represent this.