https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85957

Alexander Monakov <amonakov at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
   Last reconfirmed|                            |2018-05-29
                 CC|                            |amonakov at gcc dot gnu.org
         Resolution|DUPLICATE                   |---
     Ever confirmed|0                           |1

--- Comment #7 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
Reopening, the issue here is way more subtle than bug 323 and points to a
possible issue in DOM. Hopefully Richi can have a look and comment.

It appears dom2 pass performs something like jump threading based on
compile-time-evaluated floating-point expression values without also
substituting those expressions in IR. At run time, they are evaluated to
different values, leading to an inconsistency. Namely, dom2 creates bb 10:

  <bb 9>:
  # iftmp.1_1 = PHI <"true"(7), "false"(8), "true"(10)>
  printf ("(a6 == b6) = %s\n", iftmp.1_1);
  return 0;

  <bb 10>:
  _24 = __n2_13 * 1.0e+6;
  b6_25 = (guint64) _24;
  printf ("a6 = %llu\n", 1);
  printf ("b6 = %llu\n", b6_25);
  goto <bb 9>;

where jump to bb 9 implies that _24 evaluates to 1.0 and b6_25 to 1, but they
are not substituted as such, and at run time evaluate to 0.99... and 0 due to
excess precision.

The following reduced testcase demonstrates the same issue, but requires
-fdisable-tree-dom3 (on gcc-6 at least, as otherwise dom3 substitutes results
of compile-time evaluation).

__attribute__((noinline,noclone))
static double f(void)
{
  return 1e-6;
}

int main(void)
{
  double a = 1e-6, b = f();

  if (a != b) __builtin_printf("uneq");

  unsigned long long ia = a * 1e6, ib = b * 1e6;

  __builtin_printf("%lld %s %lld\n", ia, ia == ib ? "==" : "!=", ib);
}

Reply via email to