OSDN Git Service

PR middle-end/17055
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index e85ead8..10cdb69 100644 (file)
@@ -89,8 +89,7 @@ static tree negate_expr (tree);
 static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
 static tree associate_trees (tree, tree, enum tree_code, tree);
 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 build_zero_vector (tree);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code, bool);
 static enum comparison_code comparison_to_compcode (enum tree_code);
@@ -209,8 +208,7 @@ force_fit_type (tree t, int overflowable,
   unsigned int prec;
   int sign_extended_type;
 
-  if (TREE_CODE (t) != INTEGER_CST)
-    abort ();
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
   
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
@@ -268,7 +266,7 @@ force_fit_type (tree t, int overflowable,
   if (overflowed || overflowed_const
       || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
     {
-      t = build_int_cst (TREE_TYPE (t), low, high);
+      t = build_int_cst_wide (TREE_TYPE (t), low, high);
       
       if (overflowed
          || overflowable < 0
@@ -827,7 +825,7 @@ div_and_round_double (enum tree_code code, int uns,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Compute true remainder:  rem = num - (quo * den)  */
@@ -865,14 +863,43 @@ negate_mathfn_p (enum built_in_function code)
   return false;
 }
 
+/* Check whether we may negate an integer constant T without causing
+   overflow.  */
+
+bool
+may_negate_without_overflow_p (tree t)
+{
+  unsigned HOST_WIDE_INT val;
+  unsigned int prec;
+  tree type;
+
+  gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+  type = TREE_TYPE (t);
+  if (TYPE_UNSIGNED (type))
+    return false;
+
+  prec = TYPE_PRECISION (type);
+  if (prec > HOST_BITS_PER_WIDE_INT)
+    {
+      if (TREE_INT_CST_LOW (t) != 0)
+       return true;
+      prec -= HOST_BITS_PER_WIDE_INT;
+      val = TREE_INT_CST_HIGH (t);
+    }
+  else
+    val = TREE_INT_CST_LOW (t);
+  if (prec < HOST_BITS_PER_WIDE_INT)
+    val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
+  return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+}
+
 /* Determine whether an expression T can be cheaply negated using
    the function negate_expr.  */
 
 static bool
 negate_expr_p (tree t)
 {
-  unsigned HOST_WIDE_INT val;
-  unsigned int prec;
   tree type;
 
   if (t == 0)
@@ -888,19 +915,7 @@ negate_expr_p (tree t)
        return true;
 
       /* Check that -CST will not overflow type.  */
-      prec = TYPE_PRECISION (type);
-      if (prec > HOST_BITS_PER_WIDE_INT)
-       {
-         if (TREE_INT_CST_LOW (t) != 0)
-           return true;
-         prec -= HOST_BITS_PER_WIDE_INT;
-         val = TREE_INT_CST_HIGH (t);
-       }
-      else
-       val = TREE_INT_CST_LOW (t);
-      if (prec < HOST_BITS_PER_WIDE_INT)
-       val &= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
-      return val != ((unsigned HOST_WIDE_INT) 1 << (prec - 1));
+      return may_negate_without_overflow_p (t);
 
     case REAL_CST:
     case NEGATE_EXPR:
@@ -1409,10 +1424,10 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  t = build_int_cst (TREE_TYPE (arg1), low, hi);
+  t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
 
   if (notrunc)
     {
@@ -1572,108 +1587,22 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return t;
     }
   return 0;
 }
 
-/* These are the hash table functions for the hash table of INTEGER_CST
-   nodes of a sizetype.  */
-
-/* Return the hash code code X, an INTEGER_CST.  */
-
-static hashval_t
-size_htab_hash (const void *x)
-{
-  tree t = (tree) x;
-
-  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
-         ^ htab_hash_pointer (TREE_TYPE (t))
-         ^ (TREE_OVERFLOW (t) << 20));
-}
-
-/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
-   is the same as that given by *Y, which is the same.  */
-
-static int
-size_htab_eq (const void *x, const void *y)
-{
-  tree xt = (tree) x;
-  tree yt = (tree) y;
-
-  return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
-         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt)
-         && TREE_TYPE (xt) == TREE_TYPE (yt)
-         && TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt));
-}
-\f
-/* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT
-   bits are given by NUMBER and of the sizetype represented by KIND.  */
+/* Create a size type INT_CST node with NUMBER sign extended.  KIND
+   indicates which particular sizetype to create.  */
 
 tree
 size_int_kind (HOST_WIDE_INT number, enum size_type_kind kind)
 {
-  return size_int_type (number, sizetype_tab[(int) kind]);
-}
-
-/* Likewise, but the desired type is specified explicitly.  */
-
-static GTY (()) tree new_const;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-     htab_t size_htab;
-
-tree
-size_int_type (HOST_WIDE_INT number, tree type)
-{
-  void **slot;
-  unsigned int prec;
-  HOST_WIDE_INT high;
-  unsigned HOST_WIDE_INT low;
-
-  if (size_htab == 0)
-    {
-      size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
-      new_const = make_node (INTEGER_CST);
-    }
-
-  /* Adjust NEW_CONST to be the constant we want.  If it's already in the
-     hash table, we return the value from the hash table.  Otherwise, we
-     place that in the hash table and make a new node for the next time.  */
-  prec = TYPE_PRECISION (type);
-  TREE_TYPE (new_const) = type;
-  TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const) = 0;
-  low = number;
-  if (number >= 0)
-    high = 0;
-  else
-    {
-      /* Sizetype IS sign extended.  */
-      high = -1;
-      if (prec <= HOST_BITS_PER_WIDE_INT)
-       low |= (HOST_WIDE_INT)(-1) << (prec - 1);
-    }
-  TREE_INT_CST_LOW (new_const) = low;
-  TREE_INT_CST_HIGH (new_const) = high;
-
-  if (low != (unsigned HOST_WIDE_INT)number
-      || high != (number < 0 ? -1 : 0))
-    TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const) = 1;
-  
-  slot = htab_find_slot (size_htab, new_const, INSERT);
-  if (*slot == 0)
-    {
-      tree t = new_const;
-
-      *slot = new_const;
-      new_const = make_node (INTEGER_CST);
-      return t;
-    }
-  else
-    return (tree) *slot;
+  return build_int_cst (sizetype_tab[(int) kind], number);
 }
-
+\f
 /* Combine operands OP1 and OP2 with arithmetic operation CODE.  CODE
    is a tree code.  The type of the result is taken from the operands.
    Both must be the same type integer type and it must be a size type.
@@ -1684,9 +1613,8 @@ size_binop (enum tree_code code, tree arg0, tree arg1)
 {
   tree type = TREE_TYPE (arg0);
 
-  if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
-      || type != TREE_TYPE (arg1))
-    abort ();
+  gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
+             && type == TREE_TYPE (arg1));
 
   /* Handle the special case of two integer constants faster.  */
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
@@ -1720,16 +1648,14 @@ size_diffop (tree arg0, tree arg1)
   tree type = TREE_TYPE (arg0);
   tree ctype;
 
-  if (TREE_CODE (type) != INTEGER_TYPE || ! TYPE_IS_SIZETYPE (type)
-      || type != TREE_TYPE (arg1))
-    abort ();
+  gcc_assert (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)
+             && type == TREE_TYPE (arg1));
 
   /* If the type is already signed, just do the simple thing.  */
   if (!TYPE_UNSIGNED (type))
     return size_binop (MINUS_EXPR, arg0, arg1);
 
-  ctype = (type == bitsizetype || type == ubitsizetype
-          ? sbitsizetype : ssizetype);
+  ctype = type == bitsizetype ? sbitsizetype : ssizetype;
 
   /* If either operand is not a constant, do the conversions to the signed
      type and subtract.  The hardware will do the right thing with any
@@ -1752,6 +1678,23 @@ size_diffop (tree arg0, tree arg1)
                                                        arg1, arg0)));
 }
 \f
+/* Construct a vector of zero elements of vector type TYPE.  */
+
+static tree
+build_zero_vector (tree type)
+{
+  tree elem, list;
+  int i, units;
+
+  elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+  units = TYPE_VECTOR_SUBPARTS (type);
+
+  list = NULL_TREE;
+  for (i = 0; i < units; i++)
+    list = tree_cons (NULL_TREE, elem, list);
+  return build_vector (type, list);
+}
+
 
 /* Attempt to fold type conversion operation CODE of expression ARG1 to
    type TYPE.  If no simplification can be done return NULL_TREE.  */
@@ -1776,8 +1719,8 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
 
          /* Given an integer constant, make new constant with new type,
             appropriately sign-extended or truncated.  */
-         t = build_int_cst (type, TREE_INT_CST_LOW (arg1),
-                            TREE_INT_CST_HIGH (arg1));
+         t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
+                                 TREE_INT_CST_HIGH (arg1));
 
          t = force_fit_type (t,
                              /* Don't set the overflow when
@@ -1824,7 +1767,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          /* If R is NaN, return zero and show we have an overflow.  */
@@ -1868,7 +1811,7 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
          if (! overflow)
            REAL_VALUE_TO_INT (&low, &high, r);
 
-         t = build_int_cst (type, low, high);
+         t = build_int_cst_wide (type, low, high);
 
          t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
                              TREE_CONSTANT_OVERFLOW (arg1));
@@ -1925,9 +1868,11 @@ fold_convert (tree type, tree arg)
                                        TYPE_MAIN_VARIANT (orig)))
     return fold (build1 (NOP_EXPR, type, arg));
 
-  if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
+  switch (TREE_CODE (type))
     {
+    case INTEGER_TYPE: case CHAR_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+    case POINTER_TYPE: case REFERENCE_TYPE:
+    case OFFSET_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
          tem = fold_convert_const (NOP_EXPR, type, arg);
@@ -1942,12 +1887,11 @@ fold_convert (tree type, tree arg)
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
        }
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-    }
-  else if (TREE_CODE (type) == REAL_TYPE)
-    {
+      gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
+                 && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
+      return fold (build1 (NOP_EXPR, type, arg));
+      
+    case REAL_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
          tem = fold_convert_const (FLOAT_EXPR, type, arg);
@@ -1961,56 +1905,72 @@ fold_convert (tree type, tree arg)
            return tem;
        }
 
-      if (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
-        return fold (build1 (FLOAT_EXPR, type, arg));
-      if (TREE_CODE (orig) == REAL_TYPE)
-       return fold (build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,
-                            type, arg));
-      if (TREE_CODE (orig) == COMPLEX_TYPE)
+      switch (TREE_CODE (orig))
        {
+       case INTEGER_TYPE: case CHAR_TYPE:
+       case BOOLEAN_TYPE: case ENUMERAL_TYPE:
+       case POINTER_TYPE: case REFERENCE_TYPE:
+         return fold (build1 (FLOAT_EXPR, type, arg));
+         
+       case REAL_TYPE:
+         return fold (build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,
+                              type, arg));
+         
+       case COMPLEX_TYPE:
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
+         
+       default:
+         gcc_unreachable ();
        }
-    }
-  else if (TREE_CODE (type) == COMPLEX_TYPE)
-    {
-      if (INTEGRAL_TYPE_P (orig)
-         || POINTER_TYPE_P (orig)
-         || TREE_CODE (orig) == REAL_TYPE)
-       return build2 (COMPLEX_EXPR, type,
-                      fold_convert (TREE_TYPE (type), arg),
-                      fold_convert (TREE_TYPE (type), integer_zero_node));
-      if (TREE_CODE (orig) == COMPLEX_TYPE)
-       {
-         tree rpart, ipart;
+      
+    case COMPLEX_TYPE:
+      switch (TREE_CODE (orig))
+       {
+       case INTEGER_TYPE: case CHAR_TYPE:
+       case BOOLEAN_TYPE: case ENUMERAL_TYPE:
+       case POINTER_TYPE: case REFERENCE_TYPE:
+       case REAL_TYPE:
+         return build2 (COMPLEX_EXPR, type,
+                        fold_convert (TREE_TYPE (type), arg),
+                        fold_convert (TREE_TYPE (type), integer_zero_node));
+       case COMPLEX_TYPE:
+         {
+           tree rpart, ipart;
+           
+           if (TREE_CODE (arg) == COMPLEX_EXPR)
+             {
+               rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
+               ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
+               return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
+             }
+           
+           arg = save_expr (arg);
+           rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
+           ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
+           rpart = fold_convert (TREE_TYPE (type), rpart);
+           ipart = fold_convert (TREE_TYPE (type), ipart);
+           return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
+         }
+         
+       default:
+         gcc_unreachable ();
+       }
+      
+    case VECTOR_TYPE:
+      if (integer_zerop (arg))
+       return build_zero_vector (type);
+      gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
+      gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
+                 || TREE_CODE (orig) == VECTOR_TYPE);
+      return fold (build1 (NOP_EXPR, type, arg));
 
-         if (TREE_CODE (arg) == COMPLEX_EXPR)
-           {
-             rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
-             ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
-             return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
-           }
+    case VOID_TYPE:
+      return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
 
-         arg = save_expr (arg);
-         rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
-         ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
-         rpart = fold_convert (TREE_TYPE (type), rpart);
-         ipart = fold_convert (TREE_TYPE (type), ipart);
-         return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
-       }
-    }
-  else if (TREE_CODE (type) == VECTOR_TYPE)
-    {
-      if ((INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
-      if (TREE_CODE (orig) == VECTOR_TYPE
-         && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
-       return fold (build1 (NOP_EXPR, type, arg));
+    default:
+      gcc_unreachable ();
     }
-  else if (VOID_TYPE_P (type))
-    return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
-  abort ();
 }
 \f
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
@@ -2119,7 +2079,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
     case UNORDERED_EXPR:
       return ORDERED_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2143,7 +2103,7 @@ swap_tree_comparison (enum tree_code code)
     case LE_EXPR:
       return GE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2186,7 +2146,7 @@ comparison_to_compcode (enum tree_code code)
     case UNGE_EXPR:
       return COMPCODE_UNGE;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2228,7 +2188,7 @@ compcode_to_comparison (enum comparison_code code)
     case COMPCODE_UNGE:
       return UNGE_EXPR;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2462,10 +2422,21 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
     {
     case '1':
       /* Two conversions are equal only if signedness and modes match.  */
-      if ((TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == CONVERT_EXPR)
-         && (TYPE_UNSIGNED (TREE_TYPE (arg0))
-             != TYPE_UNSIGNED (TREE_TYPE (arg1))))
-       return 0;
+      switch (TREE_CODE (arg0))
+        {
+        case NOP_EXPR:
+        case CONVERT_EXPR:
+        case FIX_CEIL_EXPR:
+        case FIX_TRUNC_EXPR:
+        case FIX_FLOOR_EXPR:
+        case FIX_ROUND_EXPR:
+         if (TYPE_UNSIGNED (TREE_TYPE (arg0))
+             != TYPE_UNSIGNED (TREE_TYPE (arg1)))
+           return 0;
+         break;
+       default:
+         break;
+       }
 
       return operand_equal_p (TREE_OPERAND (arg0, 0),
                              TREE_OPERAND (arg1, 0), flags);
@@ -2943,7 +2914,7 @@ invert_truthvalue (tree arg)
     {
     case INTEGER_CST:
       return fold_convert (type,
-                          build_int_cst (NULL_TREE, integer_zerop (arg), 0));
+                          build_int_cst (NULL_TREE, integer_zerop (arg)));
 
     case TRUTH_AND_EXPR:
       return build2 (TRUTH_OR_EXPR, type,
@@ -3019,8 +2990,7 @@ invert_truthvalue (tree arg)
     default:
       break;
     }
-  if (TREE_CODE (TREE_TYPE (arg)) != BOOLEAN_TYPE)
-    abort ();
+  gcc_assert (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE);
   return build1 (TRUTH_NOT_EXPR, type, arg);
 }
 
@@ -3178,7 +3148,7 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
     lbitpos = nbitsize - lbitsize - lbitpos;
 
   /* Make the mask to be used against the extracted field.  */
-  mask = build_int_cst (unsigned_type, ~0, ~0);
+  mask = build_int_cst (unsigned_type, -1);
   mask = force_fit_type (mask, 0, false, false);
   mask = fold_convert (unsigned_type, mask);
   mask = const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - lbitsize), 0);
@@ -3334,7 +3304,7 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
   unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
   precision = TYPE_PRECISION (unsigned_type);
 
-  mask = build_int_cst (unsigned_type, ~0, ~0);
+  mask = build_int_cst (unsigned_type, -1);
   mask = force_fit_type (mask, 0, false, false);
   
   mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
@@ -3360,7 +3330,7 @@ all_ones_mask_p (tree mask, int size)
   unsigned int precision = TYPE_PRECISION (type);
   tree tmask;
 
-  tmask = build_int_cst (lang_hooks.types.signed_type (type), ~0, ~0);
+  tmask = build_int_cst (lang_hooks.types.signed_type (type), -1);
   tmask = force_fit_type (tmask, 0, false, false);
   
   return
@@ -3546,7 +3516,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
       result = sgn0 >= sgn1;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return constant_boolean_node (result, type);
@@ -3635,7 +3605,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
              in_p = ! in_p, low = 0, high = arg1;
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          /* If this is an unsigned comparison, we also know that EXP is
@@ -4211,7 +4181,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
        tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
        return negate_expr (fold_convert (type, tem));
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
   /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
@@ -4307,7 +4277,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
            }
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -4377,7 +4347,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
       case NE_EXPR:
        break;
       default:
-       abort ();
+       gcc_unreachable ();
       }
 
   return NULL_TREE;
@@ -5348,7 +5318,7 @@ constant_boolean_node (int value, tree type)
     return lang_hooks.truthvalue_conversion (value ? integer_one_node
                                                   : integer_zero_node);
   else
-    return build_int_cst (type, value, 0);
+    return build_int_cst (type, value);
 }
 
 /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
@@ -5681,7 +5651,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                         TREE_INT_CST_HIGH (arg01),
                         TREE_INT_CST_LOW (arg1),
                         TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
-  prod = build_int_cst (TREE_TYPE (arg00), lpart, hpart);
+  prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
   prod = force_fit_type (prod, -1, overflow, false);
 
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
@@ -5695,7 +5665,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
                             TREE_INT_CST_LOW (tmp),
                             TREE_INT_CST_HIGH (tmp),
                             &lpart, &hpart);
-      hi = build_int_cst (TREE_TYPE (arg00), lpart, hpart);
+      hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
       hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
                           TREE_CONSTANT_OVERFLOW (prod));
     }
@@ -5720,7 +5690,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   else
@@ -5744,7 +5714,7 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -6603,7 +6573,7 @@ fold (tree expr)
                    {
                      alt0 = fold (build2 (MULT_EXPR, type, arg00,
                                           build_int_cst (NULL_TREE,
-                                                         int01 / int11, 0)));
+                                                         int01 / int11)));
                      alt1 = arg10;
                      same = arg11;
                    }
@@ -7237,7 +7207,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7246,7 +7216,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7286,7 +7256,7 @@ fold (tree expr)
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg1);
        }
@@ -7295,7 +7265,7 @@ fold (tree expr)
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = build_int_cst (type, -1, -1);
+         t1 = build_int_cst (type, -1);
          t1 = force_fit_type (t1, 0, false, false);
          return omit_one_operand (type, t1, arg0);
        }
@@ -7615,7 +7585,7 @@ fold (tree expr)
              low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
            }
 
-         mask = build_int_cst (type, low, high);
+         mask = build_int_cst_wide (type, low, high);
          return fold (build2 (BIT_AND_EXPR, type,
                               fold_convert (type, arg0), mask));
        }
@@ -7674,7 +7644,7 @@ fold (tree expr)
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
          tree tem = build_int_cst (NULL_TREE,
-                                   GET_MODE_BITSIZE (TYPE_MODE (type)), 0);
+                                   GET_MODE_BITSIZE (TYPE_MODE (type)));
          tem = fold_convert (TREE_TYPE (arg1), tem);
          tem = const_binop (MINUS_EXPR, tem, arg1, 0);
          return fold (build2 (RROTATE_EXPR, type, arg0, tem));
@@ -8092,8 +8062,7 @@ fold (tree expr)
                return omit_one_operand (type, folded_compare, varop);
 
              shift = build_int_cst (NULL_TREE,
-                                    TYPE_PRECISION (TREE_TYPE (varop)) - size,
-                                    0);
+                                    TYPE_PRECISION (TREE_TYPE (varop)) - size);
              shift = fold_convert (TREE_TYPE (varop), shift);
              newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
                                       newconst, shift));
@@ -8485,7 +8454,7 @@ fold (tree expr)
            case LT_EXPR:
              return constant_boolean_node (0, type);
            default:
-             abort ();
+             gcc_unreachable ();
            }
        }
 
@@ -9085,10 +9054,9 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
   char buf[sizeof (struct tree_decl)];
   int i, len;
 
-  if (sizeof (struct tree_exp) + 5 * sizeof (tree)
-      > sizeof (struct tree_decl)
-      || sizeof (struct tree_type) > sizeof (struct tree_decl))
-    abort ();
+  gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
+              <= sizeof (struct tree_decl))
+             && sizeof (struct tree_type) <= sizeof (struct tree_decl));
   if (expr == NULL)
     return;
   slot = htab_find_slot (ht, expr, INSERT);
@@ -9616,7 +9584,10 @@ tree_expr_nonzero_p (tree t)
        return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
 
     case INTEGER_CST:
-      return !integer_zerop (t);
+      /* We used to test for !integer_zerop here.  This does not work correctly
+        if TREE_CONSTANT_OVERFLOW (t).  */
+      return (TREE_INT_CST_LOW (t) != 0
+             || TREE_INT_CST_HIGH (t) != 0);
 
     case PLUS_EXPR:
       if (!TYPE_UNSIGNED (type) && !flag_wrapv)
@@ -9651,11 +9622,22 @@ tree_expr_nonzero_p (tree t)
       break;
 
    case ADDR_EXPR:
-      /* Weak declarations may link to NULL.  */
-      if (DECL_P (TREE_OPERAND (t, 0)))
-       return !DECL_WEAK (TREE_OPERAND (t, 0));
-      /* Constants and all other cases are never weak.  */
-      return true;
+      {
+       tree base = get_base_address (TREE_OPERAND (t, 0));
+
+       if (!base)
+         return false;
+
+       /* Weak declarations may link to NULL.  */
+       if (DECL_P (base))
+         return !DECL_WEAK (base);
+
+       /* Constants are never weak.  */
+       if (TREE_CODE_CLASS (TREE_CODE (base)) == 'c')
+         return true;
+
+       return false;
+      }
 
     case COND_EXPR:
       return (tree_expr_nonzero_p (TREE_OPERAND (t, 1))
@@ -9700,50 +9682,6 @@ tree_expr_nonzero_p (tree t)
   return false;
 }
 
-/* Return true if `r' is known to be non-negative.
-   Only handles constants at the moment.  */
-
-int
-rtl_expr_nonnegative_p (rtx r)
-{
-  switch (GET_CODE (r))
-    {
-    case CONST_INT:
-      return INTVAL (r) >= 0;
-
-    case CONST_DOUBLE:
-      if (GET_MODE (r) == VOIDmode)
-       return CONST_DOUBLE_HIGH (r) >= 0;
-      return 0;
-
-    case CONST_VECTOR:
-      {
-       int units, i;
-       rtx elt;
-
-       units = CONST_VECTOR_NUNITS (r);
-
-       for (i = 0; i < units; ++i)
-         {
-           elt = CONST_VECTOR_ELT (r, i);
-           if (!rtl_expr_nonnegative_p (elt))
-             return 0;
-         }
-
-       return 1;
-      }
-
-    case SYMBOL_REF:
-    case LABEL_REF:
-      /* These are always nonnegative.  */
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
-
 /* See if we are applying CODE, a relational to the highest or lowest
    possible integer of TYPE.  If so, then the result is a compile
    time constant.  */
@@ -10316,7 +10254,7 @@ fold_read_from_constant_string (tree exp)
        return fold_convert (TREE_TYPE (exp),
                             build_int_cst (NULL_TREE,
                                            (TREE_STRING_POINTER (string)
-                                            [TREE_INT_CST_LOW (index)]), 0));
+                                            [TREE_INT_CST_LOW (index)])));
     }
   return NULL;
 }
@@ -10331,26 +10269,31 @@ fold_negate_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  switch (TREE_CODE (arg0))
     {
-      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_cst (type, low, high);
-      t = force_fit_type (t, 1,
-                         (overflow | TREE_OVERFLOW (arg0))
-                         && !TYPE_UNSIGNED (type),
-                         TREE_CONSTANT_OVERFLOW (arg0));
-    }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
+    case 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_cst_wide (type, low, high);
+       t = force_fit_type (t, 1,
+                           (overflow | TREE_OVERFLOW (arg0))
+                           && !TYPE_UNSIGNED (type),
+                           TREE_CONSTANT_OVERFLOW (arg0));
+       break;
+      }
+      
+    case REAL_CST:
+      t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+      break;
 
+    default:
+      gcc_unreachable ();
+    }
+  
   return t;
 }
 
@@ -10364,15 +10307,16 @@ fold_abs_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
+  switch (TREE_CODE (arg0))
     {
+    case INTEGER_CST:
       /* If the value is unsigned, then the absolute value is
         the same as the ordinary value.  */
       if (TYPE_UNSIGNED (type))
-       return arg0;
+       t = arg0;
       /* Similarly, if the value is non-negative.  */
       else if (INT_CST_LT (integer_minus_one_node, arg0))
-       return arg0;
+       t = arg0;
       /* If the value is negative, then the absolute value is
         its negation.  */
       else
@@ -10382,24 +10326,23 @@ fold_abs_const (tree arg0, tree type)
          int overflow = neg_double (TREE_INT_CST_LOW (arg0),
                                     TREE_INT_CST_HIGH (arg0),
                                     &low, &high);
-         t = build_int_cst (type, low, high);
+         t = build_int_cst_wide (type, low, high);
          t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0),
                              TREE_CONSTANT_OVERFLOW (arg0));
-         return t;
        }
-    }
-  else if (TREE_CODE (arg0) == REAL_CST)
-    {
+      break;
+      
+    case REAL_CST:
       if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
-       return build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
+       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       else
-       return arg0;
+       t =  arg0;
+      break;
+      
+    default:
+      gcc_unreachable ();
     }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-
+  
   return t;
 }
 
@@ -10411,19 +10354,14 @@ fold_not_const (tree arg0, tree type)
 {
   tree t = NULL_TREE;
 
-  if (TREE_CODE (arg0) == INTEGER_CST)
-    {
-      t = build_int_cst (type,
-                        ~ TREE_INT_CST_LOW (arg0),
-                        ~ TREE_INT_CST_HIGH (arg0));
-      t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
-                         TREE_CONSTANT_OVERFLOW (arg0));
-    }
-#ifdef ENABLE_CHECKING
-  else
-    abort ();
-#endif
-
+  gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
+  
+  t = build_int_cst_wide (type,
+                         ~ TREE_INT_CST_LOW (arg0),
+                         ~ TREE_INT_CST_HIGH (arg0));
+  t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
+                     TREE_CONSTANT_OVERFLOW (arg0));
+  
   return t;
 }
 
@@ -10476,7 +10414,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
              break;
 
            default:
-             abort ();
+             gcc_unreachable ();
            }
 
          return constant_boolean_node (result, type);
@@ -10537,6 +10475,10 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
 tree
 build_fold_addr_expr_with_type (tree t, tree ptrtype)
 {
+  /* The size of the object is not relevant when talking about its address.  */
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
   if (TREE_CODE (t) == INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
@@ -10663,18 +10605,17 @@ round_up (tree value, int divisor)
 {
   tree div = NULL_TREE;
 
-  if (divisor <= 0)
-    abort ();
+  gcc_assert (divisor > 0);
   if (divisor == 1)
     return value;
 
   /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
      have to do anything.  Only do this when we are not given a const,
      because in that case, this check is more expensive than just
-     doing it. */
+     doing it.  */
   if (TREE_CODE (value) != INTEGER_CST)
     {
-      div = size_int_type (divisor, TREE_TYPE (value));
+      div = build_int_cst (TREE_TYPE (value), divisor);
 
       if (multiple_of_p (TREE_TYPE (value), value, div))
        return value;
@@ -10685,15 +10626,15 @@ round_up (tree value, int divisor)
     {
       tree t;
       
-      t = build_int_cst (TREE_TYPE (value), divisor - 1, 0);
+      t = build_int_cst (TREE_TYPE (value), divisor - 1);
       value = size_binop (PLUS_EXPR, value, t);
-      t = build_int_cst (TREE_TYPE (value), -divisor, -1);
+      t = build_int_cst (TREE_TYPE (value), -divisor);
       value = size_binop (BIT_AND_EXPR, value, t);
     }
   else
     {
       if (!div)
-       div = size_int_type (divisor, TREE_TYPE (value));
+       div = build_int_cst (TREE_TYPE (value), divisor);
       value = size_binop (CEIL_DIV_EXPR, value, div);
       value = size_binop (MULT_EXPR, value, div);
     }
@@ -10708,20 +10649,17 @@ round_down (tree value, int divisor)
 {
   tree div = NULL_TREE;
 
-  if (divisor <= 0)
-    abort ();
+  gcc_assert (divisor > 0);
   if (divisor == 1)
     return value;
 
-  div = size_int_type (divisor, TREE_TYPE (value));
-
   /* See if VALUE is already a multiple of DIVISOR.  If so, we don't
      have to do anything.  Only do this when we are not given a const,
      because in that case, this check is more expensive than just
-     doing it. */
+     doing it.  */
   if (TREE_CODE (value) != INTEGER_CST)
     {
-      div = size_int_type (divisor, TREE_TYPE (value));
+      div = build_int_cst (TREE_TYPE (value), divisor);
 
       if (multiple_of_p (TREE_TYPE (value), value, div))
        return value;
@@ -10732,17 +10670,16 @@ round_down (tree value, int divisor)
     {
       tree t;
       
-      t = build_int_cst (TREE_TYPE (value), -divisor, -1);
+      t = build_int_cst (TREE_TYPE (value), -divisor);
       value = size_binop (BIT_AND_EXPR, value, t);
     }
   else
     {
       if (!div)
-       div = size_int_type (divisor, TREE_TYPE (value));
+       div = build_int_cst (TREE_TYPE (value), divisor);
       value = size_binop (FLOOR_DIV_EXPR, value, div);
       value = size_binop (MULT_EXPR, value, div);
     }
 
   return value;
 }
-#include "gt-fold-const.h"