OSDN Git Service

* fold-const.c (int_const_binop): Return NULL_TREE when an expression
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Dec 2005 23:27:34 +0000 (23:27 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Dec 2005 23:27:34 +0000 (23:27 +0000)
can't be evaluated at compile-time (instead of calling abort).
Return NULL_TREE for division (and modulus) by zero.
(const_binop):  Return NULL_TREE for floating point operators that
aren't handled by real_arithmetic.
(fold_binary):  Eliminate "wins" variable, and "binary" label, by
folding operators with constant operands early.  Assert that
operands are non-NULL.

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

gcc/ChangeLog
gcc/fold-const.c

index ae1ffcb..2103a66 100644 (file)
@@ -1,3 +1,14 @@
+2005-12-27  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (int_const_binop): Return NULL_TREE when an expression
+       can't be evaluated at compile-time (instead of calling abort).
+       Return NULL_TREE for division (and modulus) by zero.
+       (const_binop):  Return NULL_TREE for floating point operators that
+       aren't handled by real_arithmetic.
+       (fold_binary):  Eliminate "wins" variable, and "binary" label, by
+       folding operators with constant operands early.  Assert that
+       operands are non-NULL.
+
 2005-12-27  Kazu Hirata  <kazu@codesourcery.com>
 
        * tree-vrp.c (extract_range_from_binary_expr): Use
index eeb20ce..4006d89 100644 (file)
@@ -1345,7 +1345,8 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type)
 }
 \f
 /* Combine two integer constants ARG1 and ARG2 under operation CODE
-   to produce a new constant.
+   to produce a new constant.  Return NULL_TREE if we don't know how
+   to evaluate CODE at compile-time.
 
    If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
@@ -1434,6 +1435,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       /* ... fall through ...  */
 
     case ROUND_DIV_EXPR:
+      if (int2h == 0 && int2l == 0)
+       return NULL_TREE;
       if (int2h == 0 && int2l == 1)
        {
          low = int1l, hi = int1h;
@@ -1466,6 +1469,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       /* ... fall through ...  */
 
     case ROUND_MOD_EXPR:
+      if (int2h == 0 && int2l == 0)
+       return NULL_TREE;
       overflow = div_and_round_double (code, uns,
                                       int1l, int1h, int2l, int2h,
                                       &garbagel, &garbageh, &low, &hi);
@@ -1490,7 +1495,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      gcc_unreachable ();
+      return NULL_TREE;
     }
 
   t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
@@ -1546,6 +1551,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       bool inexact;
       tree t, type;
 
+      /* The following codes are handled by real_arithmetic.  */
+      switch (code)
+       {
+       case PLUS_EXPR:
+       case MINUS_EXPR:
+       case MULT_EXPR:
+       case RDIV_EXPR:
+       case MIN_EXPR:
+       case MAX_EXPR:
+         break;
+
+       default:
+         return NULL_TREE;
+       }
+
       d1 = TREE_REAL_CST (arg1);
       d2 = TREE_REAL_CST (arg2);
 
@@ -1605,6 +1625,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          | TREE_CONSTANT_OVERFLOW (arg2);
       return t;
     }
+
   if (TREE_CODE (arg1) == COMPLEX_CST)
     {
       tree type = TREE_TYPE (arg1);
@@ -1680,11 +1701,11 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        default:
-         gcc_unreachable ();
+         return NULL_TREE;
        }
       return t;
     }
-  return 0;
+  return NULL_TREE;
 }
 
 /* Create a size type INT_CST node with NUMBER sign extended.  KIND
@@ -7171,80 +7192,57 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
   tree arg0 = NULL_TREE, arg1 = NULL_TREE;
   enum tree_code_class kind = TREE_CODE_CLASS (code);
 
-  /* WINS will be nonzero when the switch is done
-     if all operands are constant.  */
-  int wins = 1;
-
   gcc_assert (IS_EXPR_CODE_CLASS (kind)
-             && TREE_CODE_LENGTH (code) == 2);
+             && TREE_CODE_LENGTH (code) == 2
+             && op0 != NULL_TREE
+             && op1 != NULL_TREE);
 
   arg0 = op0;
   arg1 = op1;
 
-  if (arg0)
-    {
-      tree subop;
-
-      /* Strip any conversions that don't change the mode.  This is
-        safe for every expression, except for a comparison expression
-        because its signedness is derived from its operands.  So, in
-        the latter case, only strip conversions that don't change the
-        signedness.
-
-        Note that this is done as an internal manipulation within the
-        constant folder, in order to find the simplest representation
-        of the arguments so that their form can be studied.  In any
-        cases, the appropriate type conversions should be put back in
-        the tree that will get out of the constant folder.  */
-      if (kind == tcc_comparison)
-       STRIP_SIGN_NOPS (arg0);
-      else
-       STRIP_NOPS (arg0);
+  /* Strip any conversions that don't change the mode.  This is
+     safe for every expression, except for a comparison expression
+     because its signedness is derived from its operands.  So, in
+     the latter case, only strip conversions that don't change the
+     signedness.
 
-      if (TREE_CODE (arg0) == COMPLEX_CST)
-       subop = TREE_REALPART (arg0);
-      else
-       subop = arg0;
+     Note that this is done as an internal manipulation within the
+     constant folder, in order to find the simplest representation
+     of the arguments so that their form can be studied.  In any
+     cases, the appropriate type conversions should be put back in
+     the tree that will get out of the constant folder.  */
 
-      if (TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
+  if (kind == tcc_comparison)
+    {
+      STRIP_SIGN_NOPS (arg0);
+      STRIP_SIGN_NOPS (arg1);
     }
-
-  if (arg1)
+  else
     {
-      tree subop;
-
-      /* Strip any conversions that don't change the mode.  This is
-        safe for every expression, except for a comparison expression
-        because its signedness is derived from its operands.  So, in
-        the latter case, only strip conversions that don't change the
-        signedness.
-
-        Note that this is done as an internal manipulation within the
-        constant folder, in order to find the simplest representation
-        of the arguments so that their form can be studied.  In any
-        cases, the appropriate type conversions should be put back in
-        the tree that will get out of the constant folder.  */
-      if (kind == tcc_comparison)
-       STRIP_SIGN_NOPS (arg1);
-      else
-       STRIP_NOPS (arg1);
+      STRIP_NOPS (arg0);
+      STRIP_NOPS (arg1);
+    }
 
-      if (TREE_CODE (arg1) == COMPLEX_CST)
-       subop = TREE_REALPART (arg1);
+  /* Note that TREE_CONSTANT isn't enough: static var addresses are
+     constant but we can't do arithmetic on them.  */
+  if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
+      || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
+      || (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST)
+      || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST))
+    {
+      if (kind == tcc_binary)
+       tem = const_binop (code, arg0, arg1, 0);
+      else if (kind == tcc_comparison)
+       tem = fold_relational_const (code, type, arg0, arg1);
       else
-       subop = arg1;
+       tem = NULL_TREE;
 
-      if (TREE_CODE (subop) != INTEGER_CST
-         && TREE_CODE (subop) != REAL_CST)
-       /* Note that TREE_CONSTANT isn't enough:
-          static var addresses are constant but we can't
-          do arithmetic on them.  */
-       wins = 0;
+      if (tem != NULL_TREE)
+       {
+         if (TREE_TYPE (tem) != type)
+           tem = fold_convert (type, tem);
+         return tem;
+       }
     }
 
   /* If this is a commutative operation, and ARG0 is a constant, move it
@@ -7253,9 +7251,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       && tree_swap_operands_p (arg0, arg1, true))
     return fold_build2 (code, type, op1, op0);
 
-  /* Now WINS is set as described above,
-     ARG0 is the first operand of EXPR,
-     and ARG1 is the second operand (if it has more than one operand).
+  /* ARG0 is the first operand of EXPR, and ARG1 is the second operand.
 
      First check for cases where an arithmetic operation is applied to a
      compound, conditional, or comparison operation.  Push the arithmetic
@@ -7577,8 +7573,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         don't associate floats at all, unless the user has specified
         -funsafe-math-optimizations.  */
 
-      if (! wins
-         && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
+      if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)
        {
          tree var0, con0, lit0, minus_lit0;
          tree var1, con1, lit1, minus_lit1;
@@ -7652,18 +7647,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            }
        }
 
-    binary:
-      if (wins)
-       t1 = const_binop (code, arg0, arg1, 0);
-      if (t1 != NULL_TREE)
-       {
-         /* The return value should always have
-            the same type as the original expression.  */
-         if (TREE_TYPE (t1) != type)
-           t1 = fold_convert (type, t1);
-
-         return t1;
-       }
       return NULL_TREE;
 
     case MINUS_EXPR:
@@ -7691,7 +7674,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 
       if (! FLOAT_TYPE_P (type))
        {
-         if (! wins && integer_zerop (arg0))
+         if (integer_zerop (arg0))
            return negate_expr (fold_convert (type, arg1));
          if (integer_zerop (arg1))
            return non_lvalue (fold_convert (type, arg0));
@@ -7739,7 +7722,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0).  So check whether
         ARG0 is zero and X + ARG0 reduces to X, since that would mean
         (-ARG1 + ARG0) reduces to -ARG1.  */
-      else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+      else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
        return negate_expr (fold_convert (type, arg1));
 
       /* Fold &x - &x.  This can happen from &x.foo - &x.
@@ -7753,7 +7736,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return fold_convert (type, integer_zero_node);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
-      if (!wins && negate_expr_p (arg1)
+      if (negate_expr_p (arg1)
          && ((FLOAT_TYPE_P (type)
                /* Avoid this transformation if B is a positive REAL_CST.  */
               && (TREE_CODE (arg1) != REAL_CST
@@ -8488,7 +8471,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              return fold_build2 (MULT_EXPR, type, arg0, arg1);
            }
        }
-      goto binary;
+      return NULL_TREE;
 
     case TRUNC_DIV_EXPR:
     case ROUND_DIV_EXPR:
@@ -8533,7 +8516,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE)))
        return fold_convert (type, tem);
 
-      goto binary;
+      return NULL_TREE;
 
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
@@ -8613,7 +8596,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE)))
        return fold_convert (type, tem);
 
-      goto binary;
+      return NULL_TREE;
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -8727,7 +8710,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type))))
        return TREE_OPERAND (arg0, 0);
 
-      goto binary;
+      return NULL_TREE;
 
     case MIN_EXPR:
       if (operand_equal_p (arg0, arg1, 0))
@@ -9998,7 +9981,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       return pedantic_non_lvalue (tem);
 
     case COMPLEX_EXPR:
-      if (wins)
+      if ((TREE_CODE (arg0) == REAL_CST
+          && TREE_CODE (arg1) == REAL_CST)
+         || (TREE_CODE (arg0) == INTEGER_CST
+             && TREE_CODE (arg1) == INTEGER_CST))
        return build_complex (type, arg0, arg1);
       return NULL_TREE;