2007-01-08 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jan 2007 22:17:43 +0000 (22:17 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Jan 2007 22:17:43 +0000 (22:17 +0000)
* builtins.c (fold_builtin_int_roundingfn): Use fit_double_type.
* tree.c (build_int_cst_type): Likewise.
(size_in_bytes): Don't call force_fit_type on the result.
(int_fits_type_p): Use fit_double_type.
* fold-const.c (fit_double_type): New function.
(force_fit_type): Use it.
* tree.h (fit_double_type): Export.

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

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const.c
gcc/tree.c
gcc/tree.h

index df84432..319ed86 100644 (file)
@@ -1,3 +1,13 @@
+2007-01-08  Richard Guenther  <rguenther@suse.de>
+
+       * builtins.c (fold_builtin_int_roundingfn): Use fit_double_type.
+       * tree.c (build_int_cst_type): Likewise.
+       (size_in_bytes): Don't call force_fit_type on the result.
+       (int_fits_type_p): Use fit_double_type.
+       * fold-const.c (fit_double_type): New function.
+       (force_fit_type): Use it.
+       * tree.h (fit_double_type): Export.
+
 2007-01-08  Jan Hubicka  <jh@suse.cz>
 
        * tree-vectorizer.c (gate_increase_alignment): Fix return type.
index e97e3bb..a39a4c1 100644 (file)
@@ -7576,7 +7576,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
       if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
        {
          tree itype = TREE_TYPE (TREE_TYPE (fndecl));
-         tree ftype = TREE_TYPE (arg), result;
+         tree ftype = TREE_TYPE (arg);
+         unsigned HOST_WIDE_INT lo2;
          HOST_WIDE_INT hi, lo;
          REAL_VALUE_TYPE r;
 
@@ -7602,11 +7603,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
            }
 
          REAL_VALUE_TO_INT (&lo, &hi, r);
-         result = build_int_cst_wide (itype, lo, hi);
-         result = force_fit_type (result, 0, false, false);
-         if (TREE_INT_CST_LOW (result) == lo
-             && TREE_INT_CST_HIGH (result) == hi)
-           return result;
+         if (!fit_double_type (lo, hi, &lo2, &hi, itype))
+           return build_int_cst_wide (itype, lo2, hi);
        }
     }
 
index 559acf0..d082ed3 100644 (file)
@@ -192,58 +192,44 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
   *hi = words[2] + words[3] * BASE;
 }
 \f
-/* T is an INT_CST node.  OVERFLOWABLE indicates if we are interested
-   in overflow of the value, when >0 we are only interested in signed
-   overflow, for <0 we are interested in any overflow.  OVERFLOWED
-   indicates whether overflow has already occurred.  CONST_OVERFLOWED
-   indicates whether constant overflow has already occurred.  We force
-   T's value to be within range of T's type (by setting to 0 or 1 all
-   the bits outside the type's range).  We set TREE_OVERFLOWED if,
-       OVERFLOWED is nonzero,
-       or OVERFLOWABLE is >0 and signed overflow occurs
-       or OVERFLOWABLE is <0 and any overflow occurs
-   We set TREE_CONSTANT_OVERFLOWED if,
-        CONST_OVERFLOWED is nonzero
-       or we set TREE_OVERFLOWED.
-  We return either the original T, or a copy.  */
+/* Force the double-word integer L1, H1 to be within the range of the
+   integer type TYPE.  Stores the properly truncated and sign-extended
+   double-word integer in *LV, *HV.  Returns true if the operation
+   overflows, that is, argument and result are different.  */
 
-tree
-force_fit_type (tree t, int overflowable,
-               bool overflowed, bool overflowed_const)
+int
+fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
+                unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, tree type)
 {
-  unsigned HOST_WIDE_INT low;
-  HOST_WIDE_INT high;
+  unsigned HOST_WIDE_INT low0 = l1;
+  HOST_WIDE_INT high0 = h1;
   unsigned int prec;
   int sign_extended_type;
 
-  gcc_assert (TREE_CODE (t) == INTEGER_CST);
-
-  low = TREE_INT_CST_LOW (t);
-  high = TREE_INT_CST_HIGH (t);
-
-  if (POINTER_TYPE_P (TREE_TYPE (t))
-      || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
+  if (POINTER_TYPE_P (type)
+      || TREE_CODE (type) == OFFSET_TYPE)
     prec = POINTER_SIZE;
   else
-    prec = TYPE_PRECISION (TREE_TYPE (t));
+    prec = TYPE_PRECISION (type);
+
   /* Size types *are* sign extended.  */
-  sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
-                       || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
-                           && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
+  sign_extended_type = (!TYPE_UNSIGNED (type)
+                       || (TREE_CODE (type) == INTEGER_TYPE
+                           && TYPE_IS_SIZETYPE (type)));
 
   /* First clear all bits that are beyond the type's precision.  */
-
   if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
     ;
   else if (prec > HOST_BITS_PER_WIDE_INT)
-    high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+    h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
   else
     {
-      high = 0;
+      h1 = 0;
       if (prec < HOST_BITS_PER_WIDE_INT)
-       low &= ~((HOST_WIDE_INT) (-1) << prec);
+       l1 &= ~((HOST_WIDE_INT) (-1) << prec);
     }
 
+  /* Then do sign extension if necessary.  */
   if (!sign_extended_type)
     /* No sign extension */;
   else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
@@ -251,28 +237,70 @@ force_fit_type (tree t, int overflowable,
   else if (prec > HOST_BITS_PER_WIDE_INT)
     {
       /* Sign extend top half? */
-      if (high & ((unsigned HOST_WIDE_INT)1
-                 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
-       high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
+      if (h1 & ((unsigned HOST_WIDE_INT)1
+               << (prec - HOST_BITS_PER_WIDE_INT - 1)))
+       h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
     }
   else if (prec == HOST_BITS_PER_WIDE_INT)
     {
-      if ((HOST_WIDE_INT)low < 0)
-       high = -1;
+      if ((HOST_WIDE_INT)l1 < 0)
+       h1 = -1;
     }
   else
     {
       /* Sign extend bottom half? */
-      if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
+      if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
        {
-         high = -1;
-         low |= (HOST_WIDE_INT)(-1) << prec;
+         h1 = -1;
+         l1 |= (HOST_WIDE_INT)(-1) << prec;
        }
     }
 
+  *lv = l1;
+  *hv = h1;
+
+  /* If the value didn't fit, signal overflow.  */
+  return l1 != low0 || h1 != high0;
+}
+
+/* T is an INT_CST node.  OVERFLOWABLE indicates if we are interested
+   in overflow of the value, when >0 we are only interested in signed
+   overflow, for <0 we are interested in any overflow.  OVERFLOWED
+   indicates whether overflow has already occurred.  CONST_OVERFLOWED
+   indicates whether constant overflow has already occurred.  We force
+   T's value to be within range of T's type (by setting to 0 or 1 all
+   the bits outside the type's range).  We set TREE_OVERFLOWED if,
+       OVERFLOWED is nonzero,
+       or OVERFLOWABLE is >0 and signed overflow occurs
+       or OVERFLOWABLE is <0 and any overflow occurs
+   We set TREE_CONSTANT_OVERFLOWED if,
+        CONST_OVERFLOWED is nonzero
+       or we set TREE_OVERFLOWED.
+  We return either the original T, or a copy.  */
+
+tree
+force_fit_type (tree t, int overflowable,
+               bool overflowed, bool overflowed_const)
+{
+  unsigned HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
+  int sign_extended_type;
+  bool overflow;
+
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+  /* Size types *are* sign extended.  */
+  sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
+                       || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+                           && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
+
+  low = TREE_INT_CST_LOW (t);
+  high = TREE_INT_CST_HIGH (t);
+
+  overflow = fit_double_type (low, high, &low, &high, TREE_TYPE (t));
+
   /* If the value changed, return a new node.  */
-  if (overflowed || overflowed_const
-      || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
+  if (overflowed || overflowed_const || overflow)
     {
       t = build_int_cst_wide (TREE_TYPE (t), low, high);
 
index e3eb4be..348d288 100644 (file)
@@ -779,53 +779,14 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
 tree
 build_int_cst_type (tree type, HOST_WIDE_INT low)
 {
-  unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
-  unsigned HOST_WIDE_INT hi, mask;
-  unsigned bits;
-  bool signed_p;
-  bool negative;
+  unsigned HOST_WIDE_INT low1;
+  HOST_WIDE_INT hi;
 
-  if (!type)
-    type = integer_type_node;
-
-  bits = TYPE_PRECISION (type);
-  signed_p = !TYPE_UNSIGNED (type);
-
-  if (bits >= HOST_BITS_PER_WIDE_INT)
-    negative = (low < 0);
-  else
-    {
-      /* If the sign bit is inside precision of LOW, use it to determine
-        the sign of the constant.  */
-      negative = ((val >> (bits - 1)) & 1) != 0;
-
-      /* Mask out the bits outside of the precision of the constant.  */
-      mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
-
-      if (signed_p && negative)
-       val |= ~mask;
-      else
-       val &= mask;
-    }
-
-  /* Determine the high bits.  */
-  hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
+  gcc_assert (type);
 
-  /* For unsigned type we need to mask out the bits outside of the type
-     precision.  */
-  if (!signed_p)
-    {
-      if (bits <= HOST_BITS_PER_WIDE_INT)
-       hi = 0;
-      else
-       {
-         bits -= HOST_BITS_PER_WIDE_INT;
-         mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
-         hi &= mask;
-       }
-    }
+  fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type);
 
-  return build_int_cst_wide (type, val, hi);
+  return build_int_cst_wide (type, low1, hi);
 }
 
 /* These are the hash table functions for the hash table of INTEGER_CST
@@ -1818,9 +1779,6 @@ size_in_bytes (tree type)
       return size_zero_node;
     }
 
-  if (TREE_CODE (t) == INTEGER_CST)
-    t = force_fit_type (t, 0, false, false);
-
   return t;
 }
 
@@ -6009,12 +5967,13 @@ int_fits_type_p (tree c, tree type)
   tree type_low_bound = TYPE_MIN_VALUE (type);
   tree type_high_bound = TYPE_MAX_VALUE (type);
   bool ok_for_low_bound, ok_for_high_bound;
-  tree tmp;
+  unsigned HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
 
   /* If at least one bound of the type is a constant integer, we can check
      ourselves and maybe make a decision. If no such decision is possible, but
      this type is a subtype, try checking against that.  Otherwise, use
-     force_fit_type, which checks against the precision.
+     fit_double_type, which checks against the precision.
 
      Compute the status for each possibly constant bound, and return if we see
      one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
@@ -6069,12 +6028,10 @@ int_fits_type_p (tree c, tree type)
       && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type)))
     return int_fits_type_p (c, TREE_TYPE (type));
 
-  /* Or to force_fit_type, if nothing else.  */
-  tmp = copy_node (c);
-  TREE_TYPE (tmp) = type;
-  tmp = force_fit_type (tmp, -1, false, false);
-  return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c)
-         && TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c);
+  /* Or to fit_double_type, if nothing else.  */
+  low = TREE_INT_CST_LOW (c);
+  high = TREE_INT_CST_HIGH (c);
+  return !fit_double_type (low, high, &low, &high, type);
 }
 
 /* Subprogram of following function.  Called by walk_tree.
index 9f2d707..fd9e14a 100644 (file)
@@ -4321,6 +4321,8 @@ extern tree fold_indirect_ref_1 (tree, tree);
 
 extern tree force_fit_type (tree, int, bool, bool);
 
+extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+                           unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, tree);
 extern int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
                                 unsigned HOST_WIDE_INT, HOST_WIDE_INT,
                                 unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,