OSDN Git Service

* fold-const.c (negate_mathfn_p): New function to determine whether
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Oct 2003 21:15:08 +0000 (21:15 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Oct 2003 21:15:08 +0000 (21:15 +0000)
a built-in mathematical function is sign preserving, f(-x) == -f(x).
Add support for BUILT_IN_ASIN, BUILT_IN_ASINF and BUILT_IN_ASINL.
(tree_swap_operands_p): Change API to take an additional argument
indicating that the swapped operands evaluate in reverse order.
Canonicalize VAR_DECLs and PARM_DECLs last if we can, i.e. neither
operand side-effects or we don't care about flag_evaluation_order.
(reorder_operands_p): New function to check whether its safe to
evaluate the given operands in reverse order.
(negate_expr_p):  We can always negate integer constants unless
we honor -ftrapv and the signed type would overflow.  Only allow
-(A-B) into B-A if reorder_operands_p says that its OK.  Allow
negation of COMPLEX_CST if both real and imaginary parts can be
negated.  Allow negation through floating point extensions and
sign-preserving built-in functions.
(negate_expr):  Move the code to negate integers from "fold" to
here.  Always negate integer constants unless we honor -ftrapv
and the signed type would overflow.  Always negate real constants
unless we honor -ftrapping-math.  Only convert -(A-B) into B-A
if allowed by reorder_operands_p.  Add support for COMPLEX_CST.
Optimize negation through floating point extensions and
sign-preserving built-in functions (as defined by negate_mathfn_p).
(fold): Adjust calls to tree_swap_operands_p.
(fold <NEGATE_EXPR>): Move the remaining negation optimizations
to negate_expr_p/negate_expr.
(fold <MINUS_EXPR>): Use reorder_operands_p to check whether we're
allowed to convert (-A) - B into (-B) - A.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72381 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c

index a05b726..b233e94 100644 (file)
@@ -1,5 +1,35 @@
 2003-10-11  Roger Sayle  <roger@eyesopen.com>
 
+       * fold-const.c (negate_mathfn_p): New function to determine whether
+       a built-in mathematical function is sign preserving, f(-x) == -f(x).
+       Add support for BUILT_IN_ASIN, BUILT_IN_ASINF and BUILT_IN_ASINL.
+       (tree_swap_operands_p): Change API to take an additional argument
+       indicating that the swapped operands evaluate in reverse order.
+       Canonicalize VAR_DECLs and PARM_DECLs last if we can, i.e. neither
+       operand side-effects or we don't care about flag_evaluation_order.
+       (reorder_operands_p): New function to check whether its safe to
+       evaluate the given operands in reverse order.
+       (negate_expr_p):  We can always negate integer constants unless
+       we honor -ftrapv and the signed type would overflow.  Only allow
+       -(A-B) into B-A if reorder_operands_p says that its OK.  Allow
+       negation of COMPLEX_CST if both real and imaginary parts can be
+       negated.  Allow negation through floating point extensions and
+       sign-preserving built-in functions.
+       (negate_expr):  Move the code to negate integers from "fold" to
+       here.  Always negate integer constants unless we honor -ftrapv
+       and the signed type would overflow.  Always negate real constants
+       unless we honor -ftrapping-math.  Only convert -(A-B) into B-A
+       if allowed by reorder_operands_p.  Add support for COMPLEX_CST.
+       Optimize negation through floating point extensions and 
+       sign-preserving built-in functions (as defined by negate_mathfn_p).
+       (fold): Adjust calls to tree_swap_operands_p.
+       (fold <NEGATE_EXPR>): Move the remaining negation optimizations
+       to negate_expr_p/negate_expr.
+       (fold <MINUS_EXPR>): Use reorder_operands_p to check whether we're
+       allowed to convert (-A) - B into (-B) - A.
+
+2003-10-11  Roger Sayle  <roger@eyesopen.com>
+
        * builtins.c (expand_builtin_strcmp): Defend against the possibility
        that gen_cmpstrsi may fail: Stabilize the argument list against
        re-evaluation and expand the library call directly using this saved
index 92b885c..2e64314 100644 (file)
@@ -60,6 +60,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
+static bool negate_mathfn_p (enum built_in_function);
 static bool negate_expr_p (tree);
 static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
@@ -108,7 +109,8 @@ static bool fold_real_zero_addition_p (tree, tree, int);
 static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
                                 tree, tree, tree);
 static tree fold_inf_compare (enum tree_code, tree, tree, tree);
-static bool tree_swap_operands_p (tree, tree);
+static bool reorder_operands_p (tree, tree);
+static bool tree_swap_operands_p (tree, tree, bool);
 
 /* The following constants represent a bit based encoding of GCC's
    comparison operators.  This encoding simplifies transformations
@@ -803,6 +805,35 @@ div_and_round_double (enum tree_code code, int uns,
   return overflow;
 }
 \f
+/* Return true if built-in mathematical function specified by CODE
+   preserves the sign of it argument, i.e. -f(x) == f(-x).  */
+
+static bool
+negate_mathfn_p (enum built_in_function code)
+{
+  switch (code)
+    {
+    case BUILT_IN_ASIN:
+    case BUILT_IN_ASINF:
+    case BUILT_IN_ASINL:
+    case BUILT_IN_ATAN:
+    case BUILT_IN_ATANF:
+    case BUILT_IN_ATANL:
+    case BUILT_IN_SIN:
+    case BUILT_IN_SINF:
+    case BUILT_IN_SINL:
+    case BUILT_IN_TAN:
+    case BUILT_IN_TANF:
+    case BUILT_IN_TANL:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
+
 /* Determine whether an expression T can be cheaply negated using
    the function negate_expr.  */
 
@@ -822,8 +853,8 @@ negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (TREE_UNSIGNED (type))
-       return false;
+      if (TREE_UNSIGNED (type) || ! flag_trapv)
+       return true;
 
       /* Check that -CST will not overflow type.  */
       prec = TYPE_PRECISION (type);
@@ -844,9 +875,15 @@ negate_expr_p (tree t)
     case NEGATE_EXPR:
       return true;
 
+    case COMPLEX_CST:
+      return negate_expr_p (TREE_REALPART (t))
+            && negate_expr_p (TREE_IMAGPART (t));
+
     case MINUS_EXPR:
       /* We can't turn -(A-B) into B-A when we honor signed zeros.  */
-      return ! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations;
+      return (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+            && reorder_operands_p (TREE_OPERAND (t, 0),
+                                   TREE_OPERAND (t, 1));
 
     case MULT_EXPR:
       if (TREE_UNSIGNED (TREE_TYPE (t)))
@@ -860,6 +897,22 @@ negate_expr_p (tree t)
               || negate_expr_p (TREE_OPERAND (t, 0));
       break;
 
+    case NOP_EXPR:
+      /* Negate -((double)float) as (double)(-float).  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tree tem = strip_float_extensions (t);
+         if (tem != t)
+           return negate_expr_p (tem);
+       }
+      break;
+
+    case CALL_EXPR:
+      /* Negate -f(x) as f(-x).  */
+      if (negate_mathfn_p (builtin_mathfn_code (t)))
+       return negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1)));
+      break;
+
     default:
       break;
     }
@@ -884,25 +937,53 @@ negate_expr (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (! TREE_UNSIGNED (type)
-         && 0 != (tem = fold (build1 (NEGATE_EXPR, type, t)))
-         && ! TREE_OVERFLOW (tem))
+      {
+       unsigned HOST_WIDE_INT low;
+       HOST_WIDE_INT high;
+       int overflow = neg_double (TREE_INT_CST_LOW (t),
+                                  TREE_INT_CST_HIGH (t),
+                                  &low, &high);
+       tem = build_int_2 (low, high);
+       TREE_TYPE (tem) = type;
+       TREE_OVERFLOW (tem)
+         = (TREE_OVERFLOW (t)
+            | force_fit_type (tem, overflow && !TREE_UNSIGNED (type)));
+       TREE_CONSTANT_OVERFLOW (tem)
+         = TREE_OVERFLOW (tem) | TREE_CONSTANT_OVERFLOW (t);
+      }
+      if (! TREE_OVERFLOW (tem)
+         || TREE_UNSIGNED (type)
+         || ! flag_trapv)
        return tem;
       break;
 
     case REAL_CST:
       tem = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (t)));
       /* Two's complement FP formats, such as c4x, may overflow.  */
-      if (! TREE_OVERFLOW (tem))
+      if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
        return convert (type, tem);
       break;
 
+    case COMPLEX_CST:
+      {
+       tree rpart = negate_expr (TREE_REALPART (t));
+       tree ipart = negate_expr (TREE_IMAGPART (t));
+
+       if ((TREE_CODE (rpart) == REAL_CST
+            && TREE_CODE (ipart) == REAL_CST)
+           || (TREE_CODE (rpart) == INTEGER_CST
+               && TREE_CODE (ipart) == INTEGER_CST))
+         return build_complex (type, rpart, ipart);
+      }
+      break;
+
     case NEGATE_EXPR:
       return convert (type, TREE_OPERAND (t, 0));
 
     case MINUS_EXPR:
       /* - (A - B) -> B - A  */
-      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+      if ((! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
+         && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
        return convert (type,
                        fold (build (MINUS_EXPR, TREE_TYPE (t),
                                     TREE_OPERAND (t, 1),
@@ -933,6 +1014,30 @@ negate_expr (tree t)
        }
       break;
 
+    case NOP_EXPR:
+      /* Convert -((double)float) into (double)(-float).  */
+      if (TREE_CODE (type) == REAL_TYPE)
+       {
+         tem = strip_float_extensions (t);
+         if (tem != t && negate_expr_p (tem))
+           return convert (type, negate_expr (tem));
+       }
+      break;
+
+    case CALL_EXPR:
+      /* Negate -f(x) as f(-x).  */
+      if (negate_mathfn_p (builtin_mathfn_code (t))
+         && negate_expr_p (TREE_VALUE (TREE_OPERAND (t, 1))))
+       {
+         tree fndecl, arg, arglist;
+
+         fndecl = get_callee_fndecl (t);
+         arg = negate_expr (TREE_VALUE (TREE_OPERAND (t, 1)));
+         arglist = build_tree_list (NULL_TREE, arg);
+         return build_function_call_expr (fndecl, arglist);
+       }
+      break;
+
     default:
       break;
     }
@@ -4999,12 +5104,27 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
   return NULL_TREE;
 }
 
+/* Check whether we are allowed to reorder operands arg0 and arg1,
+   such that the evaluation of arg1 occurs before arg0.  */
+
+static bool
+reorder_operands_p (tree arg0, tree arg1)
+{
+  if (! flag_evaluation_order)
+    return true;
+  if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
+    return true;
+  return ! TREE_SIDE_EFFECTS (arg0)
+        && ! TREE_SIDE_EFFECTS (arg1);
+}
+
 /* Test whether it is preferable two swap two operands, ARG0 and
    ARG1, for example because ARG0 is an integer constant and ARG1
-   isn't.  */
+   isn't.  If REORDER is true, only recommend swapping if we can
+   evaluate the operands in reverse order.  */
 
 static bool
-tree_swap_operands_p (tree arg0, tree arg1)
+tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
 {
   STRIP_SIGN_NOPS (arg0);
   STRIP_SIGN_NOPS (arg1);
@@ -5029,6 +5149,15 @@ tree_swap_operands_p (tree arg0, tree arg1)
   if (TREE_CONSTANT (arg0))
     return 1;
 
+  if (reorder && flag_evaluation_order
+      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
+    return 0;
+
+  if (DECL_P (arg1))
+    return 0;
+  if (DECL_P (arg0))
+    return 1;
+
   return 0;
 }
 
@@ -5143,7 +5272,7 @@ fold (tree expr)
   if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
        || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
        || code == BIT_AND_EXPR)
-      && tree_swap_operands_p (arg0, arg1))
+      && tree_swap_operands_p (arg0, arg1, true))
     return fold (build (code, type, arg1, arg0));
 
   /* Now WINS is set as described above,
@@ -5482,71 +5611,8 @@ fold (tree expr)
       return t;
 
     case NEGATE_EXPR:
-      if (wins)
-       {
-         if (TREE_CODE (arg0) == INTEGER_CST)
-           {
-             unsigned HOST_WIDE_INT low;
-             HOST_WIDE_INT high;
-             int overflow = neg_double (TREE_INT_CST_LOW (arg0),
-                                        TREE_INT_CST_HIGH (arg0),
-                                        &low, &high);
-             t = build_int_2 (low, high);
-             TREE_TYPE (t) = type;
-             TREE_OVERFLOW (t)
-               = (TREE_OVERFLOW (arg0)
-                  | force_fit_type (t, overflow && !TREE_UNSIGNED (type)));
-             TREE_CONSTANT_OVERFLOW (t)
-               = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg0);
-           }
-         else if (TREE_CODE (arg0) == REAL_CST)
-           t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-       }
-      else if (TREE_CODE (arg0) == NEGATE_EXPR)
-       return TREE_OPERAND (arg0, 0);
-      /* Convert -((double)float) into (double)(-float).  */
-      else if (TREE_CODE (arg0) == NOP_EXPR
-              && TREE_CODE (type) == REAL_TYPE)
-       {
-         tree targ0 = strip_float_extensions (arg0);
-         if (targ0 != arg0)
-           return convert (type, build1 (NEGATE_EXPR, TREE_TYPE (targ0), targ0));
-
-       }
-
-      /* Convert - (a - b) to (b - a) for non-floating-point.  */
-      else if (TREE_CODE (arg0) == MINUS_EXPR
-              && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
-       return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
-                     TREE_OPERAND (arg0, 0));
-
-      /* Convert -f(x) into f(-x) where f is sin, tan or atan.  */
-      switch (builtin_mathfn_code (arg0))
-       {
-       case BUILT_IN_SIN:
-       case BUILT_IN_SINF:
-       case BUILT_IN_SINL:
-       case BUILT_IN_TAN:
-       case BUILT_IN_TANF:
-       case BUILT_IN_TANL:
-       case BUILT_IN_ATAN:
-       case BUILT_IN_ATANF:
-       case BUILT_IN_ATANL:
-         if (negate_expr_p (TREE_VALUE (TREE_OPERAND (arg0, 1))))
-           {
-             tree fndecl, arg, arglist;
-
-             fndecl = get_callee_fndecl (arg0);
-             arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
-             arg = fold (build1 (NEGATE_EXPR, type, arg));
-             arglist = build_tree_list (NULL_TREE, arg);
-             return build_function_call_expr (fndecl, arglist);
-           }
-         break;
-
-       default:
-         break;
-       }
+      if (negate_expr_p (arg0))
+       return negate_expr (arg0);
       return t;
 
     case ABS_EXPR:
@@ -5999,8 +6065,7 @@ fold (tree expr)
          && (FLOAT_TYPE_P (type)
              || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv))
          && negate_expr_p (arg1)
-         && (! TREE_SIDE_EFFECTS (arg0) || TREE_CONSTANT (arg1))
-         && (! TREE_SIDE_EFFECTS (arg1) || TREE_CONSTANT (arg0)))
+         && reorder_operands_p (arg0, arg1))
        return fold (build (MINUS_EXPR, type, negate_expr (arg1),
                            TREE_OPERAND (arg0, 0)));
 
@@ -6911,7 +6976,7 @@ fold (tree expr)
     case LE_EXPR:
     case GE_EXPR:
       /* If one arg is a real or integer constant, put it last.  */
-      if (tree_swap_operands_p (arg0, arg1))
+      if (tree_swap_operands_p (arg0, arg1, true))
        return fold (build (swap_tree_comparison (code), type, arg1, arg0));
 
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
@@ -8025,7 +8090,8 @@ fold (tree expr)
 
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
-      if (tree_swap_operands_p (TREE_OPERAND (t, 1), TREE_OPERAND (t, 2)))
+      if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+                               TREE_OPERAND (t, 2), false))
        {
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do