+2007-09-04 Revital Eres <eres@il.ibm.com>
+ Richard Guenther <rguenther@suse.de>
+ R. Clint Whaley <whaley@cs.utsa.edu>
+
+ * doc/invoke.texi (-fassociative-math, -freciprocal-math):
+ Document new flags.
+ * tree-tailcall.c (process_assignment): Use -fassociative-math
+ when reodering operands of floating-point type.
+ * fold-const.c (fold_comparison, fold_binary): Use
+ -fassociative-math and -freciprocal-math instead of
+ -funsafe-math-optimization flag.
+ * toplev.h (set_unsafe_math_optimizations_flags): Declare function.
+ * tree-ssa-math-opts.c (gate_cse_reciprocals): Use
+ -freciprocal-math instead of -funsafe-math-optimizations.
+ * opts.c (set_fast_math_flags): Set -freciprocal-math and
+ -fassociative-math when -ffast-math is set.
+ (set_unsafe_math_optimizations_flags): New Function
+ to set -freciprocal-math and -fassociative-math when
+ -funsafe-math-optimizations is set.
+ (common_handle_option): Call it.
+ * tree-vectorizer.c (vect_is_simple_reduction): Use
+ -fassociative-math when doing reduction on floats.
+ * loop-unroll.c (analyze_insn_to_expand_var): Use
+ -fassociative-math when expanding an accumulator of type float.
+ * simplify-rtx.c (simplify_binary_operation_1): Use
+ -fassociative-math and -freciprocal-math when reordeing operands
+ of floating-point type.
+ * combine.c (combine_simplify_rtx): Likewise.
+ * tree-ssa-reassoc.c (break_up_subtract_bb, reassociate_bb):
+ Likewise.
+ * common.opt (-fassociative-math, -freciprocal-math): New flags.
+
2007-09-04 Paolo Carlini <pcarlini@suse.de>
PR c++/18608
|| code == AND || code == IOR || code == XOR
|| code == SMAX || code == SMIN || code == UMAX || code == UMIN)
&& ((INTEGRAL_MODE_P (mode) && code != DIV)
- || (flag_unsafe_math_optimizations && FLOAT_MODE_P (mode))))
+ || (flag_associative_math && FLOAT_MODE_P (mode))))
{
if (GET_CODE (XEXP (x, 0)) == code)
{
}
/* Try simplify a*(b/c) as (a*b)/c. */
- if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
+ if (FLOAT_MODE_P (mode) && flag_associative_math
&& GET_CODE (XEXP (x, 0)) == DIV)
{
rtx tem = simplify_binary_operation (MULT, mode,
Common Report Var(flag_unsafe_loop_optimizations) Optimization
Allow loop optimizations to assume that the loops behave in normal way
+fassociative-math
+Common Report Var(flag_associative_math)
+Allow optimization for floating-point arithmetic which may change the
+result of the operation due to rounding.
+
+freciprocal-math
+Common Report Var(flag_reciprocal_math)
+Same as -fassociative-math for expressions which include division.
+
; Nonzero means that unsafe floating-point math optimizations are allowed
; for the sake of speed. IEEE compliance is not guaranteed, and operations
; are allowed to assume that their arguments and results are "normal"
@item -funsafe-math-optimizations
@opindex funsafe-math-optimizations
+
Allow optimizations for floating-point arithmetic that (a) assume
that arguments and results are valid and (b) may violate IEEE or
ANSI standards. When used at link-time, it may include libraries
an exact implementation of IEEE or ISO rules/specifications for
math functions. It may, however, yield faster code for programs
that do not require the guarantees of these specifications.
+Enables @option{-freciprocal-math} and @option{-fassociative-math}.
The default is @option{-fno-unsafe-math-optimizations}.
+@item -fassociative-math
+@opindex -fassociative-math
+
+Allow re-association of operands in series of floating-point operations.
+This violates the ISO C and C++ language standard by possibly changing
+computation result. NOTE: re-ordering may change the sign of zero as
+well as ignore NaNs and inhibit or create underflow or overflow (and
+thus cannot be used on a code which relies on rounding behavior like
+@code{(x + 2**52) - 2**52)}. May also reorder floating-point comparisons
+and thus may not be used when ordered comparisons are required.
+This flag doesn't make much sense without @option{-fno-signed-zeros}
+or @option{-fno-trapping-math} or with @option{-frounding-math}.
+
+The default is @option{-fno-associative-math}.
+
+@item -freciprocal-math
+@opindex -freciprocal-math
+
+Allow the reciprocal of a value to be used instead of dividing by
+the value if this enables optimizations. For example @code{x / y}
+can be replaced with @code{x * (1/y)} which is useful if @code{(1/y)}
+is subject to common subexpression elimination. Note that this loses
+precision and increases the number of flops operating on the value.
+
+The default is @option{-fno-reciprocal-math}.
+
@item -ffinite-math-only
@opindex ffinite-math-only
Allow optimizations for floating-point arithmetic that assume
/* Likewise, we can simplify a comparison of a real constant with
a MINUS_EXPR whose first operand is also a real constant, i.e.
- (c1 - x) < c2 becomes x > c1-c2. */
- if (flag_unsafe_math_optimizations
+ (c1 - x) < c2 becomes x > c1-c2. Reordering is allowed on
+ floating-point types only if -fassociative-math is set. */
+ if (flag_associative_math
&& TREE_CODE (arg1) == REAL_CST
&& TREE_CODE (arg0) == MINUS_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
}
/* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
- same or one. Make sure type is not saturating. */
+ same or one. Make sure type is not saturating.
+ fold_plusminus_mult_expr will re-associate. */
if ((TREE_CODE (arg0) == MULT_EXPR
|| TREE_CODE (arg1) == MULT_EXPR)
&& !TYPE_SATURATING (type)
- && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
+ && (!FLOAT_TYPE_P (type) || flag_associative_math))
{
tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
if (tem)
return fold_build2 (MULT_EXPR, type, arg0,
build_real (type, dconst2));
- /* Convert a + (b*c + d*e) into (a + b*c) + d*e. */
- if (flag_unsafe_math_optimizations
+ /* Convert a + (b*c + d*e) into (a + b*c) + d*e.
+ We associate floats only if the user has specified
+ -fassociative-math. */
+ if (flag_associative_math
&& TREE_CODE (arg1) == PLUS_EXPR
&& TREE_CODE (arg0) != MULT_EXPR)
{
return fold_build2 (PLUS_EXPR, type, tree0, tree11);
}
}
- /* Convert (b*c + d*e) + a into b*c + (d*e +a). */
- if (flag_unsafe_math_optimizations
+ /* Convert (b*c + d*e) + a into b*c + (d*e +a).
+ We associate floats only if the user has specified
+ -fassociative-math. */
+ if (flag_associative_math
&& TREE_CODE (arg0) == PLUS_EXPR
&& TREE_CODE (arg1) != MULT_EXPR)
{
/* In most languages, can't associate operations on floats through
parentheses. Rather than remember where the parentheses were, we
don't associate floats at all, unless the user has specified
- -funsafe-math-optimizations.
+ -fassociative-math.
And, we need to make sure type is not saturating. */
- if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+ if ((! FLOAT_TYPE_P (type) || flag_associative_math)
&& !TYPE_SATURATING (type))
{
tree var0, con0, lit0, minus_lit0;
return tem;
/* Handle (A1 * C1) - (A2 * C2) with A1, A2 or C1, C2 being the
- same or one. Make sure type is not saturating. */
+ same or one. Make sure type is not saturating.
+ fold_plusminus_mult_expr will re-associate. */
if ((TREE_CODE (arg0) == MULT_EXPR
|| TREE_CODE (arg1) == MULT_EXPR)
&& !TYPE_SATURATING (type)
- && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
+ && (!FLOAT_TYPE_P (type) || flag_associative_math))
{
tree tem = fold_plusminus_mult_expr (code, type, arg0, arg1);
if (tem)
&& real_minus_onep (arg1))
return fold_convert (type, negate_expr (arg0));
- /* Convert (C1/X)*C2 into (C1*C2)/X. */
- if (flag_unsafe_math_optimizations
+ /* Convert (C1/X)*C2 into (C1*C2)/X. This transformation may change
+ the result for floating point types due to rounding so it is applied
+ only if -fassociative-math was specify. */
+ if (flag_associative_math
&& TREE_CODE (arg0) == RDIV_EXPR
&& TREE_CODE (arg1) == REAL_CST
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
/* If ARG1 is a constant, we can convert this to a multiply by the
reciprocal. This does not have the same rounding properties,
- so only do this if -funsafe-math-optimizations. We can actually
+ so only do this if -freciprocal-math. We can actually
always safely do it if ARG1 is a power of two, but it's hard to
tell if it is or not in a portable manner. */
if (TREE_CODE (arg1) == REAL_CST)
{
- if (flag_unsafe_math_optimizations
+ if (flag_reciprocal_math
&& 0 != (tem = const_binop (code, build_real (type, dconst1),
arg1, 0)))
return fold_build2 (MULT_EXPR, type, arg0, tem);
}
}
}
- /* Convert A/B/C to A/(B*C). */
- if (flag_unsafe_math_optimizations
+ /* Convert A/B/C to A/(B*C). */
+ if (flag_reciprocal_math
&& TREE_CODE (arg0) == RDIV_EXPR)
return fold_build2 (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
fold_build2 (MULT_EXPR, type,
TREE_OPERAND (arg0, 1), arg1));
/* Convert A/(B/C) to (A/B)*C. */
- if (flag_unsafe_math_optimizations
+ if (flag_reciprocal_math
&& TREE_CODE (arg1) == RDIV_EXPR)
return fold_build2 (MULT_EXPR, type,
fold_build2 (RDIV_EXPR, type, arg0,
TREE_OPERAND (arg1, 1));
/* Convert C1/(X*C2) into (C1/C2)/X. */
- if (flag_unsafe_math_optimizations
+ if (flag_reciprocal_math
&& TREE_CODE (arg1) == MULT_EXPR
&& TREE_CODE (arg0) == REAL_CST
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
mode2 = GET_MODE (something);
if ((FLOAT_MODE_P (mode1)
|| FLOAT_MODE_P (mode2))
- && !flag_unsafe_math_optimizations)
+ && !flag_associative_math)
return NULL;
if (dump_file)
set_fast_math_flags (value);
break;
+ case OPT_funsafe_math_optimizations:
+ set_unsafe_math_optimizations_flags (value);
+ break;
+
case OPT_ffixed_:
fix_register (arg, 1, 1);
break;
{
flag_trapping_math = !set;
flag_unsafe_math_optimizations = set;
+ flag_associative_math = set;
+ flag_reciprocal_math = set;
flag_finite_math_only = set;
flag_signed_zeros = !set;
flag_errno_math = !set;
}
}
+/* When -funsafe-math-optimizations is set the following
+ flags are set as well. */
+void
+set_unsafe_math_optimizations_flags (int set)
+{
+ flag_reciprocal_math = set;
+ flag_associative_math = set;
+}
+
/* Return true iff flags are set as if -ffast-math. */
bool
fast_math_flags_set_p (void)
return tem;
/* Reassociate floating point addition only when the user
- specifies unsafe math optimizations. */
+ specifies associative math operations. */
if (FLOAT_MODE_P (mode)
- && flag_unsafe_math_optimizations)
+ && flag_associative_math)
{
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return simplify_gen_unary (NEG, mode, op0, mode);
/* Change FP division by a constant into multiplication.
- Only do this with -funsafe-math-optimizations. */
- if (flag_unsafe_math_optimizations
+ Only do this with -freciprocal-math. */
+ if (flag_reciprocal_math
&& !REAL_VALUES_EQUAL (d, dconst0))
{
REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
extern void set_fast_math_flags (int);
+extern void set_unsafe_math_optimizations_flags (int);
+
/* Handle -d switch. */
extern void decode_d_option (const char *);
static bool
gate_cse_reciprocals (void)
{
- return optimize && !optimize_size && flag_unsafe_math_optimizations;
+ return optimize && !optimize_size && flag_reciprocal_math;
}
/* Go through all the floating-point SSA_NAMEs, and call
tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
TREE_VISITED (stmt) = 0;
- /* If unsafe math optimizations we can do reassociation for
+ /* If associative-math we can do reassociation for
non-integral types. Or, we can do reassociation for
non-saturating fixed-point types. */
if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
&& (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
- || !flag_unsafe_math_optimizations)
+ || !flag_associative_math)
&& (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs))))
continue;
if (TREE_VISITED (stmt))
continue;
- /* If unsafe math optimizations we can do reassociation for
+ /* If associative-math we can do reassociation for
non-integral types. Or, we can do reassociation for
non-saturating fixed-point types. */
if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
&& (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
|| !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
- || !flag_unsafe_math_optimizations)
+ || !flag_associative_math)
&& (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (rhs))
|| !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(lhs))))
continue;
/* Accumulator optimizations will reverse the order of operations.
We can only do that for floating-point types if we're assuming
that addition and multiplication are associative. */
- if (!flag_unsafe_math_optimizations)
+ if (!flag_associative_math)
if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
return false;
outer-loop vectorization is safe. */
/* CHECKME: check for !flag_finite_math_only too? */
- if (SCALAR_FLOAT_TYPE_P (type) && !flag_unsafe_math_optimizations
+ if (SCALAR_FLOAT_TYPE_P (type) && !flag_associative_math
&& !nested_in_vect_loop_p (vect_loop, def_stmt))
{
/* Changing the order of operations changes the semantics. */