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?