OSDN Git Service

PR tree-optimization/20773
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index c8b6ea6..770ed31 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This file contains the low level primitives for operating on tree nodes,
    including allocation, list operations, interning of identifiers,
@@ -93,6 +93,7 @@ static const char * const tree_node_kind_names[] = {
   "binfos",
   "phi_nodes",
   "ssa names",
+  "constructors",
   "random kinds",
   "lang_decl kinds",
   "lang_type kinds"
@@ -131,12 +132,34 @@ static GTY (()) tree int_cst_node;
 static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
      htab_t int_cst_hash_table;
 
+/* General tree->tree mapping  structure for use in hash tables.  */
+
+
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) 
+     htab_t debug_expr_for_decl;
+
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) 
+     htab_t value_expr_for_decl;
+
+static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
+  htab_t init_priority_for_decl;
+
+struct tree_int_map GTY(())
+{
+  tree from;
+  unsigned short to;
+};
+static unsigned int tree_int_map_hash (const void *);
+static int tree_int_map_eq (const void *, const void *);
+static int tree_int_map_marked_p (const void *);
 static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
 static hashval_t int_cst_hash_hash (const void *);
 static int int_cst_hash_eq (const void *, const void *);
 static void print_type_hash_statistics (void);
+static void print_debug_expr_statistics (void);
+static void print_value_expr_statistics (void);
 static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
 static unsigned int type_hash_list (tree, hashval_t);
@@ -144,18 +167,80 @@ static unsigned int attribute_hash_list (tree, hashval_t);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
+
+unsigned char tree_contains_struct[256][64];
 \f
 /* Init tree.c.  */
 
 void
 init_ttree (void)
 {
+
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                     type_hash_eq, 0);
+
+  debug_expr_for_decl = htab_create_ggc (512, tree_map_hash,
+                                        tree_map_eq, 0);
+
+  value_expr_for_decl = htab_create_ggc (512, tree_map_hash,
+                                        tree_map_eq, 0);
+  init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash,
+                                           tree_int_map_eq, 0);
+
   int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
                                        int_cst_hash_eq, NULL);
+  
   int_cst_node = make_node (INTEGER_CST);
+
+  tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1;
+  tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1;
+  tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1;
+  
+
+  tree_contains_struct[CONST_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[VAR_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[PARM_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[RESULT_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[TYPE_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[LABEL_DECL][TS_DECL_COMMON] = 1;
+  tree_contains_struct[FIELD_DECL][TS_DECL_COMMON] = 1;
+
+
+  tree_contains_struct[CONST_DECL][TS_DECL_WRTL] = 1;
+  tree_contains_struct[VAR_DECL][TS_DECL_WRTL] = 1;
+  tree_contains_struct[PARM_DECL][TS_DECL_WRTL] = 1;
+  tree_contains_struct[RESULT_DECL][TS_DECL_WRTL] = 1;
+  tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL] = 1;
+  tree_contains_struct[LABEL_DECL][TS_DECL_WRTL] = 1; 
+
+  tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1;
+  tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1;
+
+  tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
+  tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1;
+  tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS] = 1;
+  tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS] = 1;
+  
+  tree_contains_struct[VAR_DECL][TS_VAR_DECL] = 1;
+  tree_contains_struct[FIELD_DECL][TS_FIELD_DECL] = 1;
+  tree_contains_struct[PARM_DECL][TS_PARM_DECL] = 1;
+  tree_contains_struct[LABEL_DECL][TS_LABEL_DECL] = 1;
+  tree_contains_struct[RESULT_DECL][TS_RESULT_DECL] = 1;
+  tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1;
+  tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1;
+  tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1;
+
+  lang_hooks.init_ts ();
 }
 
 \f
@@ -167,7 +252,7 @@ decl_assembler_name (tree decl)
 {
   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
     lang_hooks.set_decl_assembler_name (decl);
-  return DECL_CHECK (decl)->decl.assembler_name;
+  return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
 }
 
 /* Compute the number of bytes occupied by a tree with code CODE.
@@ -179,7 +264,29 @@ tree_code_size (enum tree_code code)
   switch (TREE_CODE_CLASS (code))
     {
     case tcc_declaration:  /* A decl node */
-      return sizeof (struct tree_decl);
+      {
+       switch (code)
+         {
+         case FIELD_DECL:
+           return sizeof (struct tree_field_decl);
+         case PARM_DECL:
+           return sizeof (struct tree_parm_decl);
+         case VAR_DECL:
+           return sizeof (struct tree_var_decl);
+         case LABEL_DECL:
+           return sizeof (struct tree_label_decl);
+         case RESULT_DECL:
+           return sizeof (struct tree_result_decl);
+         case CONST_DECL:
+           return sizeof (struct tree_const_decl);
+         case TYPE_DECL:
+           return sizeof (struct tree_type_decl);
+         case FUNCTION_DECL:
+           return sizeof (struct tree_function_decl);
+         default:
+           return sizeof (struct tree_decl_non_common);
+         }
+      }
 
     case tcc_type:  /* a type node */
       return sizeof (struct tree_type);
@@ -222,6 +329,7 @@ tree_code_size (enum tree_code code)
        case STATEMENT_LIST:    return sizeof (struct tree_statement_list);
        case BLOCK:             return sizeof (struct tree_block);
        case VALUE_HANDLE:      return sizeof (struct tree_value_handle);
+       case CONSTRUCTOR:       return sizeof (struct tree_constructor);
 
        default:
          return lang_hooks.tree_size (code);
@@ -312,7 +420,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          kind = id_kind;
          break;
 
-       case TREE_VEC:;
+       case TREE_VEC:
          kind = vec_kind;
          break;
 
@@ -332,6 +440,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          kind = b_kind;
          break;
 
+       case CONSTRUCTOR:
+         kind = constr_kind;
+         break;
+
        default:
          kind = x_kind;
          break;
@@ -347,9 +459,9 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 #endif
 
   if (code == IDENTIFIER_NODE)
-    t = ggc_alloc_zone_stat (length, &tree_id_zone PASS_MEM_STAT);
+    t = ggc_alloc_zone_pass_stat (length, &tree_id_zone);
   else
-    t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+    t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -365,12 +477,13 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       if (code != FUNCTION_DECL)
        DECL_ALIGN (t) = 1;
       DECL_USER_ALIGN (t) = 0;
-      DECL_IN_SYSTEM_HEADER (t) = in_system_header;
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
+      /* We have not yet computed the alias set for this declaration.  */
+      DECL_POINTER_ALIAS_SET (t) = -1;
       DECL_SOURCE_LOCATION (t) = input_location;
       DECL_UID (t) = next_decl_uid++;
 
-      /* We have not yet computed the alias set for this declaration.  */
-      DECL_POINTER_ALIAS_SET (t) = -1;
       break;
 
     case tcc_type:
@@ -433,7 +546,7 @@ copy_node_stat (tree node MEM_STAT_DECL)
   gcc_assert (code != STATEMENT_LIST);
 
   length = tree_size (node);
-  t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
   memcpy (t, node, length);
 
   TREE_CHAIN (t) = 0;
@@ -442,7 +555,21 @@ copy_node_stat (tree node MEM_STAT_DECL)
   t->common.ann = 0;
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
-    DECL_UID (t) = next_decl_uid++;
+    {
+      DECL_UID (t) = next_decl_uid++;
+      if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
+         && DECL_HAS_VALUE_EXPR_P (node))
+       {
+         SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node));
+         DECL_HAS_VALUE_EXPR_P (t) = 1;
+       }
+      if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node))
+       {
+         SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node));
+         DECL_HAS_INIT_PRIORITY_P (t) = 1;
+       }
+      
+    }
   else if (TREE_CODE_CLASS (code) == tcc_type)
     {
       TYPE_UID (t) = next_type_uid++;
@@ -518,7 +645,7 @@ 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;
+  unsigned HOST_WIDE_INT hi, mask;
   unsigned bits;
   bool signed_p;
   bool negative;
@@ -538,10 +665,12 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
       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 = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
+       val |= ~mask;
       else
-       val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+       val &= mask;
     }
 
   /* Determine the high bits.  */
@@ -556,7 +685,8 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
       else
        {
          bits -= HOST_BITS_PER_WIDE_INT;
-         hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
+         mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
+         hi &= mask;
        }
     }
 
@@ -780,27 +910,72 @@ build_vector (tree type, tree vals)
   return v;
 }
 
+/* Return a new VECTOR_CST node whose type is TYPE and whose values
+   are extracted from V, a vector of CONSTRUCTOR_ELT.  */
+
+tree
+build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
+{
+  tree list = NULL_TREE;
+  unsigned HOST_WIDE_INT idx;
+  tree value;
+
+  FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
+    list = tree_cons (NULL_TREE, value, list);
+  return build_vector (type, nreverse (list));
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
-   are in a list pointed to by VALS.  */
+   are in the VEC pointed by VALS.  */
 tree
-build_constructor (tree type, tree vals)
+build_constructor (tree type, VEC(constructor_elt,gc) *vals)
 {
   tree c = make_node (CONSTRUCTOR);
   TREE_TYPE (c) = type;
   CONSTRUCTOR_ELTS (c) = vals;
+  return c;
+}
+
+/* Build a CONSTRUCTOR node made of a single initializer, with the specified
+   INDEX and VALUE.  */
+tree
+build_constructor_single (tree type, tree index, tree value)
+{
+  VEC(constructor_elt,gc) *v;
+  constructor_elt *elt;
+
+  v = VEC_alloc (constructor_elt, gc, 1);
+  elt = VEC_quick_push (constructor_elt, v, NULL);
+  elt->index = index;
+  elt->value = value;
+
+  return build_constructor (type, v);
+}
+
+
+/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
+   are in a list pointed to by VALS.  */
+tree
+build_constructor_from_list (tree type, tree vals)
+{
+  tree t;
+  VEC(constructor_elt,gc) *v = NULL;
 
-  /* ??? May not be necessary.  Mirrors what build does.  */
   if (vals)
     {
-      TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals);
-      TREE_READONLY (c) = TREE_READONLY (vals);
-      TREE_CONSTANT (c) = TREE_CONSTANT (vals);
-      TREE_INVARIANT (c) = TREE_INVARIANT (vals);
+      v = VEC_alloc (constructor_elt, gc, list_length (vals));
+      for (t = vals; t; t = TREE_CHAIN (t))
+       {
+         constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+         elt->index = TREE_PURPOSE (t);
+         elt->value = TREE_VALUE (t);
+       }
     }
 
-  return c;
+  return build_constructor (type, v);
 }
 
+
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
 tree
@@ -918,7 +1093,7 @@ make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
   tree_node_sizes[(int) binfo_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, offsetof (struct tree_binfo, base_binfos));
 
@@ -943,7 +1118,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
   tree_node_sizes[(int) vec_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -1415,8 +1590,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
 {
   tree node;
 
-  node = ggc_alloc_zone_stat (sizeof (struct tree_list),
-                             &tree_zone PASS_MEM_STAT);
+  node = ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone);
 
   memset (node, 0, sizeof (struct tree_common));
 
@@ -1591,7 +1765,7 @@ array_type_nelts (tree type)
 
   return (integer_zerop (min)
          ? max
-         : fold (build2 (MINUS_EXPR, TREE_TYPE (max), max, min)));
+         : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min));
 }
 \f
 /* If arg is static -- a reference to an object in static storage -- then
@@ -1611,7 +1785,7 @@ staticp (tree arg)
 
     case VAR_DECL:
       return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
-             && ! DECL_THREAD_LOCAL (arg)
+             && ! DECL_THREAD_LOCAL_P (arg)
              && ! DECL_NON_ADDR_CONST_P (arg)
              ? arg : NULL);
 
@@ -1773,9 +1947,31 @@ tree_node_structure (tree t)
   enum tree_code code = TREE_CODE (t);
 
   switch (TREE_CODE_CLASS (code))
-    {
+    {      
     case tcc_declaration:
-      return TS_DECL;
+      {
+       switch (code)
+         {
+         case FIELD_DECL:
+           return TS_FIELD_DECL;
+         case PARM_DECL:
+           return TS_PARM_DECL;
+         case VAR_DECL:
+           return TS_VAR_DECL;
+         case LABEL_DECL:
+           return TS_LABEL_DECL;
+         case RESULT_DECL:
+           return TS_RESULT_DECL;
+         case CONST_DECL:
+           return TS_CONST_DECL;
+         case TYPE_DECL:
+           return TS_TYPE_DECL;
+         case FUNCTION_DECL:
+           return TS_FUNCTION_DECL;
+         default:
+           return TS_DECL_NON_COMMON;
+         }
+      }
     case tcc_type:
       return TS_TYPE;
     case tcc_reference:
@@ -1806,6 +2002,7 @@ tree_node_structure (tree t)
     case PLACEHOLDER_EXPR:     return TS_COMMON;
     case STATEMENT_LIST:       return TS_STATEMENT_LIST;
     case BLOCK:                        return TS_BLOCK;
+    case CONSTRUCTOR:          return TS_CONSTRUCTOR;
     case TREE_BINFO:           return TS_BINFO;
     case VALUE_HANDLE:         return TS_VALUE_HANDLE;
 
@@ -2012,8 +2209,8 @@ substitute_in_expr (tree exp, tree f, tree r)
      if (op0 == TREE_OPERAND (exp, 0))
        return exp;
 
-     new = fold (build3 (COMPONENT_REF, TREE_TYPE (exp),
-                        op0, TREE_OPERAND (exp, 1), NULL_TREE));
+     new = fold_build3 (COMPONENT_REF, TREE_TYPE (exp),
+                       op0, TREE_OPERAND (exp, 1), NULL_TREE);
    }
   else
     switch (TREE_CODE_CLASS (code))
@@ -2038,7 +2235,7 @@ substitute_in_expr (tree exp, tree f, tree r)
            if (op0 == TREE_OPERAND (exp, 0))
              return exp;
 
-           new = fold (build1 (code, TREE_TYPE (exp), op0));
+           new = fold_build1 (code, TREE_TYPE (exp), op0);
            break;
 
          case 2:
@@ -2048,7 +2245,7 @@ substitute_in_expr (tree exp, tree f, tree r)
            if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
              return exp;
 
-           new = fold (build2 (code, TREE_TYPE (exp), op0, op1));
+           new = fold_build2 (code, TREE_TYPE (exp), op0, op1);
            break;
 
          case 3:
@@ -2060,7 +2257,7 @@ substitute_in_expr (tree exp, tree f, tree r)
                && op2 == TREE_OPERAND (exp, 2))
              return exp;
 
-           new = fold (build3 (code, TREE_TYPE (exp), op0, op1, op2));
+           new = fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
            break;
 
          default:
@@ -2116,7 +2313,7 @@ substitute_placeholder_in_expr (tree exp, tree obj)
        if (POINTER_TYPE_P (TREE_TYPE (elt))
            && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
                == need_type))
-         return fold (build1 (INDIRECT_REF, need_type, elt));
+         return fold_build1 (INDIRECT_REF, need_type, elt);
 
       /* If we didn't find it, return the original PLACEHOLDER_EXPR.  If it
         survives until RTL generation, there will be an error.  */
@@ -2158,7 +2355,7 @@ substitute_placeholder_in_expr (tree exp, tree obj)
            if (op0 == TREE_OPERAND (exp, 0))
              return exp;
            else
-             return fold (build1 (code, TREE_TYPE (exp), op0));
+             return fold_build1 (code, TREE_TYPE (exp), op0);
 
          case 2:
            op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
@@ -2167,7 +2364,7 @@ substitute_placeholder_in_expr (tree exp, tree obj)
            if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
              return exp;
            else
-             return fold (build2 (code, TREE_TYPE (exp), op0, op1));
+             return fold_build2 (code, TREE_TYPE (exp), op0, op1);
 
          case 3:
            op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
@@ -2178,7 +2375,7 @@ substitute_placeholder_in_expr (tree exp, tree obj)
                && op2 == TREE_OPERAND (exp, 2))
              return exp;
            else
-             return fold (build3 (code, TREE_TYPE (exp), op0, op1, op2));
+             return fold_build3 (code, TREE_TYPE (exp), op0, op1, op2);
 
          case 4:
            op0 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), obj);
@@ -2425,6 +2622,8 @@ do { tree _node = (NODE); \
        UPDATE_TITCSE (TREE_OPERAND (node, 2));
     }
 
+  node = lang_hooks.expr_to_decl (node, &tc, &ti, &se);
+
   /* Now see what's inside.  If it's an INDIRECT_REF, copy our properties from
      the address, since &(*a)->b is a form of addition.  If it's a decl, it's
      invariant and constant if the decl is static.  It's also invariant if it's
@@ -2439,7 +2638,8 @@ do { tree _node = (NODE); \
        ;
       else if (decl_function_context (node) == current_function_decl
               /* Addresses of thread-local variables are invariant.  */
-              || (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node)))
+              || (TREE_CODE (node) == VAR_DECL
+                  && DECL_THREAD_LOCAL_P (node)))
        tc = false;
       else
        ti = tc = false;
@@ -2509,7 +2709,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 
   gcc_assert (TREE_CODE_LENGTH (code) == 1);
 
-  t = ggc_alloc_zone_stat (length, &tree_zone PASS_MEM_STAT);
+  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, sizeof (struct tree_common));
 
@@ -2534,13 +2734,7 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
     TREE_SIDE_EFFECTS (t) = 1;
   else switch (code)
     {
-    case INIT_EXPR:
-    case MODIFY_EXPR:
     case VA_ARG_EXPR:
-    case PREDECREMENT_EXPR:
-    case PREINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
       /* All of these have side-effects, no matter what their
         operands are.  */
       TREE_SIDE_EFFECTS (t) = 1;
@@ -2704,12 +2898,41 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
   return t;
 }
 
+tree
+build7_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+            tree arg2, tree arg3, tree arg4, tree arg5,
+            tree arg6 MEM_STAT_DECL)
+{
+  bool constant, read_only, side_effects, invariant;
+  tree t;
+
+  gcc_assert (code == TARGET_MEM_REF);
+
+  t = make_node_stat (code PASS_MEM_STAT);
+  TREE_TYPE (t) = tt;
+
+  side_effects = TREE_SIDE_EFFECTS (t);
+
+  PROCESS_ARG(0);
+  PROCESS_ARG(1);
+  PROCESS_ARG(2);
+  PROCESS_ARG(3);
+  PROCESS_ARG(4);
+  PROCESS_ARG(5);
+  PROCESS_ARG(6);
+
+  TREE_SIDE_EFFECTS (t) = side_effects;
+  TREE_THIS_VOLATILE (t) = 0;
+
+  return t;
+}
+
 /* Backup definition for non-gcc build compilers.  */
 
 tree
 (build) (enum tree_code code, tree tt, ...)
 {
-  tree t, arg0, arg1, arg2, arg3;
+  tree t, arg0, arg1, arg2, arg3, arg4, arg5, arg6;
   int length = TREE_CODE_LENGTH (code);
   va_list p;
 
@@ -2741,6 +2964,16 @@ tree
       arg3 = va_arg (p, tree);
       t = build4 (code, tt, arg0, arg1, arg2, arg3);
       break;
+    case 7:
+      arg0 = va_arg (p, tree);
+      arg1 = va_arg (p, tree);
+      arg2 = va_arg (p, tree);
+      arg3 = va_arg (p, tree);
+      arg4 = va_arg (p, tree);
+      arg5 = va_arg (p, tree);
+      arg6 = va_arg (p, tree);
+      t = build7 (code, tt, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -2800,21 +3033,40 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
   else if (code == FUNCTION_DECL)
     DECL_MODE (t) = FUNCTION_MODE;
 
-  /* Set default visibility to whatever the user supplied with
-     visibility_specified depending on #pragma GCC visibility.  */
-  DECL_VISIBILITY (t) = default_visibility;
-  DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+    {
+      /* Set default visibility to whatever the user supplied with
+        visibility_specified depending on #pragma GCC visibility.  */
+      DECL_VISIBILITY (t) = default_visibility;
+      DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma;
+    }
 
   return t;
 }
+
+/* Builds and returns function declaration with NAME and TYPE.  */
+
+tree
+build_fn_decl (const char *name, tree type)
+{
+  tree id = get_identifier (name);
+  tree decl = build_decl (FUNCTION_DECL, id, type);
+
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  TREE_NOTHROW (decl) = 1;
+
+  return decl;
+}
+
 \f
 /* BLOCK nodes are used to represent the structure of binding contours
    and declarations, once those contours have been exited and their contents
    compiled.  This information is used for outputting debugging info.  */
 
 tree
-build_block (tree vars, tree tags ATTRIBUTE_UNUSED, tree subblocks,
-            tree supercontext, tree chain)
+build_block (tree vars, tree subblocks, tree supercontext, tree chain)
 {
   tree block = make_node (BLOCK);
 
@@ -3258,7 +3510,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
        }
       if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
        {
-         warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+         warning (OPT_Wattributes, "%qs attribute ignored",
+                  IDENTIFIER_POINTER (name));
          *no_add_attrs = true;
        }
 
@@ -3276,7 +3529,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
       if (TREE_CODE (node) == FUNCTION_DECL  && DECL_INITIAL (node)
           && !DECL_DECLARED_INLINE_P (node))
        {
-         error ("%Jfunction %qD definition is marked dllimport.", node, node);
+         error ("function %q+D definition is marked dllimport", node);
          *no_add_attrs = true;
        }
 
@@ -3284,8 +3537,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
        {
          if (DECL_INITIAL (node))
            {
-             error ("%Jvariable %qD definition is marked dllimport.",
-                    node, node);
+             error ("variable %q+D definition is marked dllimport",
+                    node);
              *no_add_attrs = true;
            }
 
@@ -3304,8 +3557,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
       && (TREE_CODE (node) == VAR_DECL
          || TREE_CODE (node) == FUNCTION_DECL))
     {
-      error ("%Jexternal linkage required for symbol %qD because of "
-            "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
+      error ("external linkage required for symbol %q+D because of "
+            "%qs attribute", node, IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
 
@@ -3417,6 +3670,175 @@ build_variant_type_copy (tree type)
   return t;
 }
 \f
+/* Return true if the from tree in both tree maps are equal.  */
+
+int
+tree_map_eq (const void *va, const void *vb)
+{
+  const struct tree_map  *a = va, *b = vb;
+  return (a->from == b->from);
+}
+
+/* Hash a from tree in a tree_map.  */
+
+unsigned int
+tree_map_hash (const void *item)
+{
+  return (((const struct tree_map *) item)->hash);
+}
+
+/* Return true if this tree map structure is marked for garbage collection
+   purposes.  We simply return true if the from tree is marked, so that this
+   structure goes away when the from tree goes away.  */
+
+int
+tree_map_marked_p (const void *p)
+{
+  tree from = ((struct tree_map *) p)->from;
+
+  return ggc_marked_p (from);
+}
+
+/* Return true if the trees in the tree_int_map *'s VA and VB are equal.  */
+
+static int
+tree_int_map_eq (const void *va, const void *vb)
+{
+  const struct tree_int_map  *a = va, *b = vb;
+  return (a->from == b->from);
+}
+
+/* Hash a from tree in the tree_int_map * ITEM.  */
+
+static unsigned int
+tree_int_map_hash (const void *item)
+{
+  return htab_hash_pointer (((const struct tree_int_map *)item)->from);
+}
+
+/* Return true if this tree int map structure is marked for garbage collection
+   purposes.  We simply return true if the from tree_int_map *P's from tree is marked, so that this
+   structure goes away when the from tree goes away.  */
+
+static int
+tree_int_map_marked_p (const void *p)
+{
+  tree from = ((struct tree_int_map *) p)->from;
+
+  return ggc_marked_p (from);
+}
+/* Lookup an init priority for FROM, and return it if we find one.  */
+
+unsigned short
+decl_init_priority_lookup (tree from)
+{
+  struct tree_int_map *h, in;
+  in.from = from;
+
+  h = htab_find_with_hash (init_priority_for_decl, 
+                          &in, htab_hash_pointer (from));
+  if (h)
+    return h->to;
+  return 0;
+}
+
+/* Insert a mapping FROM->TO in the init priority hashtable.  */
+
+void
+decl_init_priority_insert (tree from, unsigned short to)
+{
+  struct tree_int_map *h;
+  void **loc;
+
+  h = ggc_alloc (sizeof (struct tree_int_map));
+  h->from = from;
+  h->to = to;
+  loc = htab_find_slot_with_hash (init_priority_for_decl, h, 
+                                 htab_hash_pointer (from), INSERT);
+  *(struct tree_int_map **) loc = h;
+}  
+
+/* Print out the statistics for the DECL_DEBUG_EXPR hash table.  */
+
+static void
+print_debug_expr_statistics (void)
+{
+  fprintf (stderr, "DECL_DEBUG_EXPR  hash: size %ld, %ld elements, %f collisions\n",
+          (long) htab_size (debug_expr_for_decl),
+          (long) htab_elements (debug_expr_for_decl),
+          htab_collisions (debug_expr_for_decl));
+}
+
+/* Print out the statistics for the DECL_VALUE_EXPR hash table.  */
+
+static void
+print_value_expr_statistics (void)
+{
+  fprintf (stderr, "DECL_VALUE_EXPR  hash: size %ld, %ld elements, %f collisions\n",
+          (long) htab_size (value_expr_for_decl),
+          (long) htab_elements (value_expr_for_decl),
+          htab_collisions (value_expr_for_decl));
+}
+/* Lookup a debug expression for FROM, and return it if we find one.  */
+
+tree 
+decl_debug_expr_lookup (tree from)
+{
+  struct tree_map *h, in;
+  in.from = from;
+
+  h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+  if (h)
+    return h->to;
+  return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the debug expression hashtable.  */
+
+void
+decl_debug_expr_insert (tree from, tree to)
+{
+  struct tree_map *h;
+  void **loc;
+
+  h = ggc_alloc (sizeof (struct tree_map));
+  h->hash = htab_hash_pointer (from);
+  h->from = from;
+  h->to = to;
+  loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
+  *(struct tree_map **) loc = h;
+}  
+
+/* Lookup a value expression for FROM, and return it if we find one.  */
+
+tree 
+decl_value_expr_lookup (tree from)
+{
+  struct tree_map *h, in;
+  in.from = from;
+
+  h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from));
+  if (h)
+    return h->to;
+  return NULL_TREE;
+}
+
+/* Insert a mapping FROM->TO in the value expression hashtable.  */
+
+void
+decl_value_expr_insert (tree from, tree to)
+{
+  struct tree_map *h;
+  void **loc;
+
+  h = ggc_alloc (sizeof (struct tree_map));
+  h->hash = htab_hash_pointer (from);
+  h->from = from;
+  h->to = to;
+  loc = htab_find_slot_with_hash (value_expr_for_decl, h, h->hash, INSERT);
+  *(struct tree_map **) loc = h;
+}
+
 /* Hashing of types so that we don't make duplicates.
    The entry point is `type_hash_canon'.  */
 
@@ -3951,8 +4373,21 @@ simple_cst_equal (tree t1, tree t2)
                         TREE_STRING_LENGTH (t1)));
 
     case CONSTRUCTOR:
-      return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1),
-                                   CONSTRUCTOR_ELTS (t2));
+      {
+       unsigned HOST_WIDE_INT idx;
+       VEC(constructor_elt, gc) *v1 = CONSTRUCTOR_ELTS (t1);
+       VEC(constructor_elt, gc) *v2 = CONSTRUCTOR_ELTS (t2);
+
+       if (VEC_length (constructor_elt, v1) != VEC_length (constructor_elt, v2))
+         return false;
+
+        for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx)
+         /* ??? Should we handle also fields here? */
+         if (!simple_cst_equal (VEC_index (constructor_elt, v1, idx)->value,
+                                VEC_index (constructor_elt, v2, idx)->value))
+           return false;
+       return true;
+      }
 
     case SAVE_EXPR:
       return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
@@ -4160,6 +4595,17 @@ iterative_hash_expr (tree t, hashval_t val)
       for (; t; t = TREE_CHAIN (t))
        val = iterative_hash_expr (TREE_VALUE (t), val);
       return val;
+    case CONSTRUCTOR:
+      {
+       unsigned HOST_WIDE_INT idx;
+       tree field, value;
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
+         {
+           val = iterative_hash_expr (field, val);
+           val = iterative_hash_expr (value, val);
+         }
+       return val;
+      }
     case FUNCTION_DECL:
       /* When referring to a built-in FUNCTION_DECL, use the
         __builtin__ form.  Otherwise nodes that compare equal
@@ -4736,9 +5182,16 @@ get_unwidened (tree op, tree for_type)
   while (TREE_CODE (op) == NOP_EXPR
         || TREE_CODE (op) == CONVERT_EXPR)
     {
-      int bitschange
-       = TYPE_PRECISION (TREE_TYPE (op))
-         - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
+      int bitschange;
+
+      /* TYPE_PRECISION on vector types has different meaning
+        (TYPE_VECTOR_SUBPARTS) and casts from vectors are view conversions,
+        so avoid them here.  */
+      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == VECTOR_TYPE)
+       break;
+
+      bitschange = TYPE_PRECISION (TREE_TYPE (op))
+                  - TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op, 0)));
 
       /* Truncations are many-one so cannot be removed.
         Unless we are later going to truncate down even farther.  */
@@ -5248,6 +5701,8 @@ dump_tree_statistics (void)
   fprintf (stderr, "(No per-node statistics)\n");
 #endif
   print_type_hash_statistics ();
+  print_debug_expr_statistics ();
+  print_value_expr_statistics ();
   lang_hooks.print_statistics ();
 }
 \f
@@ -5451,6 +5906,31 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl,
      TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
      tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
 }
+#undef DEFTREESTRUCT
+#define DEFTREESTRUCT(VAL, NAME) NAME,
+
+static const char *ts_enum_names[] = {
+#include "treestruct.def"
+};
+#undef DEFTREESTRUCT
+
+#define TS_ENUM_NAME(EN) (ts_enum_names[(EN)])
+
+/* Similar to tree_class_check_failed, except that we check for
+   whether CODE contains the tree structure identified by EN.  */
+
+void
+tree_contains_struct_check_failed (const tree node, 
+                                  const enum tree_node_structure_enum en,
+                                  const char *file, int line, 
+                                  const char *function)
+{
+  internal_error
+    ("tree check: expected tree that contains %qs structure, have %qs  in %s, at %s:%d",
+     TS_ENUM_NAME(en),
+     tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+}
+
 
 /* Similar to above, except that the check is for the bounds of a TREE_VEC's
    (dynamically sized) vector.  */
@@ -5500,7 +5980,7 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode)
   tree t = make_node (VECTOR_TYPE);
 
   TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype);
-  TYPE_VECTOR_SUBPARTS (t) = nunits;
+  SET_TYPE_VECTOR_SUBPARTS (t, nunits);
   TYPE_MODE (t) = mode;
   TYPE_READONLY (t) = TYPE_READONLY (innertype);
   TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
@@ -5759,7 +6239,7 @@ build_common_builtin_nodes (void)
       tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
       tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
       tmp = tree_cons (NULL_TREE, const_ptr_type_node, tmp);
-      ftype = build_function_type (ptr_type_node, tmp);
+      ftype = build_function_type (integer_type_node, tmp);
       local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP,
                            "memcmp", ECF_PURE | ECF_NOTHROW);
     }
@@ -5954,6 +6434,16 @@ build_vector_type (tree innertype, int nunits)
   return make_vector_type (innertype, nunits, VOIDmode);
 }
 
+/* Build RESX_EXPR with given REGION_NUMBER.  */
+tree
+build_resx (int region_number)
+{
+  tree t;
+  t = build1 (RESX_EXPR, void_type_node,
+             build_int_cst (NULL_TREE, region_number));
+  return t;
+}
+
 /* Given an initializer INIT, return TRUE if INIT is zero or some
    aggregate of zeros.  Otherwise return FALSE.  */
 bool
@@ -5988,14 +6478,14 @@ initializer_zerop (tree init)
       return true;
 
     case CONSTRUCTOR:
-      elt = CONSTRUCTOR_ELTS (init);
-      if (elt == NULL_TREE)
-       return true;
+      {
+       unsigned HOST_WIDE_INT idx;
 
-      for (; elt ; elt = TREE_CHAIN (elt))
-       if (! initializer_zerop (TREE_VALUE (elt)))
-         return false;
-      return true;
+       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
+         if (!initializer_zerop (elt))
+           return false;
+       return true;
+      }
 
     default:
       return false;
@@ -6151,16 +6641,16 @@ tree_fold_gcd (tree a, tree b)
     return a;
 
   if (tree_int_cst_sgn (a) == -1)
-    a = fold (build2 (MULT_EXPR, type, a,
-                     convert (type, integer_minus_one_node)));
+    a = fold_build2 (MULT_EXPR, type, a,
+                    convert (type, integer_minus_one_node));
 
   if (tree_int_cst_sgn (b) == -1)
-    b = fold (build2 (MULT_EXPR, type, b,
-                     convert (type, integer_minus_one_node)));
+    b = fold_build2 (MULT_EXPR, type, b,
+                    convert (type, integer_minus_one_node));
 
   while (1)
     {
-      a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b));
+      a_mod_b = fold_build2 (FLOOR_MOD_EXPR, type, a, b);
 
       if (!TREE_INT_CST_LOW (a_mod_b)
          && !TREE_INT_CST_HIGH (a_mod_b))
@@ -6194,43 +6684,64 @@ tree
 upper_bound_in_type (tree outer, tree inner)
 {
   unsigned HOST_WIDE_INT lo, hi;
-  unsigned bits = TYPE_PRECISION (inner);
+  unsigned int det = 0;
+  unsigned oprec = TYPE_PRECISION (outer);
+  unsigned iprec = TYPE_PRECISION (inner);
+  unsigned prec;
+
+  /* Compute a unique number for every combination.  */
+  det |= (oprec > iprec) ? 4 : 0;
+  det |= TYPE_UNSIGNED (outer) ? 2 : 0;
+  det |= TYPE_UNSIGNED (inner) ? 1 : 0;
+
+  /* Determine the exponent to use.  */
+  switch (det)
+    {
+    case 0:
+    case 1:
+      /* oprec <= iprec, outer: signed, inner: don't care.  */
+      prec = oprec - 1;
+      break;
+    case 2:
+    case 3:
+      /* oprec <= iprec, outer: unsigned, inner: don't care.  */
+      prec = oprec;
+      break;
+    case 4:
+      /* oprec > iprec, outer: signed, inner: signed.  */
+      prec = iprec - 1;
+      break;
+    case 5:
+      /* oprec > iprec, outer: signed, inner: unsigned.  */
+      prec = iprec;
+      break;
+    case 6:
+      /* oprec > iprec, outer: unsigned, inner: signed.  */
+      prec = oprec;
+      break;
+    case 7:
+      /* oprec > iprec, outer: unsigned, inner: unsigned.  */
+      prec = iprec;
+      break;
+    default:
+      gcc_unreachable ();
+    }
 
-  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+  /* Compute 2^^prec - 1.  */
+  if (prec <= HOST_BITS_PER_WIDE_INT)
     {
-      /* Zero extending in these cases.  */
-      if (bits <= HOST_BITS_PER_WIDE_INT)
-       {
-         hi = 0;
-         lo = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (HOST_BITS_PER_WIDE_INT - bits);
-       }
-      else
-       {
-         hi = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (2 * HOST_BITS_PER_WIDE_INT - bits);
-         lo = ~(unsigned HOST_WIDE_INT) 0;
-       }
+      hi = 0;
+      lo = ((~(unsigned HOST_WIDE_INT) 0)
+           >> (HOST_BITS_PER_WIDE_INT - prec));
     }
   else
     {
-      /* Sign extending in these cases.  */
-      if (bits <= HOST_BITS_PER_WIDE_INT)
-       {
-         hi = 0;
-         lo = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (HOST_BITS_PER_WIDE_INT - bits) >> 1;
-       }
-      else
-       {
-         hi = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1;
-         lo = ~(unsigned HOST_WIDE_INT) 0;
-       }
+      hi = ((~(unsigned HOST_WIDE_INT) 0)
+           >> (2 * HOST_BITS_PER_WIDE_INT - prec));
+      lo = ~(unsigned HOST_WIDE_INT) 0;
     }
 
-  return fold_convert (outer,
-                      build_int_cst_wide (inner, lo, hi));
+  return build_int_cst_wide (outer, lo, hi);
 }
 
 /* Returns the smallest value obtainable by casting something in INNER type to
@@ -6240,23 +6751,39 @@ tree
 lower_bound_in_type (tree outer, tree inner)
 {
   unsigned HOST_WIDE_INT lo, hi;
-  unsigned bits = TYPE_PRECISION (inner);
-
-  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+  unsigned oprec = TYPE_PRECISION (outer);
+  unsigned iprec = TYPE_PRECISION (inner);
+
+  /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type
+     and obtain 0.  */
+  if (TYPE_UNSIGNED (outer)
+      /* If we are widening something of an unsigned type, OUTER type
+        contains all values of INNER type.  In particular, both INNER
+        and OUTER types have zero in common.  */
+      || (oprec > iprec && TYPE_UNSIGNED (inner)))
     lo = hi = 0;
-  else if (bits <= HOST_BITS_PER_WIDE_INT)
-    {
-      hi = ~(unsigned HOST_WIDE_INT) 0;
-      lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1);
-    }
   else
     {
-      hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1);
-      lo = 0;
+      /* If we are widening a signed type to another signed type, we
+        want to obtain -2^^(iprec-1).  If we are keeping the
+        precision or narrowing to a signed type, we want to obtain
+        -2^(oprec-1).  */
+      unsigned prec = oprec > iprec ? iprec : oprec;
+
+      if (prec <= HOST_BITS_PER_WIDE_INT)
+       {
+         hi = ~(unsigned HOST_WIDE_INT) 0;
+         lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
+       }
+      else
+       {
+         hi = ((~(unsigned HOST_WIDE_INT) 0)
+               << (prec - HOST_BITS_PER_WIDE_INT - 1));
+         lo = 0;
+       }
     }
 
-  return fold_convert (outer,
-                      build_int_cst_wide (inner, lo, hi));
+  return build_int_cst_wide (outer, lo, hi);
 }
 
 /* Return nonzero if two operands that are suitable for PHI nodes are
@@ -6577,7 +7104,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        case SSA_NAME:
        case FIELD_DECL:
        case RESULT_DECL:
-         /* None of thse have subtrees other than those already walked
+         /* None of these have subtrees other than those already walked
             above.  */
          break;
 
@@ -6606,7 +7133,16 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
 
        case CONSTRUCTOR:
-         WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
+         {
+           unsigned HOST_WIDE_INT idx;
+           constructor_elt *ce;
+
+           for (idx = 0;
+                VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce);
+                idx++)
+             WALK_SUBTREE (ce->value);
+         }
+         break;
 
        case SAVE_EXPR:
          WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));