OSDN Git Service

Add new fp flags: -fassociative-math and -freciprocal-math
authorrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Sep 2007 12:11:11 +0000 (12:11 +0000)
committerrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 4 Sep 2007 12:11:11 +0000 (12:11 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128075 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/combine.c
gcc/common.opt
gcc/doc/invoke.texi
gcc/fold-const.c
gcc/loop-unroll.c
gcc/opts.c
gcc/simplify-rtx.c
gcc/toplev.h
gcc/tree-ssa-math-opts.c
gcc/tree-ssa-reassoc.c
gcc/tree-tailcall.c
gcc/tree-vectorizer.c

index 346a10b..1abb3fe 100644 (file)
@@ -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
index b2bc780..c8ed440 100644 (file)
@@ -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,
index d9894a9..27b2b63 100644 (file)
@@ -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"
index ee6bb6f..774f2f3 100644 (file)
@@ -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
index 7220711..6b11283 100644 (file)
@@ -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)
index 1d9bcc4..e57e8e6 100644 (file)
@@ -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)
index dc5a26d..735f942 100644 (file)
@@ -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)
index 857b741..ac91f2f 100644 (file)
@@ -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);
index 2397dee..749cf30 100644 (file)
@@ -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 *);
 
index addd83d..543169a 100644 (file)
@@ -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
index 87db02f..f75437d 100644 (file)
@@ -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;
index 544b0e3..8651b60 100644 (file)
@@ -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;
 
index 11349c2..c239d29 100644 (file)
@@ -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.  */