OSDN Git Service

* fold-const.c (fold_convert): Rename to fold_convert_const.
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Jan 2004 22:59:59 +0000 (22:59 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Jan 2004 22:59:59 +0000 (22:59 +0000)
(fold_convert_const): Change arguments to take a tree_code,
a type and the operand/expression to be converted.  Return
NULL_TREE if no simplification is possible.  Add support for
FIX_CEIL_EXPR and FIX_FLOOR_EXPR in addition to FIX_TRUNC_EXPR.
(fold): Handle FIX_CEIL_EXPR and FIX_FLOOR_EXPR.
Adjust call to fold_convert to match new fold_convert_const.
Avoid modifying the tree passed to fold in-place.

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

gcc/ChangeLog
gcc/fold-const.c

index 0d7623b..497575a 100644 (file)
@@ -1,3 +1,14 @@
+2004-01-20  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold_convert): Rename to fold_convert_const.
+       (fold_convert_const): Change arguments to take a tree_code,
+       a type and the operand/expression to be converted.  Return
+       NULL_TREE if no simplification is possible.  Add support for
+       FIX_CEIL_EXPR and FIX_FLOOR_EXPR in addition to FIX_TRUNC_EXPR.
+       (fold): Handle FIX_CEIL_EXPR and FIX_FLOOR_EXPR.
+       Adjust call to fold_convert to match new fold_convert_const.
+       Avoid modifying the tree passed to fold in-place.
+
 2004-01-21  Alan Modra  <amodra@bigpond.net.au>
 
        * config/rs6000/sysv4.h (DWARF2_FRAME_REG_OUT): Define.
index 402a560..d29b86e 100644 (file)
@@ -1,6 +1,6 @@
 /* Fold a constant sub-tree into a single node for C-compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -69,7 +69,7 @@ static tree int_const_binop (enum tree_code, tree, tree, int);
 static tree const_binop (enum tree_code, tree, tree, int);
 static hashval_t size_htab_hash (const void *);
 static int size_htab_eq (const void *, const void *);
-static tree fold_convert (tree, tree);
+static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code);
 static enum tree_code swap_tree_comparison (enum tree_code);
 static int comparison_to_compcode (enum tree_code);
@@ -1657,14 +1657,17 @@ size_diffop (tree arg0, tree arg1)
 }
 \f
 
-/* Given T, a tree representing type conversion of ARG1, a constant,
-   return a constant tree representing the result of conversion.  */
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+   type TYPE.  If no simplification can be done return NULL_TREE.  */
 
 static tree
-fold_convert (tree t, tree arg1)
+fold_convert_const (enum tree_code code, tree type, tree arg1)
 {
-  tree type = TREE_TYPE (t);
   int overflow = 0;
+  tree t;
+
+  if (TREE_TYPE (arg1) == type)
+    return arg1;
 
   if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
     {
@@ -1673,7 +1676,7 @@ fold_convert (tree t, tree arg1)
          /* If we would build a constant wider than GCC supports,
             leave the conversion unfolded.  */
          if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
-           return t;
+           return NULL_TREE;
 
          /* If we are trying to make a sizetype for a small integer, use
             size_int to pick up cached types to reduce duplicate nodes.  */
@@ -1701,6 +1704,7 @@ fold_convert (tree t, tree arg1)
               || TREE_OVERFLOW (arg1));
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         return t;
        }
       else if (TREE_CODE (arg1) == REAL_CST)
        {
@@ -1715,25 +1719,43 @@ fold_convert (tree t, tree arg1)
 
          HOST_WIDE_INT high, low;
 
+         REAL_VALUE_TYPE r;
          REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
-         /* If x is NaN, return zero and show we have an overflow.  */
-         if (REAL_VALUE_ISNAN (x))
+
+         switch (code)
+           {
+           case FIX_TRUNC_EXPR:
+             real_trunc (&r, VOIDmode, &x);
+             break;
+
+           case FIX_CEIL_EXPR:
+             real_ceil (&r, VOIDmode, &x);
+             break;
+
+           case FIX_FLOOR_EXPR:
+             real_floor (&r, VOIDmode, &x);
+             break;
+
+           default:
+             abort ();
+           }
+
+         /* If R is NaN, return zero and show we have an overflow.  */
+         if (REAL_VALUE_ISNAN (r))
            {
              overflow = 1;
              high = 0;
              low = 0;
            }
 
-         /* See if X will be in range after truncation towards 0.
-            To compensate for truncation, move the bounds away from 0,
-            but reject if X exactly equals the adjusted bounds.  */
+         /* See if R is less than the lower bound or greater than the
+            upper bound.  */
 
          if (! overflow)
            {
              tree lt = TYPE_MIN_VALUE (type);
              REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
-             REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
-             if (! REAL_VALUES_LESS (l, x))
+             if (REAL_VALUES_LESS (r, l))
                {
                  overflow = 1;
                  high = TREE_INT_CST_HIGH (lt);
@@ -1747,8 +1769,7 @@ fold_convert (tree t, tree arg1)
              if (ut)
                {
                  REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
-                 REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
-                 if (! REAL_VALUES_LESS (x, u))
+                 if (REAL_VALUES_LESS (u, r))
                    {
                      overflow = 1;
                      high = TREE_INT_CST_HIGH (ut);
@@ -1758,7 +1779,7 @@ fold_convert (tree t, tree arg1)
            }
 
          if (! overflow)
-           REAL_VALUE_TO_INT (&low, &high, x);
+           REAL_VALUE_TO_INT (&low, &high, r);
 
          t = build_int_2 (low, high);
          TREE_TYPE (t) = type;
@@ -1766,8 +1787,8 @@ fold_convert (tree t, tree arg1)
            = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
          TREE_CONSTANT_OVERFLOW (t)
            = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+         return t;
        }
-      TREE_TYPE (t) = type;
     }
   else if (TREE_CODE (type) == REAL_TYPE)
     {
@@ -1795,8 +1816,7 @@ fold_convert (tree t, tree arg1)
          return t;
        }
     }
-  TREE_CONSTANT (t) = 1;
-  return t;
+  return NULL_TREE;
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -5432,8 +5452,8 @@ fold (tree expr)
     case FLOAT_EXPR:
     case CONVERT_EXPR:
     case FIX_TRUNC_EXPR:
-      /* Other kinds of FIX are not handled properly by fold_convert.  */
-
+    case FIX_CEIL_EXPR:
+    case FIX_FLOOR_EXPR:
       if (TREE_TYPE (TREE_OPERAND (t, 0)) == TREE_TYPE (t))
        return TREE_OPERAND (t, 0);
 
@@ -5577,17 +5597,8 @@ fold (tree expr)
                                convert (TREE_TYPE (t), and1)));
        }
 
-      if (!wins)
-       {
-         if (TREE_CONSTANT (t) != TREE_CONSTANT (arg0))
-           {
-             if (t == orig_t)
-               t = copy_node (t);
-             TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
-           }
-         return t;
-       }
-      return fold_convert (t, arg0);
+      tem = fold_convert_const (code, TREE_TYPE (t), arg0);
+      return tem ? tem : t;
 
     case VIEW_CONVERT_EXPR:
       if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)