summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog32
-rw-r--r--gcc/combine.c4
-rw-r--r--gcc/common.opt9
-rw-r--r--gcc/doc/invoke.texi28
-rw-r--r--gcc/fold-const.c49
-rw-r--r--gcc/loop-unroll.c2
-rw-r--r--gcc/opts.c15
-rw-r--r--gcc/simplify-rtx.c8
-rw-r--r--gcc/toplev.h2
-rw-r--r--gcc/tree-ssa-math-opts.c2
-rw-r--r--gcc/tree-ssa-reassoc.c8
-rw-r--r--gcc/tree-tailcall.c2
-rw-r--r--gcc/tree-vectorizer.c2
13 files changed, 129 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 346a10b1042..1abb3fe3ed2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,35 @@
+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
diff --git a/gcc/combine.c b/gcc/combine.c
index b2bc7806f7b..c8ed4402f93 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4699,7 +4699,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
|| 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)
{
@@ -4972,7 +4972,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
}
/* 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,
diff --git a/gcc/common.opt b/gcc/common.opt
index d9894a98844..27b2b63803c 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1125,6 +1125,15 @@ funsafe-loop-optimizations
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"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ee6bb6f1ed5..774f2f3709b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6173,6 +6173,7 @@ it might, and @option{-fno-math-errno} is the default.
@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
@@ -6184,9 +6185,36 @@ it can result in incorrect output for programs which depend on
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
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7220711539a..6b11283a8ae 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9096,8 +9096,9 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
/* 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
@@ -9651,11 +9652,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
/* 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)
@@ -9791,8 +9793,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
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)
{
@@ -9806,8 +9810,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
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)
{
@@ -9898,10 +9904,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
/* 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;
@@ -10202,11 +10208,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
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)
@@ -10297,8 +10304,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
&& 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)
@@ -10962,12 +10971,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
/* 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);
@@ -10984,15 +10993,15 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
}
}
- /* 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,
@@ -11000,7 +11009,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
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)
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 1d9bcc45ccf..e57e8e665b2 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -1631,7 +1631,7 @@ analyze_insn_to_expand_var (struct loop *loop, rtx insn)
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)
diff --git a/gcc/opts.c b/gcc/opts.c
index dc5a26d2483..735f942a883 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1559,6 +1559,10 @@ common_handle_option (size_t scode, const char *arg, int value,
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;
@@ -1857,6 +1861,8 @@ set_fast_math_flags (int set)
{
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;
@@ -1868,6 +1874,15 @@ set_fast_math_flags (int 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)
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 857b7412343..ac91f2fc92a 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1723,9 +1723,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
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)
@@ -2480,8 +2480,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
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);
diff --git a/gcc/toplev.h b/gcc/toplev.h
index 2397dee6dbf..749cf308a96 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -148,6 +148,8 @@ extern struct ht *ident_hash;
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 *);
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index addd83d8339..543169ad932 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -443,7 +443,7 @@ execute_cse_reciprocals_1 (block_stmt_iterator *def_bsi, tree def)
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
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 87db02f3273..f75437d0522 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1244,14 +1244,14 @@ break_up_subtract_bb (basic_block bb)
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;
@@ -1294,14 +1294,14 @@ reassociate_bb (basic_block bb)
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;
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 544b0e360f7..8651b60fc0d 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -297,7 +297,7 @@ process_assignment (tree ass, tree stmt, block_stmt_iterator call, tree *m,
/* 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;
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 11349c2771f..c239d296316 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -2304,7 +2304,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, tree phi)
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. */