[PATCH] gimple-fold: Don't optimize wierdo floating point value reads [PR95450]

Jakub Jelinek jakub@redhat.com
Wed Aug 12 15:33:48 GMT 2020

On Wed, Aug 12, 2020 at 04:30:35PM +0200, Richard Biener wrote:
> Not a final review but if we care for this kind of normalization at all
> the we should do so consistently, thus for both encode and interpret and
> for all modes.  For FP we could also check if we'd consider the values
> equal rather than whether we would en/decode them to the same bit pattern
> (which might or might not be what an actual ISA gpr<->fpr reg move would
> do)

I think the verification that what we encode can be interpreted back
woiuld be only an internal consistency check (so perhaps for ENABLE_CHECKING
if flag_checking only, but if both directions perform it, then we need
to avoid mutual recursion).
While for the other direction (interpretation), at least for the broken by
design long doubles we just know we can't represent in GCC all valid values.
The other floating point formats are just theoretical case, perhaps we would
canonicalize something to a value that wouldn't trigger invalid exception
when without canonicalization it would trigger it at runtime, so let's just
ignore those.

Adjusted (so far untested) patch to do it in native_interpret_real instead
and limit it to the MODE_COMPOSITE_P cases, for which e.g.
fold-const.c/simplify-rtx.c punts in several other places too because we just
know we can't represent everything.

      /* Don't constant fold this floating point operation if the
         result may dependent upon the run-time rounding mode and
         flag_rounding_math is set, or if GCC's software emulation
         is unable to accurately represent the result.  */
      if ((flag_rounding_math
           || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations))
          && (inexact || !real_identical (&result, &value)))
        return NULL_TREE;
Or perhaps guard it with MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations
too, thus break what gnulib / m4 does with -ffast-math, but not normally?

2020-08-12  Jakub Jelinek  <jakub@redhat.com>

	PR target/95450
	* fold-const.c (native_interpret_real): For MODE_COMPOSITE_P modes
	punt if the to be returned REAL_CST does not encode to the bitwise
	same representation.

	* gcc.target/powerpc/pr95450.c: New test.

--- gcc/fold-const.c.jj	2020-08-04 10:02:43.434408528 +0200
+++ gcc/fold-const.c	2020-08-12 17:16:31.893226663 +0200
@@ -8327,7 +8327,19 @@ native_interpret_real (tree type, const
   real_from_target (&r, tmp, mode);
-  return build_real (type, r);
+  tree ret = build_real (type, r);
+  if (MODE_COMPOSITE_P (mode))
+    {
+      /* For floating point values in composite modes, punt if this folding
+	 doesn't preserve bit representation.  As the mode doesn't have fixed
+	 precision while GCC pretends it does, there could be valid values that
+	 GCC can't really represent accurately.  See PR95450.  */
+      unsigned char buf[24];
+      if (native_encode_expr (ret, buf, total_bytes, 0) != total_bytes
+	  || memcmp (ptr, buf, total_bytes) != 0)
+	ret = NULL_TREE;
+    }
+  return ret;
--- gcc/testsuite/gcc.target/powerpc/pr95450.c.jj	2020-08-12 17:10:51.402872241 +0200
+++ gcc/testsuite/gcc.target/powerpc/pr95450.c	2020-08-12 17:10:51.402872241 +0200
@@ -0,0 +1,29 @@
+/* PR target/95450 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "return \[0-9.e+]\+;" "optimized" } } */
+/* Verify this is not optimized for double double into return floating_point_constant,
+   as while that constant is the maximum normalized floating point value, it needs
+   107 bit precision, which is more than GCC supports for this format.  */
+#if __LDBL_MANT_DIG__ == 106
+union U
+  struct { double hi; double lo; } dd;
+  long double ld;
+const union U g = { { __DBL_MAX__, __DBL_MAX__ / (double)134217728UL / (double)134217728UL } };
+struct S
+  long double ld;
+} g;
+long double
+foo (void)
+  return g.ld;


More information about the Gcc-patches mailing list