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?