http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48295

           Summary: Incorrect code generated with dynamic floating point
                    rounding mode switches
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: frederic.r...@gmail.com


The attached code is compiled incorrectly with every GCC version I could try.

The code tries to do a floating point multiplication with a non-default
rounding mode and then switches the rounding mode back to normal before
checking the result.

The result is wrong even if -frounding-math is specified on the command line. I
tracked it down to tree-ssa-ter used during RTL expansion. The multiplication
is detected to be a replaceable statement and is thus emitted after the
floating point rounding mode has been reset back to normal.

That simple hack fixes it :

--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -429,8 +429,10 @@ is_replaceable_p (gimple stmt, bool ter)
       && !is_gimple_val (gimple_assign_rhs1 (stmt)))
     return false;

-  /* Float expressions must go through memory if float-store is on.  */
-  if (flag_float_store
+  /* Float expressions must go through memory if float-store is on.
+     Also, don't move float operations around if we're not sure the
+     rounding mode never changes.  */
+  if ((flag_float_store || flag_rounding_math)
       && FLOAT_TYPE_P (gimple_expr_type (stmt)))
     return false;


However it's clearly not the optimal solution, as we might be able to detect
that the rounding didn't change. AFAIU, tree-ssa-ter doesn't allow to
replacements spanning calls, so it might be better to extend that logic to
consider asm and builtins as replacement barriers when in flag_rounding_math
mode. What do you think?

Reply via email to