diff options
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/combine.c | 4 | ||||
-rw-r--r-- | gcc/common.opt | 9 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 28 | ||||
-rw-r--r-- | gcc/fold-const.c | 49 | ||||
-rw-r--r-- | gcc/loop-unroll.c | 2 | ||||
-rw-r--r-- | gcc/opts.c | 15 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 8 | ||||
-rw-r--r-- | gcc/toplev.h | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 8 | ||||
-rw-r--r-- | gcc/tree-tailcall.c | 2 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 2 |
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. */ |