OSDN Git Service

2008-07-28 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index 2d96bd7..cdecd70 100644 (file)
@@ -1,13 +1,13 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file contains the low level primitives for operating on tree nodes,
    including allocation, list operations, interning of identifiers,
@@ -51,6 +50,45 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tree-flow.h"
 #include "params.h"
 #include "pointer-set.h"
+#include "fixed-value.h"
+
+/* Tree code classes.  */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+#define END_OF_BASE_TREE_CODES tcc_exceptional,
+
+const enum tree_code_class tree_code_type[] = {
+#include "all-tree.def"
+};
+
+#undef DEFTREECODE
+#undef END_OF_BASE_TREE_CODES
+
+/* Table indexed by tree code giving number of expression
+   operands beyond the fixed part of the node structure.
+   Not used for types or decls.  */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+#define END_OF_BASE_TREE_CODES 0,
+
+const unsigned char tree_code_length[] = {
+#include "all-tree.def"
+};
+
+#undef DEFTREECODE
+#undef END_OF_BASE_TREE_CODES
+
+/* Names of tree components.
+   Used for printing out the tree and error messages.  */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+#define END_OF_BASE_TREE_CODES "@dummy",
+
+const char *const tree_code_name[] = {
+#include "all-tree.def"
+};
+
+#undef DEFTREECODE
+#undef END_OF_BASE_TREE_CODES
 
 /* Each tree code class has an associated string representation.
    These must correspond to the tree_code_class entries.  */
@@ -67,8 +105,7 @@ const char *const tree_code_class_strings[] =
   "binary",
   "statement",
   "vl_exp",
-  "expression",
-  "gimple_stmt"
+  "expression"
 };
 
 /* obstack.[ch] explicitly declined to prototype this.  */
@@ -94,14 +131,12 @@ static const char * const tree_node_kind_names[] = {
   "temp_tree_lists",
   "vecs",
   "binfos",
-  "phi_nodes",
   "ssa names",
   "constructors",
   "random kinds",
   "lang_decl kinds",
   "lang_type kinds",
   "omp clauses",
-  "gimple statements"
 };
 #endif /* GATHER_STATISTICS */
 
@@ -137,6 +172,16 @@ static GTY (()) tree int_cst_node;
 static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
      htab_t int_cst_hash_table;
 
+/* Hash table for optimization flags and target option flags.  Use the same
+   hash table for both sets of options.  Nodes for building the current
+   optimization and target option nodes.  The assumption is most of the time
+   the options created will already be in the hash table, so we avoid
+   allocating and freeing up a node repeatably.  */
+static GTY (()) tree cl_optimization_node;
+static GTY (()) tree cl_target_option_node;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t cl_option_hash_table;
+
 /* General tree->tree mapping  structure for use in hash tables.  */
 
 
@@ -158,12 +203,14 @@ 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 hashval_t cl_option_hash_hash (const void *);
+static int cl_option_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 int type_hash_marked_p (const void *);
-static unsigned int type_hash_list (tree, hashval_t);
-static unsigned int attribute_hash_list (tree, hashval_t);
+static unsigned int type_hash_list (const_tree, hashval_t);
+static unsigned int attribute_hash_list (const_tree, hashval_t);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -177,7 +224,7 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_PRIVATE  */
   1, /* OMP_CLAUSE_SHARED  */
   1, /* OMP_CLAUSE_FIRSTPRIVATE  */
-  1, /* OMP_CLAUSE_LASTPRIVATE  */
+  2, /* OMP_CLAUSE_LASTPRIVATE  */
   4, /* OMP_CLAUSE_REDUCTION  */
   1, /* OMP_CLAUSE_COPYIN  */
   1, /* OMP_CLAUSE_COPYPRIVATE  */
@@ -186,7 +233,9 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_SCHEDULE  */
   0, /* OMP_CLAUSE_NOWAIT  */
   0, /* OMP_CLAUSE_ORDERED  */
-  0  /* OMP_CLAUSE_DEFAULT  */
+  0, /* OMP_CLAUSE_DEFAULT  */
+  3, /* OMP_CLAUSE_COLLAPSE  */
+  0  /* OMP_CLAUSE_UNTIED   */
 };
 
 const char * const omp_clause_code_name[] =
@@ -204,7 +253,9 @@ const char * const omp_clause_code_name[] =
   "schedule",
   "nowait",
   "ordered",
-  "default"
+  "default",
+  "collapse",
+  "untied"
 };
 \f
 /* Init tree.c.  */
@@ -231,6 +282,12 @@ init_ttree (void)
   
   int_cst_node = make_node (INTEGER_CST);
 
+  cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
+                                         cl_option_hash_eq, NULL);
+
+  cl_optimization_node = make_node (OPTIMIZATION_NODE);
+  cl_target_option_node = make_node (TARGET_OPTION_NODE);
+
   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;
@@ -263,17 +320,14 @@ init_ttree (void)
   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[STRUCT_FIELD_TAG][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[NAME_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[SYMBOL_MEMORY_TAG][TS_DECL_MINIMAL] = 1;
   tree_contains_struct[MEMORY_PARTITION_TAG][TS_DECL_MINIMAL] = 1;
 
-  tree_contains_struct[STRUCT_FIELD_TAG][TS_MEMORY_TAG] = 1;
   tree_contains_struct[NAME_MEMORY_TAG][TS_MEMORY_TAG] = 1;
   tree_contains_struct[SYMBOL_MEMORY_TAG][TS_MEMORY_TAG] = 1;
   tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_TAG] = 1;
 
-  tree_contains_struct[STRUCT_FIELD_TAG][TS_STRUCT_FIELD_TAG] = 1;
   tree_contains_struct[MEMORY_PARTITION_TAG][TS_MEMORY_PARTITION_TAG] = 1;
 
   tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1;
@@ -308,40 +362,82 @@ decl_assembler_name (tree decl)
 /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
 
 bool
-decl_assembler_name_equal (tree decl, tree asmname)
+decl_assembler_name_equal (tree decl, const_tree asmname)
 {
   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
+  const char *decl_str;
+  const char *asmname_str;
+  bool test = false;
 
   if (decl_asmname == asmname)
     return true;
 
+  decl_str = IDENTIFIER_POINTER (decl_asmname);
+  asmname_str = IDENTIFIER_POINTER (asmname);
+  
+
   /* If the target assembler name was set by the user, things are trickier.
      We have a leading '*' to begin with.  After that, it's arguable what
      is the correct thing to do with -fleading-underscore.  Arguably, we've
      historically been doing the wrong thing in assemble_alias by always
      printing the leading underscore.  Since we're not changing that, make
      sure user_label_prefix follows the '*' before matching.  */
-  if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
+  if (decl_str[0] == '*')
+    {
+      size_t ulp_len = strlen (user_label_prefix);
+
+      decl_str ++;
+
+      if (ulp_len == 0)
+       test = true;
+      else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+       decl_str += ulp_len, test=true;
+      else
+       decl_str --;
+    }
+  if (asmname_str[0] == '*')
+    {
+      size_t ulp_len = strlen (user_label_prefix);
+
+      asmname_str ++;
+
+      if (ulp_len == 0)
+       test = true;
+      else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
+       asmname_str += ulp_len, test=true;
+      else
+       asmname_str --;
+    }
+
+  if (!test)
+    return false;
+  return strcmp (decl_str, asmname_str) == 0;
+}
+
+/* Hash asmnames ignoring the user specified marks.  */
+
+hashval_t
+decl_assembler_name_hash (const_tree asmname)
+{
+  if (IDENTIFIER_POINTER (asmname)[0] == '*')
     {
-      const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
+      const char *decl_str = IDENTIFIER_POINTER (asmname) + 1;
       size_t ulp_len = strlen (user_label_prefix);
 
       if (ulp_len == 0)
        ;
       else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
        decl_str += ulp_len;
-      else
-       return false;
 
-      return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
+      return htab_hash_string (decl_str);
     }
 
-  return false;
+  return htab_hash_string (IDENTIFIER_POINTER (asmname));
 }
 
 /* Compute the number of bytes occupied by a tree with code CODE.
    This function cannot be used for nodes that have variable sizes,
-   including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR.  */
+   including TREE_VEC, STRING_CST, and CALL_EXPR.  */
 size_t
 tree_code_size (enum tree_code code)
 {
@@ -370,8 +466,6 @@ tree_code_size (enum tree_code code)
          case NAME_MEMORY_TAG:
          case SYMBOL_MEMORY_TAG:
            return sizeof (struct tree_memory_tag);
-         case STRUCT_FIELD_TAG:
-           return sizeof (struct tree_struct_field_tag);
          case MEMORY_PARTITION_TAG:
            return sizeof (struct tree_memory_partition_tag);
          default:
@@ -391,15 +485,12 @@ tree_code_size (enum tree_code code)
       return (sizeof (struct tree_exp)
              + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
 
-    case tcc_gimple_stmt:
-      return (sizeof (struct gimple_stmt)
-             + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
-
     case tcc_constant:  /* a constant */
       switch (code)
        {
        case INTEGER_CST:       return sizeof (struct tree_int_cst);
        case REAL_CST:          return sizeof (struct tree_real_cst);
+       case FIXED_CST:         return sizeof (struct tree_fixed_cst);
        case COMPLEX_CST:       return sizeof (struct tree_complex);
        case VECTOR_CST:        return sizeof (struct tree_vector);
        case STRING_CST:        gcc_unreachable ();
@@ -417,15 +508,15 @@ tree_code_size (enum tree_code code)
        case PLACEHOLDER_EXPR:  return sizeof (struct tree_common);
 
        case TREE_VEC:
-       case OMP_CLAUSE:
-       case PHI_NODE:          gcc_unreachable ();
+       case OMP_CLAUSE:        gcc_unreachable ();
 
        case SSA_NAME:          return sizeof (struct tree_ssa_name);
 
        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);
+       case OPTIMIZATION_NODE: return sizeof (struct tree_optimization_option);
+       case TARGET_OPTION_NODE: return sizeof (struct tree_target_option);
 
        default:
          return lang_hooks.tree_size (code);
@@ -439,15 +530,11 @@ tree_code_size (enum tree_code code)
 /* Compute the number of bytes occupied by NODE.  This routine only
    looks at TREE_CODE, except for those nodes that have variable sizes.  */
 size_t
-tree_size (tree node)
+tree_size (const_tree node)
 {
-  enum tree_code code = TREE_CODE (node);
+  const enum tree_code code = TREE_CODE (node);
   switch (code)
     {
-    case PHI_NODE:
-      return (sizeof (struct tree_phi_node)
-             + (PHI_ARG_CAPACITY (node) - 1) * sizeof (struct phi_arg_d));
-
     case TREE_BINFO:
       return (offsetof (struct tree_binfo, base_binfos)
              + VEC_embedded_size (tree, BINFO_N_BASE_BINFOS (node)));
@@ -475,9 +562,8 @@ tree_size (tree node)
 
 /* Return a newly allocated node of code CODE.  For decl and type
    nodes, some other fields are initialized.  The rest of the node is
-   initialized to zero.  This function cannot be used for PHI_NODE,
-   TREE_VEC or OMP_CLAUSE nodes, which is enforced by asserts in
-   tree_code_size.
+   initialized to zero.  This function cannot be used for TREE_VEC or
+   OMP_CLAUSE nodes, which is enforced by asserts in tree_code_size.
 
    Achoo!  I got a code in the node.  */
 
@@ -519,10 +605,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       kind = c_kind;
       break;
 
-    case tcc_gimple_stmt:
-      kind = gimple_stmt_kind;
-      break;
-
     case tcc_exceptional:  /* something random, like an identifier.  */
       switch (code)
        {
@@ -538,10 +620,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
          kind = binfo_kind;
          break;
 
-       case PHI_NODE:
-         kind = phi_kind;
-         break;
-
        case SSA_NAME:
          kind = ssa_name_kind;
          break;
@@ -569,9 +647,9 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 #endif
 
   if (code == IDENTIFIER_NODE)
-    t = ggc_alloc_zone_pass_stat (length, &tree_id_zone);
+    t = (tree) ggc_alloc_zone_pass_stat (length, &tree_id_zone);
   else
-    t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+    t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -584,13 +662,15 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
       break;
 
     case tcc_declaration:
-      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
-       DECL_IN_SYSTEM_HEADER (t) = in_system_header;
       if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
-         if (code != FUNCTION_DECL)
+         if (code == FUNCTION_DECL)
+           {
+             DECL_ALIGN (t) = FUNCTION_BOUNDARY;
+             DECL_MODE (t) = FUNCTION_MODE;
+           }
+         else
            DECL_ALIGN (t) = 1;
-         DECL_USER_ALIGN (t) = 0;        
          /* We have not yet computed the alias set for this declaration.  */
          DECL_POINTER_ALIAS_SET (t) = -1;
        }
@@ -616,7 +696,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
 
     case tcc_constant:
       TREE_CONSTANT (t) = 1;
-      TREE_INVARIANT (t) = 1;
       break;
 
     case tcc_expression:
@@ -639,17 +718,6 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
        }
       break;
 
-    case tcc_gimple_stmt:
-      switch (code)
-       {
-      case GIMPLE_MODIFY_STMT:
-       TREE_SIDE_EFFECTS (t) = 1;
-       break;
-
-      default:
-       break;
-       }
-
     default:
       /* Other classes need no special treatment.  */
       break;
@@ -671,11 +739,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
   gcc_assert (code != STATEMENT_LIST);
 
   length = tree_size (node);
-  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+  t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
   memcpy (t, node, length);
 
-  if (!GIMPLE_TUPLE_P (node))
-    TREE_CHAIN (t) = 0;
+  TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
   TREE_VISITED (t) = 0;
   t->base.ann = 0;
@@ -807,7 +874,7 @@ build_int_cst_wide_type (tree type,
 static hashval_t
 int_cst_hash_hash (const void *x)
 {
-  tree t = (tree) x;
+  const_tree const t = (const_tree) x;
 
   return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
          ^ htab_hash_pointer (TREE_TYPE (t)));
@@ -819,8 +886,8 @@ int_cst_hash_hash (const void *x)
 static int
 int_cst_hash_eq (const void *x, const void *y)
 {
-  tree xt = (tree) x;
-  tree yt = (tree) y;
+  const_tree const xt = (const_tree) x;
+  const_tree const yt = (const_tree) y;
 
   return (TREE_TYPE (xt) == TREE_TYPE (yt)
          && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
@@ -925,7 +992,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
       TREE_TYPE (int_cst_node) = type;
 
       slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
-      t = *slot;
+      t = (tree) *slot;
       if (!t)
        {
          /* Insert this one into the hash table.  */
@@ -977,7 +1044,7 @@ build_low_bits_mask (tree type, unsigned bits)
    HOST_WIDE_INT without loss of precision.  */
 
 bool
-cst_and_fits_in_hwi (tree x)
+cst_and_fits_in_hwi (const_tree x)
 {
   if (TREE_CODE (x) != INTEGER_CST)
     return false;
@@ -1092,6 +1159,22 @@ build_constructor_from_list (tree type, tree vals)
   return t;
 }
 
+/* Return a new FIXED_CST node whose type is TYPE and value is F.  */
+
+tree
+build_fixed (tree type, FIXED_VALUE_TYPE f)
+{
+  tree v;
+  FIXED_VALUE_TYPE *fp;
+
+  v = make_node (FIXED_CST);
+  fp = GGC_NEW (FIXED_VALUE_TYPE);
+  memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
+
+  TREE_TYPE (v) = type;
+  TREE_FIXED_CST_PTR (v) = fp;
+  return v;
+}
 
 /* Return a new REAL_CST node whose type is TYPE and value is D.  */
 
@@ -1106,7 +1189,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
      Consider doing it via real_convert now.  */
 
   v = make_node (REAL_CST);
-  dp = ggc_alloc (sizeof (REAL_VALUE_TYPE));
+  dp = GGC_NEW (REAL_VALUE_TYPE);
   memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
 
   TREE_TYPE (v) = type;
@@ -1119,7 +1202,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
    and whose value is the integer value of the INTEGER_CST node I.  */
 
 REAL_VALUE_TYPE
-real_value_from_int_cst (tree type, tree i)
+real_value_from_int_cst (const_tree type, const_tree i)
 {
   REAL_VALUE_TYPE d;
 
@@ -1137,7 +1220,7 @@ real_value_from_int_cst (tree type, tree i)
    representing the same value as a floating-point constant of type TYPE.  */
 
 tree
-build_real_from_int_cst (tree type, tree i)
+build_real_from_int_cst (tree type, const_tree i)
 {
   tree v;
   int overflow = TREE_OVERFLOW (i);
@@ -1171,10 +1254,9 @@ build_string (int len, const char *str)
   memset (s, 0, sizeof (struct tree_common));
   TREE_SET_CODE (s, STRING_CST);
   TREE_CONSTANT (s) = 1;
-  TREE_INVARIANT (s) = 1;
   TREE_STRING_LENGTH (s) = len;
-  memcpy ((char *) TREE_STRING_POINTER (s), str, len);
-  ((char *) TREE_STRING_POINTER (s))[len] = '\0';
+  memcpy (s->string.str, str, len);
+  s->string.str[len] = '\0';
 
   return s;
 }
@@ -1212,6 +1294,11 @@ build_one_cst (tree type)
     case REAL_TYPE:
       return build_real (type, dconst1);
 
+    case FIXED_POINT_TYPE:
+      /* We can only generate 1 for accum types.  */
+      gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
+      return build_fixed (type, FCONST1(TYPE_MODE (type)));
+
     case VECTOR_TYPE:
       {
        tree scalar, cst;
@@ -1251,7 +1338,7 @@ make_tree_binfo_stat (unsigned base_binfos MEM_STAT_DECL)
   tree_node_sizes[(int) binfo_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+  t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, offsetof (struct tree_binfo, base_binfos));
 
@@ -1276,7 +1363,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
   tree_node_sizes[(int) vec_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+  t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -1290,7 +1377,7 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
    of zero.  */
 
 int
-integer_zerop (tree expr)
+integer_zerop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1306,7 +1393,7 @@ integer_zerop (tree expr)
    complex constant.  */
 
 int
-integer_onep (tree expr)
+integer_onep (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1322,7 +1409,7 @@ integer_onep (tree expr)
    it contains.  Likewise for the corresponding complex constant.  */
 
 int
-integer_all_onesp (tree expr)
+integer_all_onesp (const_tree expr)
 {
   int prec;
   int uns;
@@ -1374,7 +1461,7 @@ integer_all_onesp (tree expr)
    one bit on).  */
 
 int
-integer_pow2p (tree expr)
+integer_pow2p (const_tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -1419,7 +1506,7 @@ integer_pow2p (tree expr)
    complex constant other than zero.  */
 
 int
-integer_nonzerop (tree expr)
+integer_nonzerop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1431,11 +1518,20 @@ integer_nonzerop (tree expr)
                  || integer_nonzerop (TREE_IMAGPART (expr)))));
 }
 
+/* Return 1 if EXPR is the fixed-point constant zero.  */
+
+int
+fixed_zerop (const_tree expr)
+{
+  return (TREE_CODE (expr) == FIXED_CST
+         && double_int_zero_p (TREE_FIXED_CST (expr).data));
+}
+
 /* Return the power of two represented by a tree node known to be a
    power of two.  */
 
 int
-tree_log2 (tree expr)
+tree_log2 (const_tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -1473,7 +1569,7 @@ tree_log2 (tree expr)
    than or equal to EXPR.  */
 
 int
-tree_floor_log2 (tree expr)
+tree_floor_log2 (const_tree expr)
 {
   int prec;
   HOST_WIDE_INT high, low;
@@ -1511,7 +1607,7 @@ tree_floor_log2 (tree expr)
 /* Return 1 if EXPR is the real constant zero.  */
 
 int
-real_zerop (tree expr)
+real_zerop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1525,7 +1621,7 @@ real_zerop (tree expr)
 /* Return 1 if EXPR is the real constant one in real or complex form.  */
 
 int
-real_onep (tree expr)
+real_onep (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1539,7 +1635,7 @@ real_onep (tree expr)
 /* Return 1 if EXPR is the real constant two.  */
 
 int
-real_twop (tree expr)
+real_twop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1553,7 +1649,7 @@ real_twop (tree expr)
 /* Return 1 if EXPR is the real constant minus one.  */
 
 int
-real_minus_onep (tree expr)
+real_minus_onep (const_tree expr)
 {
   STRIP_NOPS (expr);
 
@@ -1567,11 +1663,10 @@ real_minus_onep (tree expr)
 /* Nonzero if EXP is a constant or a cast of a constant.  */
 
 int
-really_constant_p (tree exp)
+really_constant_p (const_tree exp)
 {
   /* This is not quite the same as STRIP_NOPS.  It does more.  */
-  while (TREE_CODE (exp) == NOP_EXPR
-        || TREE_CODE (exp) == CONVERT_EXPR
+  while (CONVERT_EXPR_P (exp)
         || TREE_CODE (exp) == NON_LVALUE_EXPR)
     exp = TREE_OPERAND (exp, 0);
   return TREE_CONSTANT (exp);
@@ -1596,7 +1691,7 @@ value_member (tree elem, tree list)
    Return 0 if ELEM is not in LIST.  */
 
 tree
-purpose_member (tree elem, tree list)
+purpose_member (const_tree elem, tree list)
 {
   while (list)
     {
@@ -1610,7 +1705,7 @@ purpose_member (tree elem, tree list)
 /* Return nonzero if ELEM is part of the chain CHAIN.  */
 
 int
-chain_member (tree elem, tree chain)
+chain_member (const_tree elem, const_tree chain)
 {
   while (chain)
     {
@@ -1627,11 +1722,11 @@ chain_member (tree elem, tree chain)
    This is the Lisp primitive `length'.  */
 
 int
-list_length (tree t)
+list_length (const_tree t)
 {
-  tree p = t;
+  const_tree p = t;
 #ifdef ENABLE_TREE_CHECKING
-  tree q = t;
+  const_tree q = t;
 #endif
   int len = 0;
 
@@ -1652,7 +1747,7 @@ list_length (tree t)
 /* Returns the number of FIELD_DECLs in TYPE.  */
 
 int
-fields_length (tree type)
+fields_length (const_tree type)
 {
   tree t = TYPE_FIELDS (type);
   int count = 0;
@@ -1742,7 +1837,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
 {
   tree node;
 
-  node = ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone);
+  node = (tree) ggc_alloc_zone_pass_stat (sizeof (struct tree_list), &tree_zone);
 
   memset (node, 0, sizeof (struct tree_common));
 
@@ -1758,6 +1853,24 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
   return node;
 }
 
+/* Return the elements of a CONSTRUCTOR as a TREE_LIST.  */
+
+tree
+ctor_to_list (tree ctor)
+{
+  tree list = NULL_TREE;
+  tree *p = &list;
+  unsigned ix;
+  tree purpose, val;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, purpose, val)
+    {
+      *p = build_tree_list (purpose, val);
+      p = &TREE_CHAIN (*p);
+    }
+
+  return list;
+}
 \f
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -1766,7 +1879,7 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL)
    make_unsigned_type).  */
 
 tree
-size_in_bytes (tree type)
+size_in_bytes (const_tree type)
 {
   tree t;
 
@@ -1789,7 +1902,7 @@ size_in_bytes (tree type)
    or return -1 if the size can vary or is larger than an integer.  */
 
 HOST_WIDE_INT
-int_size_in_bytes (tree type)
+int_size_in_bytes (const_tree type)
 {
   tree t;
 
@@ -1812,7 +1925,7 @@ int_size_in_bytes (tree type)
    or return -1 if the size can vary or is larger than an integer.  */
 
 HOST_WIDE_INT
-max_int_size_in_bytes (tree type)
+max_int_size_in_bytes (const_tree type)
 {
   HOST_WIDE_INT size = -1;
   tree size_tree;
@@ -1845,7 +1958,7 @@ max_int_size_in_bytes (tree type)
    This is a tree of type bitsizetype.  */
 
 tree
-bit_position (tree field)
+bit_position (const_tree field)
 {
   return bit_from_pos (DECL_FIELD_OFFSET (field),
                       DECL_FIELD_BIT_OFFSET (field));
@@ -1856,7 +1969,7 @@ bit_position (tree field)
    option of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
-int_bit_position (tree field)
+int_bit_position (const_tree field)
 {
   return tree_low_cst (bit_position (field), 0);
 }
@@ -1865,7 +1978,7 @@ int_bit_position (tree field)
    This is a tree of type sizetype.  */
 
 tree
-byte_position (tree field)
+byte_position (const_tree field)
 {
   return byte_from_pos (DECL_FIELD_OFFSET (field),
                        DECL_FIELD_BIT_OFFSET (field));
@@ -1876,7 +1989,7 @@ byte_position (tree field)
    option of returning -1 like int_size_in_byte can.  */
 
 HOST_WIDE_INT
-int_byte_position (tree field)
+int_byte_position (const_tree field)
 {
   return tree_low_cst (byte_position (field), 0);
 }
@@ -1884,23 +1997,19 @@ int_byte_position (tree field)
 /* Return the strictest alignment, in bits, that T is known to have.  */
 
 unsigned int
-expr_align (tree t)
+expr_align (const_tree t)
 {
   unsigned int align0, align1;
 
   switch (TREE_CODE (t))
     {
-    case NOP_EXPR:  case CONVERT_EXPR:  case NON_LVALUE_EXPR:
+    CASE_CONVERT:  case NON_LVALUE_EXPR:
       /* If we have conversions, we know that the alignment of the
         object must meet each of the alignments of the types.  */
       align0 = expr_align (TREE_OPERAND (t, 0));
       align1 = TYPE_ALIGN (TREE_TYPE (t));
       return MAX (align0, align1);
 
-    case GIMPLE_MODIFY_STMT:
-      /* We should never ask for the alignment of a gimple statement.  */
-      gcc_unreachable ();
-
     case SAVE_EXPR:         case COMPOUND_EXPR:       case MODIFY_EXPR:
     case INIT_EXPR:         case TARGET_EXPR:         case WITH_CLEANUP_EXPR:
     case CLEANUP_POINT_EXPR:
@@ -1914,14 +2023,13 @@ expr_align (tree t)
       align1 = expr_align (TREE_OPERAND (t, 2));
       return MIN (align0, align1);
 
+      /* FIXME: LABEL_DECL and CONST_DECL never have DECL_ALIGN set
+        meaningfully, it's always 1.  */
     case LABEL_DECL:     case CONST_DECL:
     case VAR_DECL:       case PARM_DECL:   case RESULT_DECL:
-      if (DECL_ALIGN (t) != 0)
-       return DECL_ALIGN (t);
-      break;
-
     case FUNCTION_DECL:
-      return FUNCTION_BOUNDARY;
+      gcc_assert (DECL_ALIGN (t) != 0);
+      return DECL_ALIGN (t);
 
     default:
       break;
@@ -1935,7 +2043,7 @@ expr_align (tree t)
    ARRAY_TYPE) minus one. This counts only elements of the top array.  */
 
 tree
-array_type_nelts (tree type)
+array_type_nelts (const_tree type)
 {
   tree index_type, min, max;
 
@@ -2022,7 +2130,111 @@ staticp (tree arg)
        return NULL;
     }
 }
+
 \f
+
+
+/* Return whether OP is a DECL whose address is function-invariant.  */
+
+bool
+decl_address_invariant_p (const_tree op)
+{
+  /* The conditions below are slightly less strict than the one in
+     staticp.  */
+
+  switch (TREE_CODE (op))
+    {
+    case PARM_DECL:
+    case RESULT_DECL:
+    case LABEL_DECL:
+    case FUNCTION_DECL:
+      return true;
+
+    case VAR_DECL:
+      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+           && !DECL_DLLIMPORT_P (op))
+          || DECL_THREAD_LOCAL_P (op)
+          || DECL_CONTEXT (op) == current_function_decl
+          || decl_function_context (op) == current_function_decl)
+        return true;
+      break;
+
+    case CONST_DECL:
+      if ((TREE_STATIC (op) || DECL_EXTERNAL (op))
+          || decl_function_context (op) == current_function_decl)
+        return true;
+      break;
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
+
+/* Return true if T is function-invariant (internal function, does
+   not handle arithmetic; that's handled in skip_simple_arithmetic and
+   tree_invariant_p).  */
+
+static bool tree_invariant_p (tree t);
+
+static bool
+tree_invariant_p_1 (tree t)
+{
+  tree op;
+
+  if (TREE_CONSTANT (t)
+      || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t)))
+    return true;
+
+  switch (TREE_CODE (t))
+    {
+    case SAVE_EXPR:
+      return true;
+
+    case ADDR_EXPR:
+      op = TREE_OPERAND (t, 0);
+      while (handled_component_p (op))
+       {
+         switch (TREE_CODE (op))
+           {
+           case ARRAY_REF:
+           case ARRAY_RANGE_REF:
+             if (!tree_invariant_p (TREE_OPERAND (op, 1))
+                 || TREE_OPERAND (op, 2) != NULL_TREE
+                 || TREE_OPERAND (op, 3) != NULL_TREE)
+               return false;
+             break;
+
+           case COMPONENT_REF:
+             if (TREE_OPERAND (op, 2) != NULL_TREE)
+               return false;
+             break;
+
+           default:;
+           }
+         op = TREE_OPERAND (op, 0);
+       }
+
+      return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
+/* Return true if T is function-invariant.  */
+
+static bool
+tree_invariant_p (tree t)
+{
+  tree inner = skip_simple_arithmetic (t);
+  return tree_invariant_p_1 (inner);
+}
+
 /* Wrap a SAVE_EXPR around EXPR, if appropriate.
    Do this to any expression which may be used in more than one place,
    but must be evaluated only once.
@@ -2057,11 +2269,10 @@ save_expr (tree expr)
      Since it is no problem to reevaluate literals, we just return the
      literal node.  */
   inner = skip_simple_arithmetic (t);
+  if (TREE_CODE (inner) == ERROR_MARK)
+    return inner;
 
-  if (TREE_INVARIANT (inner)
-      || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
-      || TREE_CODE (inner) == SAVE_EXPR
-      || TREE_CODE (inner) == ERROR_MARK)
+  if (tree_invariant_p_1 (inner))
     return t;
 
   /* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
@@ -2082,7 +2293,6 @@ save_expr (tree expr)
      value was computed on both sides of the jump.  So make sure it isn't
      eliminated as dead.  */
   TREE_SIDE_EFFECTS (t) = 1;
-  TREE_INVARIANT (t) = 1;
   return t;
 }
 
@@ -2110,9 +2320,9 @@ skip_simple_arithmetic (tree expr)
        inner = TREE_OPERAND (inner, 0);
       else if (BINARY_CLASS_P (inner))
        {
-         if (TREE_INVARIANT (TREE_OPERAND (inner, 1)))
+         if (tree_invariant_p (TREE_OPERAND (inner, 1)))
            inner = TREE_OPERAND (inner, 0);
-         else if (TREE_INVARIANT (TREE_OPERAND (inner, 0)))
+         else if (tree_invariant_p (TREE_OPERAND (inner, 0)))
            inner = TREE_OPERAND (inner, 1);
          else
            break;
@@ -2127,9 +2337,9 @@ skip_simple_arithmetic (tree expr)
 /* Return which tree structure is used by T.  */
 
 enum tree_node_structure_enum
-tree_node_structure (tree t)
+tree_node_structure (const_tree t)
 {
-  enum tree_code code = TREE_CODE (t);
+  const enum tree_code code = TREE_CODE (t);
 
   switch (TREE_CODE_CLASS (code))
     {      
@@ -2155,7 +2365,6 @@ tree_node_structure (tree t)
            return TS_FUNCTION_DECL;
          case SYMBOL_MEMORY_TAG:
          case NAME_MEMORY_TAG:
-         case STRUCT_FIELD_TAG:
          case MEMORY_PARTITION_TAG:
            return TS_MEMORY_TAG;
          default:
@@ -2172,8 +2381,6 @@ tree_node_structure (tree t)
     case tcc_statement:
     case tcc_vl_exp:
       return TS_EXP;
-    case tcc_gimple_stmt:
-      return TS_GIMPLE_STATEMENT;
     default:  /* tcc_constant and tcc_exceptional */
       break;
     }
@@ -2182,25 +2389,24 @@ tree_node_structure (tree t)
       /* tcc_constant cases.  */
     case INTEGER_CST:          return TS_INT_CST;
     case REAL_CST:             return TS_REAL_CST;
+    case FIXED_CST:            return TS_FIXED_CST;
     case COMPLEX_CST:          return TS_COMPLEX;
     case VECTOR_CST:           return TS_VECTOR;
     case STRING_CST:           return TS_STRING;
       /* tcc_exceptional cases.  */
-    /* FIXME tuples: eventually this should be TS_BASE.  For now, nothing
-       returns TS_BASE.  */
     case ERROR_MARK:           return TS_COMMON;
     case IDENTIFIER_NODE:      return TS_IDENTIFIER;
     case TREE_LIST:            return TS_LIST;
     case TREE_VEC:             return TS_VEC;
-    case PHI_NODE:             return TS_PHI_NODE;
     case SSA_NAME:             return TS_SSA_NAME;
     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;
     case OMP_CLAUSE:           return TS_OMP_CLAUSE;
+    case OPTIMIZATION_NODE:    return TS_OPTIMIZATION;
+    case TARGET_OPTION_NODE:   return TS_TARGET_OPTION;
 
     default:
       gcc_unreachable ();
@@ -2211,7 +2417,7 @@ tree_node_structure (tree t)
    or offset that depends on a field within a record.  */
 
 bool
-contains_placeholder_p (tree exp)
+contains_placeholder_p (const_tree exp)
 {
   enum tree_code code;
 
@@ -2272,9 +2478,9 @@ contains_placeholder_p (tree exp)
        {
        case CALL_EXPR:
          {
-           tree arg;
-           call_expr_arg_iterator iter;
-           FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+           const_tree arg;
+           const_call_expr_arg_iterator iter;
+           FOR_EACH_CONST_CALL_EXPR_ARG (arg, iter, exp)
              if (CONTAINS_PLACEHOLDER_P (arg))
                return 1;
            return 0;
@@ -2294,7 +2500,7 @@ contains_placeholder_p (tree exp)
    (for QUAL_UNION_TYPE) and field positions.  */
 
 static bool
-type_contains_placeholder_1 (tree type)
+type_contains_placeholder_1 (const_tree type)
 {
   /* If the size contains a placeholder or the parent type (component type in
      the case of arrays) type involves a placeholder, this type does.  */
@@ -2322,6 +2528,7 @@ type_contains_placeholder_1 (tree type)
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
       /* Here we just check the bounds.  */
       return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
              || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
@@ -2387,8 +2594,7 @@ substitute_in_expr (tree exp, tree f, tree r)
 {
   enum tree_code code = TREE_CODE (exp);
   tree op0, op1, op2, op3;
-  tree new;
-  tree inner;
+  tree new, inner;
 
   /* We handle TREE_LIST and COMPONENT_REF separately.  */
   if (code == TREE_LIST)
@@ -2494,22 +2700,25 @@ substitute_in_expr (tree exp, tree f, tree r)
        {
          tree copy = NULL_TREE;
          int i;
-         int n = TREE_OPERAND_LENGTH (exp);
-         for (i = 1; i < n; i++)
+
+         for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
            {
              tree op = TREE_OPERAND (exp, i);
-             tree newop = SUBSTITUTE_IN_EXPR (op, f, r);
-             if (newop != op)
+             tree new_op = SUBSTITUTE_IN_EXPR (op, f, r);
+             if (new_op != op)
                {
-                 copy = copy_node (exp);
-                 TREE_OPERAND (copy, i) = newop;
+                 if (!copy)
+                   copy = copy_node (exp);
+                 TREE_OPERAND (copy, i) = new_op;
                }
            }
+
          if (copy)
            new = fold (copy);
          else
            return exp;
        }
+       break;
 
       default:
        gcc_unreachable ();
@@ -2647,18 +2856,19 @@ substitute_placeholder_in_expr (tree exp, tree obj)
        {
          tree copy = NULL_TREE;
          int i;
-         int n = TREE_OPERAND_LENGTH (exp);
-         for (i = 1; i < n; i++)
+
+         for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++)
            {
              tree op = TREE_OPERAND (exp, i);
-             tree newop = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj);
-             if (newop != op)
+             tree new_op = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj);
+             if (new_op != op)
                {
                  if (!copy)
                    copy = copy_node (exp);
-                 TREE_OPERAND (copy, i) = newop;
+                 TREE_OPERAND (copy, i) = new_op;
                }
            }
+
          if (copy)
            return fold (copy);
          else
@@ -2692,8 +2902,7 @@ stabilize_reference (tree ref)
       /* No action is needed in this case.  */
       return ref;
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
+    CASE_CONVERT:
     case FLOAT_EXPR:
     case FIX_TRUNC_EXPR:
       result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
@@ -2778,7 +2987,7 @@ stabilize_reference_1 (tree e)
      ignore things that are actual constant or that already have been
      handled by this function.  */
 
-  if (TREE_INVARIANT (e))
+  if (tree_invariant_p (e))
     return e;
 
   switch (TREE_CODE_CLASS (code))
@@ -2831,7 +3040,6 @@ stabilize_reference_1 (tree e)
   TREE_READONLY (result) = TREE_READONLY (e);
   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
-  TREE_INVARIANT (result) = 1;
 
   return result;
 }
@@ -2839,13 +3047,13 @@ stabilize_reference_1 (tree e)
 /* Low-level constructors for expressions.  */
 
 /* A helper function for build1 and constant folders.  Set TREE_CONSTANT,
-   TREE_INVARIANT, and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
+   and TREE_SIDE_EFFECTS for an ADDR_EXPR.  */
 
 void
 recompute_tree_invariant_for_addr_expr (tree t)
 {
   tree node;
-  bool tc = true, ti = true, se = false;
+  bool tc = true, se = false;
 
   /* We started out assuming this address is both invariant and constant, but
      does not have side effects.  Now go down any handled components and see if
@@ -2855,9 +3063,8 @@ recompute_tree_invariant_for_addr_expr (tree t)
      ??? Note that this code makes no attempt to deal with the case where
      taking the address of something causes a copy due to misalignment.  */
 
-#define UPDATE_TITCSE(NODE)  \
+#define UPDATE_FLAGS(NODE)  \
 do { tree _node = (NODE); \
-     if (_node && !TREE_INVARIANT (_node)) ti = false; \
      if (_node && !TREE_CONSTANT (_node)) tc = false; \
      if (_node && TREE_SIDE_EFFECTS (_node)) se = true; } while (0)
 
@@ -2871,11 +3078,11 @@ do { tree _node = (NODE); \
           || TREE_CODE (node) == ARRAY_RANGE_REF)
          && TREE_CODE (TREE_TYPE (TREE_OPERAND (node, 0))) == ARRAY_TYPE)
        {
-         UPDATE_TITCSE (TREE_OPERAND (node, 1));
+         UPDATE_FLAGS (TREE_OPERAND (node, 1));
          if (TREE_OPERAND (node, 2))
-           UPDATE_TITCSE (TREE_OPERAND (node, 2));
+           UPDATE_FLAGS (TREE_OPERAND (node, 2));
          if (TREE_OPERAND (node, 3))
-           UPDATE_TITCSE (TREE_OPERAND (node, 3));
+           UPDATE_FLAGS (TREE_OPERAND (node, 3));
        }
       /* Likewise, just because this is a COMPONENT_REF doesn't mean we have a
         FIELD_DECL, apparently.  The G++ front end can put something else
@@ -2884,46 +3091,35 @@ do { tree _node = (NODE); \
               && TREE_CODE (TREE_OPERAND (node, 1)) == FIELD_DECL)
        {
          if (TREE_OPERAND (node, 2))
-           UPDATE_TITCSE (TREE_OPERAND (node, 2));
+           UPDATE_FLAGS (TREE_OPERAND (node, 2));
        }
       else if (TREE_CODE (node) == BIT_FIELD_REF)
-       UPDATE_TITCSE (TREE_OPERAND (node, 2));
+       UPDATE_FLAGS (TREE_OPERAND (node, 2));
     }
 
-  node = lang_hooks.expr_to_decl (node, &tc, &ti, &se);
+  node = lang_hooks.expr_to_decl (node, &tc, &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
-     a decl in the current function.  Taking the address of a volatile variable
-     is not volatile.  If it's a constant, the address is both invariant and
-     constant.  Otherwise it's neither.  */
+     the address, since &(*a)->b is a form of addition.  If it's a constant, the
+     address is constant too.  If it's a decl, its address is constant if the
+     decl is static.  Everything else is not constant and, furthermore,
+     taking the address of a volatile variable is not volatile.  */
   if (TREE_CODE (node) == INDIRECT_REF)
-    UPDATE_TITCSE (TREE_OPERAND (node, 0));
-  else if (DECL_P (node))
-    {
-      if (staticp (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_P (node)))
-       tc = false;
-      else
-       ti = tc = false;
-    }
+    UPDATE_FLAGS (TREE_OPERAND (node, 0));
   else if (CONSTANT_CLASS_P (node))
     ;
+  else if (DECL_P (node))
+    tc &= (staticp (node) != NULL_TREE);
   else
     {
-      ti = tc = false;
+      tc = false;
       se |= TREE_SIDE_EFFECTS (node);
     }
 
+
   TREE_CONSTANT (t) = tc;
-  TREE_INVARIANT (t) = ti;
   TREE_SIDE_EFFECTS (t) = se;
-#undef UPDATE_TITCSE
+#undef UPDATE_FLAGS
 }
 
 /* Build an expression of code CODE, data type TYPE, and operands as
@@ -2975,18 +3171,14 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
 
   gcc_assert (TREE_CODE_LENGTH (code) == 1);
 
-  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+  t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, sizeof (struct tree_common));
 
   TREE_SET_CODE (t, code);
 
   TREE_TYPE (t) = type;
-#ifdef USE_MAPPED_LOCATION
   SET_EXPR_LOCATION (t, UNKNOWN_LOCATION);
-#else
-  SET_EXPR_LOCUS (t, NULL);
-#endif
   TREE_OPERAND (t, 0) = node;
   TREE_BLOCK (t) = NULL_TREE;
   if (node && !TYPE_P (node))
@@ -3024,9 +3216,6 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
          && node && !TYPE_P (node)
          && TREE_CONSTANT (node))
        TREE_CONSTANT (t) = 1;
-      if ((TREE_CODE_CLASS (code) == tcc_unary || code == VIEW_CONVERT_EXPR)
-         && node && TREE_INVARIANT (node))
-       TREE_INVARIANT (t) = 1;
       if (TREE_CODE_CLASS (code) == tcc_reference
          && node && TREE_THIS_VOLATILE (node))
        TREE_THIS_VOLATILE (t) = 1;
@@ -3047,27 +3236,25 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
          read_only = 0;                \
         if (!TREE_CONSTANT (arg##N))   \
          constant = 0;                 \
-       if (!TREE_INVARIANT (arg##N))   \
-         invariant = 0;                \
       }                                        \
   } while (0)
 
 tree
 build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 2);
 
-#if 1
-  /* FIXME tuples: Statement's aren't expressions!  */
-  if (code == GIMPLE_MODIFY_STMT)
-    return build_gimple_modify_stmt_stat (arg0, arg1 PASS_MEM_STAT);
-#else
-  /* Must use build_gimple_modify_stmt to construct GIMPLE_MODIFY_STMTs.  */
-  gcc_assert (code != GIMPLE_MODIFY_STMT);
-#endif
+  if ((code == MINUS_EXPR || code == PLUS_EXPR || code == MULT_EXPR)
+      && arg0 && arg1 && tt && POINTER_TYPE_P (tt))
+    gcc_assert (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST);
+
+  if (code == POINTER_PLUS_EXPR && arg0 && arg1 && tt)
+    gcc_assert (POINTER_TYPE_P (tt) && POINTER_TYPE_P (TREE_TYPE (arg0))
+               && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+               && useless_type_conversion_p (sizetype, TREE_TYPE (arg1)));
 
   t = make_node_stat (code PASS_MEM_STAT);
   TREE_TYPE (t) = tt;
@@ -3083,14 +3270,12 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
              || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
-  invariant = constant;
 
   PROCESS_ARG(0);
   PROCESS_ARG(1);
 
   TREE_READONLY (t) = read_only;
   TREE_CONSTANT (t) = constant;
-  TREE_INVARIANT (t) = invariant;
   TREE_SIDE_EFFECTS (t) = side_effects;
   TREE_THIS_VOLATILE (t)
     = (TREE_CODE_CLASS (code) == tcc_reference
@@ -3100,26 +3285,11 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
 }
 
 
-/* Build a GIMPLE_MODIFY_STMT node.  This tree code doesn't have a
-   type, so we can't use build2 (a.k.a. build2_stat).  */
-
-tree
-build_gimple_modify_stmt_stat (tree arg0, tree arg1 MEM_STAT_DECL)
-{
-  tree t;
-
-  t = make_node_stat (GIMPLE_MODIFY_STMT PASS_MEM_STAT);
-  /* ?? We don't care about setting flags for tuples...  */
-  GIMPLE_STMT_OPERAND (t, 0) = arg0;
-  GIMPLE_STMT_OPERAND (t, 1) = arg1;
-  return t;
-}
-
 tree
 build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
             tree arg2 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 3);
@@ -3155,7 +3325,7 @@ tree
 build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
             tree arg2, tree arg3 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 4);
@@ -3182,7 +3352,7 @@ tree
 build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
             tree arg2, tree arg3, tree arg4 MEM_STAT_DECL)
 {
-  bool constant, read_only, side_effects, invariant;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (TREE_CODE_LENGTH (code) == 5);
@@ -3211,7 +3381,7 @@ 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;
+  bool constant, read_only, side_effects;
   tree t;
 
   gcc_assert (code == TARGET_MEM_REF);
@@ -3302,8 +3472,6 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL)
 
   if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
     layout_decl (t, 0);
-  else if (code == FUNCTION_DECL)
-    DECL_MODE (t) = FUNCTION_MODE;
 
   return t;
 }
@@ -3341,13 +3509,6 @@ build_block (tree vars, tree subblocks, tree supercontext, tree chain)
   return block;
 }
 
-#if 1 /* ! defined(USE_MAPPED_LOCATION) */
-/* ??? gengtype doesn't handle conditionals */
-static GTY(()) source_locus last_annotated_node;
-#endif
-
-#ifdef USE_MAPPED_LOCATION
-
 expanded_location
 expand_location (source_location loc)
 {
@@ -3357,184 +3518,30 @@ expand_location (source_location loc)
       xloc.file = NULL;
       xloc.line = 0;
       xloc.column = 0;
+      xloc.sysp = 0;
     }
   else
     {
-      const struct line_map *map = linemap_lookup (&line_table, loc);
+      const struct line_map *map = linemap_lookup (line_table, loc);
       xloc.file = map->to_file;
       xloc.line = SOURCE_LINE (map, loc);
       xloc.column = SOURCE_COLUMN (map, loc);
+      xloc.sysp = map->sysp != 0;
     };
   return xloc;
 }
 
-#else
-
-/* Record the exact location where an expression or an identifier were
-   encountered.  */
-
-void
-annotate_with_file_line (tree node, const char *file, int line)
-{
-  /* Roughly one percent of the calls to this function are to annotate
-     a node with the same information already attached to that node!
-     Just return instead of wasting memory.  */
-  if (EXPR_LOCUS (node)
-      && EXPR_LINENO (node) == line
-      && (EXPR_FILENAME (node) == file
-         || !strcmp (EXPR_FILENAME (node), file)))
-    {
-      last_annotated_node = EXPR_LOCUS (node);
-      return;
-    }
-
-  /* In heavily macroized code (such as GCC itself) this single
-     entry cache can reduce the number of allocations by more
-     than half.  */
-  if (last_annotated_node
-      && last_annotated_node->line == line
-      && (last_annotated_node->file == file
-         || !strcmp (last_annotated_node->file, file)))
-    {
-      SET_EXPR_LOCUS (node, last_annotated_node);
-      return;
-    }
-
-  SET_EXPR_LOCUS (node, ggc_alloc (sizeof (location_t)));
-  EXPR_LINENO (node) = line;
-  EXPR_FILENAME (node) = file;
-  last_annotated_node = EXPR_LOCUS (node);
-}
-
-void
-annotate_with_locus (tree node, location_t locus)
-{
-  annotate_with_file_line (node, locus.file, locus.line);
-}
-#endif
 \f
 /* Source location accessor functions.  */
 
 
-/* The source location of this expression.  Non-tree_exp nodes such as
-   decls and constants can be shared among multiple locations, so
-   return nothing.  */
-location_t
-expr_location (tree node)
-{
-#ifdef USE_MAPPED_LOCATION
-  if (GIMPLE_STMT_P (node))
-    return GIMPLE_STMT_LOCUS (node);
-  return EXPR_P (node) ? node->exp.locus : UNKNOWN_LOCATION;
-#else
-  if (GIMPLE_STMT_P (node))
-    return EXPR_HAS_LOCATION (node)
-      ? *GIMPLE_STMT_LOCUS (node) : UNKNOWN_LOCATION;
-  return EXPR_HAS_LOCATION (node) ? *node->exp.locus : UNKNOWN_LOCATION;
-#endif
-}
-
-void
-set_expr_location (tree node, location_t locus)
-{
-#ifdef USE_MAPPED_LOCATION
-  if (GIMPLE_STMT_P (node))
-    GIMPLE_STMT_LOCUS (node) = locus;
-  else
-    EXPR_CHECK (node)->exp.locus = locus;
-#else
-      annotate_with_locus (node, locus);
-#endif
-}
-
-bool
-expr_has_location (tree node)
-{
-#ifdef USE_MAPPED_LOCATION
-  return expr_location (node) != UNKNOWN_LOCATION;
-#else
-  return expr_locus (node) != NULL;
-#endif
-}
-
-#ifdef USE_MAPPED_LOCATION
-source_location *
-#else
-source_locus
-#endif
-expr_locus (tree node)
-{
-#ifdef USE_MAPPED_LOCATION
-  if (GIMPLE_STMT_P (node))
-    return &GIMPLE_STMT_LOCUS (node);
-  return EXPR_P (node) ? &node->exp.locus : (location_t *) NULL;
-#else
-  if (GIMPLE_STMT_P (node))
-    return GIMPLE_STMT_LOCUS (node);
-  /* ?? The cast below was originally "(location_t *)" in the macro,
-     but that makes no sense.  ?? */
-  return EXPR_P (node) ? node->exp.locus : (source_locus) NULL;
-#endif
-}
-
 void
-set_expr_locus (tree node,
-#ifdef USE_MAPPED_LOCATION
-               source_location *loc
-#else
-               source_locus loc
-#endif
-               )
+set_expr_locus (tree node, source_location *loc)
 {
-#ifdef USE_MAPPED_LOCATION
   if (loc == NULL)
-    {
-      if (GIMPLE_STMT_P (node))
-       GIMPLE_STMT_LOCUS (node) = UNKNOWN_LOCATION;
-      else
-       EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
-    }
-  else
-    {
-      if (GIMPLE_STMT_P (node))
-       GIMPLE_STMT_LOCUS (node) = *loc;
-      else
-       EXPR_CHECK (node)->exp.locus = *loc;
-    }
-#else
-  if (GIMPLE_STMT_P (node))
-    GIMPLE_STMT_LOCUS (node) = loc;
+    EXPR_CHECK (node)->exp.locus = UNKNOWN_LOCATION;
   else
-    EXPR_CHECK (node)->exp.locus = loc;
-#endif
-}
-
-const char **
-expr_filename (tree node)
-{
-#ifdef USE_MAPPED_LOCATION
-  if (GIMPLE_STMT_P (node))
-    return &LOCATION_FILE (GIMPLE_STMT_LOCUS (node));
-  return &LOCATION_FILE (EXPR_CHECK (node)->exp.locus);
-#else
-  if (GIMPLE_STMT_P (node))
-    return &GIMPLE_STMT_LOCUS (node)->file;
-  return &(EXPR_CHECK (node)->exp.locus->file);
-#endif
-}
-
-int *
-expr_lineno (tree node)
-{
-#ifdef USE_MAPPED_LOCATION
-  if (GIMPLE_STMT_P (node))
-    return &LOCATION_LINE (GIMPLE_STMT_LOCUS (node));
-  return &LOCATION_LINE (EXPR_CHECK (node)->exp.locus);
-#else
-  if (GIMPLE_STMT_P (node))
-    return &GIMPLE_STMT_LOCUS (node)->line;
-  return &EXPR_CHECK (node)->exp.locus->line;
-#endif
+    EXPR_CHECK (node)->exp.locus = *loc;
 }
 \f
 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
@@ -3563,7 +3570,7 @@ build_decl_attribute_variant (tree ddecl, tree attribute)
 
 
 /* Produce good hash value combining VAL and VAL2.  */
-static inline hashval_t
+hashval_t
 iterative_hash_hashval_t (hashval_t val, hashval_t val2)
 {
   /* the golden ratio; an arbitrary value.  */
@@ -3575,7 +3582,7 @@ iterative_hash_hashval_t (hashval_t val, hashval_t val2)
 
 /* Produce good hash value combining PTR and VAL2.  */
 static inline hashval_t
-iterative_hash_pointer (void *ptr, hashval_t val2)
+iterative_hash_pointer (const void *ptr, hashval_t val2)
 {
   if (sizeof (ptr) == sizeof (hashval_t))
     return iterative_hash_hashval_t ((size_t) ptr, val2);
@@ -3629,21 +3636,26 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
       tree ntype;
       enum tree_code code = TREE_CODE (ttype);
 
-      ntype = copy_node (ttype);
+      /* Building a distinct copy of a tagged type is inappropriate; it
+        causes breakage in code that expects there to be a one-to-one
+        relationship between a struct and its fields.
+        build_duplicate_type is another solution (as used in
+        handle_transparent_union_attribute), but that doesn't play well
+        with the stronger C++ type identity model.  */
+      if (TREE_CODE (ttype) == RECORD_TYPE
+         || TREE_CODE (ttype) == UNION_TYPE
+         || TREE_CODE (ttype) == QUAL_UNION_TYPE
+         || TREE_CODE (ttype) == ENUMERAL_TYPE)
+       {
+         warning (OPT_Wattributes,
+                  "ignoring attributes applied to %qT after definition",
+                  TYPE_MAIN_VARIANT (ttype));
+         return build_qualified_type (ttype, quals);
+       }
 
-      TYPE_POINTER_TO (ntype) = 0;
-      TYPE_REFERENCE_TO (ntype) = 0;
-      TYPE_ATTRIBUTES (ntype) = attribute;
+      ntype = build_distinct_type_copy (ttype);
 
-      if (TYPE_STRUCTURAL_EQUALITY_P (ttype))
-       SET_TYPE_STRUCTURAL_EQUALITY (ntype);
-      else
-       TYPE_CANONICAL (ntype)
-         = build_qualified_type (TYPE_CANONICAL (ttype), quals);
-
-      /* Create a new main variant of TYPE.  */
-      TYPE_MAIN_VARIANT (ntype) = ntype;
-      TYPE_NEXT_VARIANT (ntype) = 0;
+      TYPE_ATTRIBUTES (ntype) = attribute;
       set_type_quals (ntype, TYPE_UNQUALIFIED);
 
       hashcode = iterative_hash_object (code, hashcode);
@@ -3658,8 +3670,9 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
          hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
          break;
        case ARRAY_TYPE:
-         hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
-                                           hashcode);
+         if (TYPE_DOMAIN (ntype))
+           hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
+                                             hashcode);
          break;
        case INTEGER_TYPE:
          hashcode = iterative_hash_object
@@ -3668,6 +3681,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
            (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
          break;
        case REAL_TYPE:
+       case FIXED_POINT_TYPE:
          {
            unsigned int precision = TYPE_PRECISION (ntype);
            hashcode = iterative_hash_object (precision, hashcode);
@@ -3682,11 +3696,17 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
       /* If the target-dependent attributes make NTYPE different from
         its canonical type, we will need to use structural equality
         checks for this qualified type. */
-      if (!targetm.comp_type_attributes (ntype, ttype))
+      ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+      if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
+          || !targetm.comp_type_attributes (ntype, ttype))
        SET_TYPE_STRUCTURAL_EQUALITY (ntype);
+      else
+       TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
 
       ttype = build_qualified_type (ntype, quals);
     }
+  else if (TYPE_QUALS (ttype) != quals)
+    ttype = build_qualified_type (ttype, quals);
 
   return ttype;
 }
@@ -3713,7 +3733,7 @@ build_type_attribute_variant (tree ttype, tree attribute)
    their canonicalized form.  */
 
 static int
-is_attribute_with_length_p (const char *attr, int attr_len, tree ident)
+is_attribute_with_length_p (const char *attr, int attr_len, const_tree ident)
 {
   int ident_len;
   const char *p;
@@ -3756,7 +3776,7 @@ is_attribute_with_length_p (const char *attr, int attr_len, tree ident)
    We try both `text' and `__text__', ATTR may be either one.  */
 
 int
-is_attribute_p (const char *attr, tree ident)
+is_attribute_p (const char *attr, const_tree ident)
 {
   return is_attribute_with_length_p (attr, strlen (attr), ident);
 }
@@ -3779,7 +3799,6 @@ lookup_attribute (const char *attr_name, tree list)
       if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
        return l;
     }
-
   return NULL_TREE;
 }
 
@@ -3918,7 +3937,7 @@ merge_dllimport_decl_attributes (tree old, tree new)
     }
   else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new))
     {
-      /* Warn about overriding a symbol that has already been used. eg:
+      /* Warn about overriding a symbol that has already been used, e.g.:
            extern int __attribute__ ((dllimport)) foo;
           int* bar () {return &foo;}
           int foo;
@@ -3929,8 +3948,7 @@ merge_dllimport_decl_attributes (tree old, tree new)
                   "after being referenced with dll linkage", new);
          /* If we have used a variable's address with dllimport linkage,
              keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
-             decl may already have had TREE_INVARIANT and TREE_CONSTANT
-             computed.
+             decl may already have had TREE_CONSTANT computed.
              We still remove the attribute so that assembler code refers
              to '&foo rather than '_imp__foo'.  */
          if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
@@ -3991,18 +4009,35 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
          *no_add_attrs = true;
          return tree_cons (name, args, NULL_TREE);
        }
-      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+      if (TREE_CODE (node) == RECORD_TYPE
+         || TREE_CODE (node) == UNION_TYPE)
+       {
+         node = TYPE_NAME (node);
+         if (!node)
+           return NULL_TREE;
+       }
+      else
        {
          warning (OPT_Wattributes, "%qs attribute ignored",
                   IDENTIFIER_POINTER (name));
          *no_add_attrs = true;
+         return NULL_TREE;
        }
+    }
 
+  if (TREE_CODE (node) != FUNCTION_DECL
+      && TREE_CODE (node) != VAR_DECL
+      && TREE_CODE (node) != TYPE_DECL)
+    {
+      *no_add_attrs = true;
+      warning (OPT_Wattributes, "%qs attribute ignored",
+              IDENTIFIER_POINTER (name));
       return NULL_TREE;
     }
 
-  if (TREE_CODE (node) != FUNCTION_DECL
-      && TREE_CODE (node) != VAR_DECL)
+  if (TREE_CODE (node) == TYPE_DECL
+      && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
+      && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
     {
       *no_add_attrs = true;
       warning (OPT_Wattributes, "%qs attribute ignored",
@@ -4065,6 +4100,22 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
       *no_add_attrs = true;
     }
 
+  /* A dllexport'd entity must have default visibility so that other
+     program units (shared libraries or the main executable) can see
+     it.  A dllimport'd entity must have default visibility so that
+     the linker knows that undefined references within this program
+     unit can be resolved by the dynamic linker.  */
+  if (!*no_add_attrs)
+    {
+      if (DECL_VISIBILITY_SPECIFIED (node)
+         && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
+       error ("%qs implies default visibility, but %qD has already "
+              "been declared with a different visibility", 
+              IDENTIFIER_POINTER (name), node);
+      DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
+      DECL_VISIBILITY_SPECIFIED (node) = 1;
+    }
+
   return NULL_TREE;
 }
 
@@ -4081,10 +4132,10 @@ set_type_quals (tree type, int type_quals)
   TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
 }
 
-/* Returns true iff cand is equivalent to base with type_quals.  */
+/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
 
 bool
-check_qualified_type (tree cand, tree base, int type_quals)
+check_qualified_type (const_tree cand, const_tree base, int type_quals)
 {
   return (TYPE_QUALS (cand) == type_quals
          && TYPE_NAME (cand) == TYPE_NAME (base)
@@ -4211,7 +4262,8 @@ build_variant_type_copy (tree type)
 int
 tree_map_base_eq (const void *va, const void *vb)
 {
-  const struct tree_map_base  *a = va, *b = vb;
+  const struct tree_map_base  *const a = (const struct tree_map_base *) va,
+    *const b = (const struct tree_map_base *) vb;
   return (a->from == b->from);
 }
 
@@ -4230,7 +4282,7 @@ tree_map_base_hash (const void *item)
 int
 tree_map_base_marked_p (const void *p)
 {
-  return ggc_marked_p (((struct tree_map_base *) p)->from);
+  return ggc_marked_p (((const struct tree_map_base *) p)->from);
 }
 
 unsigned int
@@ -4248,11 +4300,8 @@ decl_init_priority_lookup (tree decl)
   struct tree_map_base in;
 
   gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
-  gcc_assert (TREE_CODE (decl) == VAR_DECL
-             ? DECL_HAS_INIT_PRIORITY_P (decl)
-             : DECL_STATIC_CONSTRUCTOR (decl));
   in.from = decl;
-  h = htab_find (init_priority_for_decl, &in);
+  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
   return h ? h->init : DEFAULT_INIT_PRIORITY;
 }
 
@@ -4265,9 +4314,8 @@ decl_fini_priority_lookup (tree decl)
   struct tree_map_base in;
 
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-  gcc_assert (DECL_STATIC_DESTRUCTOR (decl));
   in.from = decl;
-  h = htab_find (init_priority_for_decl, &in);
+  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
   return h ? h->fini : DEFAULT_INIT_PRIORITY;
 }
 
@@ -4284,7 +4332,7 @@ decl_priority_info (tree decl)
 
   in.base.from = decl;
   loc = htab_find_slot (init_priority_for_decl, &in, INSERT);
-  h = *loc;
+  h = (struct tree_priority_map *) *loc;
   if (!h)
     {
       h = GGC_CNEW (struct tree_priority_map);
@@ -4330,8 +4378,8 @@ decl_restrict_base_lookup (tree from)
   struct tree_map in;
 
   in.base.from = from;
-  h = htab_find_with_hash (restrict_base_for_decl, &in,
-                          htab_hash_pointer (from));
+  h = (struct tree_map *) htab_find_with_hash (restrict_base_for_decl, &in,
+                                              htab_hash_pointer (from));
   return h ? h->to : NULL_TREE;
 }
 
@@ -4343,7 +4391,7 @@ decl_restrict_base_insert (tree from, tree to)
   struct tree_map *h;
   void **loc;
 
-  h = ggc_alloc (sizeof (struct tree_map));
+  h = GGC_NEW (struct tree_map);
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
@@ -4395,7 +4443,8 @@ decl_debug_expr_lookup (tree from)
   struct tree_map *h, in;
   in.base.from = from;
 
-  h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
+  h = (struct tree_map *) htab_find_with_hash (debug_expr_for_decl, &in,
+                                              htab_hash_pointer (from));
   if (h)
     return h->to;
   return NULL_TREE;
@@ -4409,7 +4458,7 @@ decl_debug_expr_insert (tree from, tree to)
   struct tree_map *h;
   void **loc;
 
-  h = ggc_alloc (sizeof (struct tree_map));
+  h = GGC_NEW (struct tree_map);
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
@@ -4425,7 +4474,8 @@ decl_value_expr_lookup (tree from)
   struct tree_map *h, in;
   in.base.from = from;
 
-  h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from));
+  h = (struct tree_map *) htab_find_with_hash (value_expr_for_decl, &in,
+                                              htab_hash_pointer (from));
   if (h)
     return h->to;
   return NULL_TREE;
@@ -4439,7 +4489,7 @@ decl_value_expr_insert (tree from, tree to)
   struct tree_map *h;
   void **loc;
 
-  h = ggc_alloc (sizeof (struct tree_map));
+  h = GGC_NEW (struct tree_map);
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
@@ -4454,10 +4504,10 @@ decl_value_expr_insert (tree from, tree to)
    with types in the TREE_VALUE slots), by adding the hash codes
    of the individual types.  */
 
-unsigned int
-type_hash_list (tree list, hashval_t hashcode)
+static unsigned int
+type_hash_list (const_tree list, hashval_t hashcode)
 {
-  tree tail;
+  const_tree tail;
 
   for (tail = list; tail; tail = TREE_CHAIN (tail))
     if (TREE_VALUE (tail) != error_mark_node)
@@ -4474,7 +4524,8 @@ type_hash_list (tree list, hashval_t hashcode)
 static int
 type_hash_eq (const void *va, const void *vb)
 {
-  const struct type_hash *a = va, *b = vb;
+  const struct type_hash *const a = (const struct type_hash *) va,
+    *const b = (const struct type_hash *) vb;
 
   /* First test the things that are the same for all types.  */
   if (a->hash != b->hash
@@ -4519,6 +4570,9 @@ type_hash_eq (const void *va, const void *vb)
                  || tree_int_cst_equal (TYPE_MIN_VALUE (a->type),
                                         TYPE_MIN_VALUE (b->type))));
 
+    case FIXED_POINT_TYPE:
+      return TYPE_SATURATING (a->type) == TYPE_SATURATING (b->type);
+
     case OFFSET_TYPE:
       return TYPE_OFFSET_BASETYPE (a->type) == TYPE_OFFSET_BASETYPE (b->type);
 
@@ -4547,17 +4601,24 @@ type_hash_eq (const void *va, const void *vb)
                                      TYPE_FIELDS (b->type))));
 
     case FUNCTION_TYPE:
-      return (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
-             || (TYPE_ARG_TYPES (a->type)
-                 && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
-                 && TYPE_ARG_TYPES (b->type)
-                 && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
-                 && type_list_equal (TYPE_ARG_TYPES (a->type),
-                                     TYPE_ARG_TYPES (b->type))));
+      if (TYPE_ARG_TYPES (a->type) == TYPE_ARG_TYPES (b->type)
+         || (TYPE_ARG_TYPES (a->type)
+             && TREE_CODE (TYPE_ARG_TYPES (a->type)) == TREE_LIST
+             && TYPE_ARG_TYPES (b->type)
+             && TREE_CODE (TYPE_ARG_TYPES (b->type)) == TREE_LIST
+             && type_list_equal (TYPE_ARG_TYPES (a->type),
+                                 TYPE_ARG_TYPES (b->type))))
+       break;
+      return 0;
 
     default:
       return 0;
     }
+
+  if (lang_hooks.types.type_hash_eq != NULL)
+    return lang_hooks.types.type_hash_eq (a->type, b->type);
+
+  return 1;
 }
 
 /* Return the cached hash value.  */
@@ -4583,7 +4644,8 @@ type_hash_lookup (hashval_t hashcode, tree type)
   in.hash = hashcode;
   in.type = type;
 
-  h = htab_find_with_hash (type_hash_table, &in, hashcode);
+  h = (struct type_hash *) htab_find_with_hash (type_hash_table, &in,
+                                               hashcode);
   if (h)
     return h->type;
   return NULL_TREE;
@@ -4598,11 +4660,11 @@ type_hash_add (hashval_t hashcode, tree type)
   struct type_hash *h;
   void **loc;
 
-  h = ggc_alloc (sizeof (struct type_hash));
+  h = GGC_NEW (struct type_hash);
   h->hash = hashcode;
   h->type = type;
   loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
-  *(struct type_hash **) loc = h;
+  *loc = (void *)h;
 }
 
 /* Given TYPE, and HASHCODE its hash code, return the canonical
@@ -4653,7 +4715,7 @@ type_hash_canon (unsigned int hashcode, tree type)
 static int
 type_hash_marked_p (const void *p)
 {
-  tree type = ((struct type_hash *) p)->type;
+  const_tree const type = ((const struct type_hash *) p)->type;
 
   return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type);
 }
@@ -4671,10 +4733,10 @@ print_type_hash_statistics (void)
    with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
    by adding the hash codes of the individual attributes.  */
 
-unsigned int
-attribute_hash_list (tree list, hashval_t hashcode)
+static unsigned int
+attribute_hash_list (const_tree list, hashval_t hashcode)
 {
-  tree tail;
+  const_tree tail;
 
   for (tail = list; tail; tail = TREE_CHAIN (tail))
     /* ??? Do we want to add in TREE_VALUE too? */
@@ -4687,7 +4749,7 @@ attribute_hash_list (tree list, hashval_t hashcode)
    equivalent to l1.  */
 
 int
-attribute_list_equal (tree l1, tree l2)
+attribute_list_equal (const_tree l1, const_tree l2)
 {
   return attribute_list_contained (l1, l2)
         && attribute_list_contained (l2, l1);
@@ -4702,9 +4764,9 @@ attribute_list_equal (tree l1, tree l2)
    correctly.  */
 
 int
-attribute_list_contained (tree l1, tree l2)
+attribute_list_contained (const_tree l1, const_tree l2)
 {
-  tree t1, t2;
+  const_tree t1, t2;
 
   /* First check the obvious, maybe the lists are identical.  */
   if (l1 == l2)
@@ -4723,8 +4785,12 @@ attribute_list_contained (tree l1, tree l2)
 
   for (; t2 != 0; t2 = TREE_CHAIN (t2))
     {
-      tree attr;
-      for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
+      const_tree attr;
+      /* This CONST_CAST is okay because lookup_attribute does not
+        modify its argument and the return value is assigned to a
+        const_tree.  */
+      for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
+                                   CONST_CAST_TREE(l1));
           attr != NULL_TREE;
           attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
                                    TREE_CHAIN (attr)))
@@ -4755,9 +4821,9 @@ attribute_list_contained (tree l1, tree l2)
    Also, the TREE_PURPOSEs must match.  */
 
 int
-type_list_equal (tree l1, tree l2)
+type_list_equal (const_tree l1, const_tree l2)
 {
-  tree t1, t2;
+  const_tree t1, t2;
 
   for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
     if (TREE_VALUE (t1) != TREE_VALUE (t2)
@@ -4775,7 +4841,7 @@ type_list_equal (tree l1, tree l2)
    then this function counts only the ordinary arguments.  */
 
 int
-type_num_arguments (tree type)
+type_num_arguments (const_tree type)
 {
   int i = 0;
   tree t;
@@ -4795,7 +4861,7 @@ type_num_arguments (tree type)
    represent the same constant value.  */
 
 int
-tree_int_cst_equal (tree t1, tree t2)
+tree_int_cst_equal (const_tree t1, const_tree t2)
 {
   if (t1 == t2)
     return 1;
@@ -4816,7 +4882,7 @@ tree_int_cst_equal (tree t1, tree t2)
    The precise way of comparison depends on their data type.  */
 
 int
-tree_int_cst_lt (tree t1, tree t2)
+tree_int_cst_lt (const_tree t1, const_tree t2)
 {
   if (t1 == t2)
     return 0;
@@ -4843,7 +4909,7 @@ tree_int_cst_lt (tree t1, tree t2)
 /* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2.  */
 
 int
-tree_int_cst_compare (tree t1, tree t2)
+tree_int_cst_compare (const_tree t1, const_tree t2)
 {
   if (tree_int_cst_lt (t1, t2))
     return -1;
@@ -4859,14 +4925,16 @@ tree_int_cst_compare (tree t1, tree t2)
    be represented in a single unsigned HOST_WIDE_INT.  */
 
 int
-host_integerp (tree t, int pos)
+host_integerp (const_tree t, int pos)
 {
   return (TREE_CODE (t) == INTEGER_CST
          && ((TREE_INT_CST_HIGH (t) == 0
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
-                 && !TYPE_UNSIGNED (TREE_TYPE (t)))
+                 && (!TYPE_UNSIGNED (TREE_TYPE (t))
+                     || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+                         && TYPE_IS_SIZETYPE (TREE_TYPE (t)))))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
 }
 
@@ -4875,7 +4943,7 @@ host_integerp (tree t, int pos)
    be non-negative.  We must be able to satisfy the above conditions.  */
 
 HOST_WIDE_INT
-tree_low_cst (tree t, int pos)
+tree_low_cst (const_tree t, int pos)
 {
   gcc_assert (host_integerp (t, pos));
   return TREE_INT_CST_LOW (t);
@@ -4884,7 +4952,7 @@ tree_low_cst (tree t, int pos)
 /* Return the most significant bit of the integer constant T.  */
 
 int
-tree_int_cst_msb (tree t)
+tree_int_cst_msb (const_tree t)
 {
   int prec;
   HOST_WIDE_INT h;
@@ -4903,7 +4971,7 @@ tree_int_cst_msb (tree t)
    Note that -1 will never be returned if T's type is unsigned.  */
 
 int
-tree_int_cst_sgn (tree t)
+tree_int_cst_sgn (const_tree t)
 {
   if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0)
     return 0;
@@ -4919,7 +4987,7 @@ tree_int_cst_sgn (tree t)
    are known to be equal; otherwise return 0.  */
 
 int
-simple_cst_list_equal (tree l1, tree l2)
+simple_cst_list_equal (const_tree l1, const_tree l2)
 {
   while (l1 != NULL_TREE && l2 != NULL_TREE)
     {
@@ -4940,7 +5008,7 @@ simple_cst_list_equal (tree l1, tree l2)
    this function.  */
 
 int
-simple_cst_equal (tree t1, tree t2)
+simple_cst_equal (const_tree t1, const_tree t2)
 {
   enum tree_code code1, code2;
   int cmp;
@@ -4979,6 +5047,9 @@ simple_cst_equal (tree t1, tree t2)
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
+    case FIXED_CST:
+      return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
+
     case STRING_CST:
       return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
              && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
@@ -5011,13 +5082,13 @@ simple_cst_equal (tree t1, tree t2)
       if (call_expr_nargs (t1) != call_expr_nargs (t2))
        return 0;
       {
-       tree arg1, arg2;
-       call_expr_arg_iterator iter1, iter2;
-       for (arg1 = first_call_expr_arg (t1, &iter1),
-              arg2 = first_call_expr_arg (t2, &iter2);
+       const_tree arg1, arg2;
+       const_call_expr_arg_iterator iter1, iter2;
+       for (arg1 = first_const_call_expr_arg (t1, &iter1),
+              arg2 = first_const_call_expr_arg (t2, &iter2);
             arg1 && arg2;
-            arg1 = next_call_expr_arg (&iter1),
-              arg2 = next_call_expr_arg (&iter2))
+            arg1 = next_const_call_expr_arg (&iter1),
+              arg2 = next_const_call_expr_arg (&iter2))
          {
            cmp = simple_cst_equal (arg1, arg2);
            if (cmp <= 0)
@@ -5104,7 +5175,7 @@ simple_cst_equal (tree t1, tree t2)
    than U, respectively.  */
 
 int
-compare_tree_int (tree t, unsigned HOST_WIDE_INT u)
+compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u)
 {
   if (tree_int_cst_sgn (t) < 0)
     return -1;
@@ -5172,13 +5243,13 @@ commutative_tree_code (enum tree_code code)
 }
 
 /* Generate a hash value for an expression.  This can be used iteratively
-   by passing a previous result as the "val" argument.
+   by passing a previous result as the VAL argument.
 
    This function is intended to produce the same hash for expressions which
    would compare equal using operand_equal_p.  */
 
 hashval_t
-iterative_hash_expr (tree t, hashval_t val)
+iterative_hash_expr (const_tree t, hashval_t val)
 {
   int i;
   enum tree_code code;
@@ -5202,6 +5273,12 @@ iterative_hash_expr (tree t, hashval_t val)
 
        return iterative_hash_hashval_t (val2, val);
       }
+    case FIXED_CST:
+      {
+       unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
+
+       return iterative_hash_hashval_t (val2, val);
+      }
     case STRING_CST:
       return iterative_hash (TREE_STRING_POINTER (t),
                             TREE_STRING_LENGTH (t), val);
@@ -5212,7 +5289,6 @@ iterative_hash_expr (tree t, hashval_t val)
       return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
 
     case SSA_NAME:
-    case VALUE_HANDLE:
       /* we can just compare by pointer.  */
       return iterative_hash_pointer (t, val);
 
@@ -5295,6 +5371,29 @@ iterative_hash_expr (tree t, hashval_t val)
       break;
     }
 }
+
+/* Generate a hash value for a pair of expressions.  This can be used
+   iteratively by passing a previous result as the VAL argument.
+
+   The same hash value is always returned for a given pair of expressions,
+   regardless of the order in which they are presented.  This is useful in
+   hashing the operands of commutative functions.  */
+
+hashval_t
+iterative_hash_exprs_commutative (const_tree t1,
+                                  const_tree t2, hashval_t val)
+{
+  hashval_t one = iterative_hash_expr (t1, 0);
+  hashval_t two = iterative_hash_expr (t2, 0);
+  hashval_t t;
+
+  if (one > two)
+    t = one, one = two, two = t;
+  val = iterative_hash_hashval_t (one, val);
+  val = iterative_hash_hashval_t (two, val);
+
+  return val;
+}
 \f
 /* Constructors for pointer, array and function types.
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
@@ -5314,6 +5413,11 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode,
   if (to_type == error_mark_node)
     return error_mark_node;
 
+  /* If the pointed-to type has the may_alias attribute set, force
+     a TYPE_REF_CAN_ALIAS_ALL pointer to be generated.  */
+  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
+    can_alias_all = true;
+
   /* In some cases, languages will have things that aren't a POINTER_TYPE
      (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO.
      In that case, return that type without regard to the rest of our
@@ -5370,6 +5474,14 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode,
 {
   tree t;
 
+  if (to_type == error_mark_node)
+    return error_mark_node;
+
+  /* If the pointed-to type has the may_alias attribute set, force
+     a TYPE_REF_CAN_ALIAS_ALL pointer to be generated.  */
+  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
+    can_alias_all = true;
+
   /* In some cases, languages will have things that aren't a REFERENCE_TYPE
      (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_REFERENCE_TO.
      In that case, return that type without regard to the rest of our
@@ -5601,20 +5713,90 @@ build_array_type (tree elt_type, tree index_type)
   return t;
 }
 
-/* Return the TYPE of the elements comprising
-   the innermost dimension of ARRAY.  */
+/* Recursively examines the array elements of TYPE, until a non-array
+   element type is found.  */
 
 tree
-get_inner_array_type (tree array)
+strip_array_types (tree type)
 {
-  tree type = TREE_TYPE (array);
-
   while (TREE_CODE (type) == ARRAY_TYPE)
     type = TREE_TYPE (type);
 
   return type;
 }
 
+/* Computes the canonical argument types from the argument type list
+   ARGTYPES. 
+
+   Upon return, *ANY_STRUCTURAL_P will be true iff either it was true
+   on entry to this function, or if any of the ARGTYPES are
+   structural.
+
+   Upon return, *ANY_NONCANONICAL_P will be true iff either it was
+   true on entry to this function, or if any of the ARGTYPES are
+   non-canonical.
+
+   Returns a canonical argument list, which may be ARGTYPES when the
+   canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is
+   true) or would not differ from ARGTYPES.  */
+
+static tree 
+maybe_canonicalize_argtypes(tree argtypes, 
+                           bool *any_structural_p,
+                           bool *any_noncanonical_p)
+{
+  tree arg;
+  bool any_noncanonical_argtypes_p = false;
+  
+  for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg))
+    {
+      if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node)
+       /* Fail gracefully by stating that the type is structural.  */
+       *any_structural_p = true;
+      else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg)))
+       *any_structural_p = true;
+      else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg)
+              || TREE_PURPOSE (arg))
+       /* If the argument has a default argument, we consider it
+          non-canonical even though the type itself is canonical.
+          That way, different variants of function and method types
+          with default arguments will all point to the variant with
+          no defaults as their canonical type.  */
+        any_noncanonical_argtypes_p = true;
+    }
+
+  if (*any_structural_p)
+    return argtypes;
+
+  if (any_noncanonical_argtypes_p)
+    {
+      /* Build the canonical list of argument types.  */
+      tree canon_argtypes = NULL_TREE;
+      bool is_void = false;
+
+      for (arg = argtypes; arg; arg = TREE_CHAIN (arg))
+        {
+          if (arg == void_list_node)
+            is_void = true;
+          else
+            canon_argtypes = tree_cons (NULL_TREE,
+                                        TYPE_CANONICAL (TREE_VALUE (arg)),
+                                        canon_argtypes);
+        }
+
+      canon_argtypes = nreverse (canon_argtypes);
+      if (is_void)
+        canon_argtypes = chainon (canon_argtypes, void_list_node);
+
+      /* There is a non-canonical type.  */
+      *any_noncanonical_p = true;
+      return canon_argtypes;
+    }
+
+  /* The canonical argument types are the same as ARGTYPES.  */
+  return argtypes;
+}
+
 /* Construct, lay out and return
    the type of functions returning type VALUE_TYPE
    given arguments of types ARG_TYPES.
@@ -5627,6 +5809,8 @@ build_function_type (tree value_type, tree arg_types)
 {
   tree t;
   hashval_t hashcode = 0;
+  bool any_structural_p, any_noncanonical_p;
+  tree canon_argtypes;
 
   if (TREE_CODE (value_type) == FUNCTION_TYPE)
     {
@@ -5639,37 +5823,49 @@ build_function_type (tree value_type, tree arg_types)
   TREE_TYPE (t) = value_type;
   TYPE_ARG_TYPES (t) = arg_types;
 
-  /* We don't have canonicalization of function types, yet. */
-  SET_TYPE_STRUCTURAL_EQUALITY (t);
-
   /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode);
   hashcode = type_hash_list (arg_types, hashcode);
   t = type_hash_canon (hashcode, t);
 
+  /* Set up the canonical type. */
+  any_structural_p   = TYPE_STRUCTURAL_EQUALITY_P (value_type);
+  any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
+  canon_argtypes = maybe_canonicalize_argtypes (arg_types, 
+                                               &any_structural_p,
+                                               &any_noncanonical_p);
+  if (any_structural_p)
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (any_noncanonical_p)
+    TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
+                                             canon_argtypes);
+      
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
   return t;
 }
 
 /* Build a function type.  The RETURN_TYPE is the type returned by the
-   function.  If additional arguments are provided, they are
-   additional argument types.  The list of argument types must always
-   be terminated by NULL_TREE.  */
+   function. If VAARGS is set, no void_type_node is appended to the
+   the list. ARGP muse be alway be terminated be a NULL_TREE.  */
 
-tree
-build_function_type_list (tree return_type, ...)
+static tree
+build_function_type_list_1 (bool vaargs, tree return_type, va_list argp)
 {
   tree t, args, last;
-  va_list p;
 
-  va_start (p, return_type);
-
-  t = va_arg (p, tree);
-  for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
+  t = va_arg (argp, tree);
+  for (args = NULL_TREE; t != NULL_TREE; t = va_arg (argp, tree))
     args = tree_cons (NULL_TREE, t, args);
 
-  if (args == NULL_TREE)
+  if (vaargs)
+    {
+         last = args;
+         if (args != NULL_TREE)
+           args = nreverse (args);
+      gcc_assert (args != NULL_TREE && last != void_list_node);
+    }
+  else if (args == NULL_TREE)
     args = void_list_node;
   else
     {
@@ -5679,10 +5875,44 @@ build_function_type_list (tree return_type, ...)
     }
   args = build_function_type (return_type, args);
 
+  return args;
+}
+
+/* Build a function type.  The RETURN_TYPE is the type returned by the
+   function.  If additional arguments are provided, they are
+   additional argument types.  The list of argument types must always
+   be terminated by NULL_TREE.  */
+
+tree
+build_function_type_list (tree return_type, ...)
+{
+  tree args;
+  va_list p;
+
+  va_start (p, return_type);
+  args = build_function_type_list_1 (false, return_type, p);
   va_end (p);
   return args;
 }
 
+/* Build a variable argument function type.  The RETURN_TYPE is the
+   type returned by the function.  If additional arguments are provided,
+   they are additional argument types.  The list of argument types must
+   always be terminated by NULL_TREE.  */
+
+tree
+build_varargs_function_type_list (tree return_type, ...)
+{
+  tree args;
+  va_list p;
+
+  va_start (p, return_type);
+  args = build_function_type_list_1 (true, return_type, p);
+  va_end (p);
+
+  return args;
+}
+
 /* Build a METHOD_TYPE for a member of BASETYPE.  The RETTYPE (a TYPE)
    and ARGTYPES (a TREE_LIST) are the return type and arguments types
    for the method.  An implicit additional parameter (of type
@@ -5696,6 +5926,8 @@ build_method_type_directly (tree basetype,
   tree t;
   tree ptype;
   int hashcode = 0;
+  bool any_structural_p, any_noncanonical_p;
+  tree canon_argtypes;
 
   /* Make a node of the sort we want.  */
   t = make_node (METHOD_TYPE);
@@ -5709,15 +5941,29 @@ build_method_type_directly (tree basetype,
   argtypes = tree_cons (NULL_TREE, ptype, argtypes);
   TYPE_ARG_TYPES (t) = argtypes;
 
-  /* We don't have canonicalization of method types yet. */
-  SET_TYPE_STRUCTURAL_EQUALITY (t);
-
   /* If we already have such a type, use the old one.  */
   hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode);
   hashcode = type_hash_list (argtypes, hashcode);
   t = type_hash_canon (hashcode, t);
 
+  /* Set up the canonical type. */
+  any_structural_p
+    = (TYPE_STRUCTURAL_EQUALITY_P (basetype)
+       || TYPE_STRUCTURAL_EQUALITY_P (rettype));
+  any_noncanonical_p
+    = (TYPE_CANONICAL (basetype) != basetype
+       || TYPE_CANONICAL (rettype) != rettype);
+  canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
+                                               &any_structural_p,
+                                               &any_noncanonical_p);
+  if (any_structural_p)
+    SET_TYPE_STRUCTURAL_EQUALITY (t);
+  else if (any_noncanonical_p)
+    TYPE_CANONICAL (t) 
+      = build_method_type_directly (TYPE_CANONICAL (basetype),
+                                   TYPE_CANONICAL (rettype),
+                                   canon_argtypes);
   if (!COMPLETE_TYPE_P (t))
     layout_type (t);
 
@@ -5768,10 +6014,10 @@ build_offset_type (tree basetype, tree type)
       if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
          || TYPE_STRUCTURAL_EQUALITY_P (type))
        SET_TYPE_STRUCTURAL_EQUALITY (t);
-      else if (TYPE_CANONICAL (basetype) != basetype
+      else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype
               || TYPE_CANONICAL (type) != type)
        TYPE_CANONICAL (t) 
-         = build_offset_type (TYPE_CANONICAL (basetype), 
+         = build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)),
                               TYPE_CANONICAL (type));
     }
 
@@ -5807,10 +6053,8 @@ build_complex_type (tree component_type)
          = build_complex_type (TYPE_CANONICAL (component_type));
     }
 
-  /* If we are writing Dwarf2 output we need to create a name,
-     since complex is a fundamental type.  */
-  if ((write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
-      && ! TYPE_NAME (t))
+  /* We need to create a name, since complex is a fundamental type.  */
+  if (! TYPE_NAME (t))
     {
       const char *name;
       if (component_type == char_type_node)
@@ -5851,11 +6095,6 @@ build_complex_type (tree component_type)
    If FOR_TYPE is nonzero, we return a value which, if converted to
    type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE.
 
-   If FOR_TYPE is nonzero, unaligned bit-field references may be changed to the
-   narrowest type that can hold the value, even if they don't exactly fit.
-   Otherwise, bit-field references are changed to a narrower type
-   only if they can be fetched directly from memory in that type.
-
    OP must have integer, real or enumeral type.  Pointers are not allowed!
 
    There are some cases where the obvious value we could return
@@ -5881,8 +6120,7 @@ get_unwidened (tree op, tree for_type)
        && TYPE_UNSIGNED (type));
   tree win = op;
 
-  while (TREE_CODE (op) == NOP_EXPR
-        || TREE_CODE (op) == CONVERT_EXPR)
+  while (CONVERT_EXPR_P (op))
     {
       int bitschange;
 
@@ -5920,8 +6158,7 @@ get_unwidened (tree op, tree for_type)
             Let's avoid computing it if it does not affect WIN
             and if UNS will not be needed again.  */
          if ((uns
-              || TREE_CODE (op) == NOP_EXPR
-              || TREE_CODE (op) == CONVERT_EXPR)
+              || CONVERT_EXPR_P (op))
              && TYPE_UNSIGNED (TREE_TYPE (op)))
            {
              uns = 1;
@@ -5930,37 +6167,6 @@ get_unwidened (tree op, tree for_type)
        }
     }
 
-  if (TREE_CODE (op) == COMPONENT_REF
-      /* Since type_for_size always gives an integer type.  */
-      && TREE_CODE (type) != REAL_TYPE
-      /* Don't crash if field not laid out yet.  */
-      && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
-      && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
-    {
-      unsigned int innerprec
-       = tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-      int unsignedp = (DECL_UNSIGNED (TREE_OPERAND (op, 1))
-                      || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 1))));
-      type = lang_hooks.types.type_for_size (innerprec, unsignedp);
-
-      /* We can get this structure field in the narrowest type it fits in.
-        If FOR_TYPE is 0, do this only for a field that matches the
-        narrower type exactly and is aligned for it
-        The resulting extension to its nominal type (a fullword type)
-        must fit the same conditions as for other extensions.  */
-
-      if (type != 0
-         && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (op)))
-         && (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
-         && (! uns || final_prec <= innerprec || unsignedp))
-       {
-         win = build3 (COMPONENT_REF, type, TREE_OPERAND (op, 0),
-                       TREE_OPERAND (op, 1), NULL_TREE);
-         TREE_SIDE_EFFECTS (win) = TREE_SIDE_EFFECTS (op);
-         TREE_THIS_VOLATILE (win) = TREE_THIS_VOLATILE (op);
-       }
-    }
-
   return win;
 }
 \f
@@ -6024,6 +6230,7 @@ get_narrower (tree op, int *unsignedp_ptr)
   if (TREE_CODE (op) == COMPONENT_REF
       /* Since type_for_size always gives an integer type.  */
       && TREE_CODE (TREE_TYPE (op)) != REAL_TYPE
+      && TREE_CODE (TREE_TYPE (op)) != FIXED_POINT_TYPE
       /* Ensure field is laid out already.  */
       && DECL_SIZE (TREE_OPERAND (op, 1)) != 0
       && host_integerp (DECL_SIZE (TREE_OPERAND (op, 1)), 1))
@@ -6061,7 +6268,7 @@ get_narrower (tree op, int *unsignedp_ptr)
    for type TYPE (an INTEGER_TYPE).  */
 
 int
-int_fits_type_p (tree c, tree type)
+int_fits_type_p (const_tree c, const_tree type)
 {
   tree type_low_bound = TYPE_MIN_VALUE (type);
   tree type_high_bound = TYPE_MAX_VALUE (type);
@@ -6139,7 +6346,7 @@ int_fits_type_p (tree c, tree type)
    precision of the type are returned instead.  */
 
 void
-get_type_static_bounds (tree type, mpz_t min, mpz_t max)
+get_type_static_bounds (const_tree type, mpz_t min, mpz_t max)
 {
   if (!POINTER_TYPE_P (type) && TYPE_MIN_VALUE (type)
       && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
@@ -6174,6 +6381,18 @@ get_type_static_bounds (tree type, mpz_t min, mpz_t max)
     }
 }
 
+/* Return true if VAR is an automatic variable defined in function FN.  */
+
+bool
+auto_var_in_fn_p (const_tree var, const_tree fn)
+{
+  return (DECL_P (var) && DECL_CONTEXT (var) == fn
+         && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL)
+              && ! TREE_STATIC (var))
+             || TREE_CODE (var) == LABEL_DECL
+             || TREE_CODE (var) == RESULT_DECL));
+}
+
 /* Subprogram of following function.  Called by walk_tree.
 
    Return *TP if it is an automatic variable or parameter of the
@@ -6188,7 +6407,7 @@ find_var_from_fn (tree *tp, int *walk_subtrees, void *data)
     *walk_subtrees = 0;
 
   else if (DECL_P (*tp)
-          && lang_hooks.tree_inlining.auto_var_in_fn_p (*tp, fn))
+          && auto_var_in_fn_p (*tp, fn))
     return *tp;
 
   return NULL_TREE;
@@ -6247,6 +6466,7 @@ variably_modified_type_p (tree type, tree fn)
 
     case INTEGER_TYPE:
     case REAL_TYPE:
+    case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
       /* Scalar types are variably modified if their end points
@@ -6296,7 +6516,7 @@ variably_modified_type_p (tree type, tree fn)
    NULL_TREE if there is no containing scope.  */
 
 tree
-get_containing_scope (tree t)
+get_containing_scope (const_tree t)
 {
   return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t));
 }
@@ -6305,7 +6525,7 @@ get_containing_scope (tree t)
    a FUNCTION_DECL, or zero if none.  */
 
 tree
-decl_function_context (tree decl)
+decl_function_context (const_tree decl)
 {
   tree context;
 
@@ -6341,7 +6561,7 @@ decl_function_context (tree decl)
    TYPE_DECLs and FUNCTION_DECLs are transparent to this function.  */
 
 tree
-decl_type_context (tree decl)
+decl_type_context (const_tree decl)
 {
   tree context = DECL_CONTEXT (decl);
 
@@ -6378,12 +6598,12 @@ decl_type_context (tree decl)
    determined.  */
 
 tree
-get_callee_fndecl (tree call)
+get_callee_fndecl (const_tree call)
 {
   tree addr;
 
   if (call == error_mark_node)
-    return call;
+    return error_mark_node;
 
   /* It's invalid to call this function with anything but a
      CALL_EXPR.  */
@@ -6546,7 +6766,7 @@ get_file_function_name (const char *type)
        file = input_filename;
 
       len = strlen (file);
-      q = alloca (9 * 2 + len + 1);
+      q = (char *) alloca (9 * 2 + len + 1);
       memcpy (q, file, len + 1);
       clean_symbol_name (q);
 
@@ -6556,7 +6776,8 @@ get_file_function_name (const char *type)
       p = q;
     }
 
-  buf = alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p) + strlen (type));
+  buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
+                        + strlen (type));
 
   /* Set up the name of the file-level functions we may need.
      Use a global object (which is already required to be unique over
@@ -6575,11 +6796,11 @@ get_file_function_name (const char *type)
    are of the caller.  */
 
 void
-tree_check_failed (const tree node, const char *file,
+tree_check_failed (const_tree node, const char *file,
                   int line, const char *function, ...)
 {
   va_list args;
-  char *buffer;
+  const char *buffer;
   unsigned length = 0;
   int code;
 
@@ -6589,23 +6810,24 @@ tree_check_failed (const tree node, const char *file,
   va_end (args);
   if (length)
     {
+      char *tmp;
       va_start (args, function);
       length += strlen ("expected ");
-      buffer = alloca (length);
+      buffer = tmp = (char *) alloca (length);
       length = 0;
       while ((code = va_arg (args, int)))
        {
          const char *prefix = length ? " or " : "expected ";
          
-         strcpy (buffer + length, prefix);
+         strcpy (tmp + length, prefix);
          length += strlen (prefix);
-         strcpy (buffer + length, tree_code_name[code]);
+         strcpy (tmp + length, tree_code_name[code]);
          length += strlen (tree_code_name[code]);
        }
       va_end (args);
     }
   else
-    buffer = (char *)"unexpected node";
+    buffer = "unexpected node";
 
   internal_error ("tree check: %s, have %s in %s, at %s:%d",
                  buffer, tree_code_name[TREE_CODE (node)],
@@ -6617,7 +6839,7 @@ tree_check_failed (const tree node, const char *file,
    the caller.  */
 
 void
-tree_not_check_failed (const tree node, const char *file,
+tree_not_check_failed (const_tree node, const char *file,
                       int line, const char *function, ...)
 {
   va_list args;
@@ -6630,7 +6852,7 @@ tree_not_check_failed (const tree node, const char *file,
     length += 4 + strlen (tree_code_name[code]);
   va_end (args);
   va_start (args, function);
-  buffer = alloca (length);
+  buffer = (char *) alloca (length);
   length = 0;
   while ((code = va_arg (args, int)))
     {
@@ -6653,7 +6875,7 @@ tree_not_check_failed (const tree node, const char *file,
    code, given in CL.  */
 
 void
-tree_class_check_failed (const tree node, const enum tree_code_class cl,
+tree_class_check_failed (const_tree node, const enum tree_code_class cl,
                         const char *file, int line, const char *function)
 {
   internal_error
@@ -6667,7 +6889,7 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl,
    dozen codes, use the knowledge that they're all sequential.  */
 
 void
-tree_range_check_failed (const tree node, const char *file, int line,
+tree_range_check_failed (const_tree node, const char *file, int line,
                         const char *function, enum tree_code c1,
                         enum tree_code c2)
 {
@@ -6679,7 +6901,7 @@ tree_range_check_failed (const tree node, const char *file, int line,
     length += 4 + strlen (tree_code_name[c]);
 
   length += strlen ("expected ");
-  buffer = alloca (length);
+  buffer = (char *) alloca (length);
   length = 0;
 
   for (c = c1; c <= c2; ++c)
@@ -6702,7 +6924,7 @@ tree_range_check_failed (const tree node, const char *file, int line,
    not have the specified code, given in CL.  */
 
 void
-tree_not_class_check_failed (const tree node, const enum tree_code_class cl,
+tree_not_class_check_failed (const_tree node, const enum tree_code_class cl,
                             const char *file, int line, const char *function)
 {
   internal_error
@@ -6716,7 +6938,7 @@ tree_not_class_check_failed (const tree node, const enum tree_code_class cl,
 /* Similar to tree_check_failed but applied to OMP_CLAUSE codes.  */
 
 void
-omp_clause_check_failed (const tree node, const char *file, int line,
+omp_clause_check_failed (const_tree node, const char *file, int line,
                          const char *function, enum omp_clause_code code)
 {
   internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d",
@@ -6728,7 +6950,7 @@ omp_clause_check_failed (const tree node, const char *file, int line,
 /* Similar to tree_range_check_failed but applied to OMP_CLAUSE codes.  */
 
 void
-omp_clause_range_check_failed (const tree node, const char *file, int line,
+omp_clause_range_check_failed (const_tree node, const char *file, int line,
                               const char *function, enum omp_clause_code c1,
                               enum omp_clause_code c2)
 {
@@ -6740,7 +6962,7 @@ omp_clause_range_check_failed (const tree node, const char *file, int line,
     length += 4 + strlen (omp_clause_code_name[c]);
 
   length += strlen ("expected ");
-  buffer = alloca (length);
+  buffer = (char *) alloca (length);
   length = 0;
 
   for (c = c1; c <= c2; ++c)
@@ -6773,7 +6995,7 @@ static const char *ts_enum_names[] = {
    whether CODE contains the tree structure identified by EN.  */
 
 void
-tree_contains_struct_check_failed (const tree node, 
+tree_contains_struct_check_failed (const_tree node, 
                                   const enum tree_node_structure_enum en,
                                   const char *file, int line, 
                                   const char *function)
@@ -6797,23 +7019,11 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
      idx + 1, len, function, trim_filename (file), line);
 }
 
-/* Similar to above, except that the check is for the bounds of a PHI_NODE's
-   (dynamically sized) vector.  */
-
-void
-phi_node_elt_check_failed (int idx, int len, const char *file, int line,
-                           const char *function)
-{
-  internal_error
-    ("tree check: accessed elt %d of phi_node with %d elts in %s, at %s:%d",
-     idx + 1, len, function, trim_filename (file), line);
-}
-
 /* Similar to above, except that the check is for the bounds of the operand
    vector of an expression node EXP.  */
 
 void
-tree_operand_check_failed (int idx, tree exp, const char *file,
+tree_operand_check_failed (int idx, const_tree exp, const char *file,
                           int line, const char *function)
 {
   int code = TREE_CODE (exp);
@@ -6827,7 +7037,7 @@ tree_operand_check_failed (int idx, tree exp, const char *file,
    operands of an OMP_CLAUSE node.  */
 
 void
-omp_clause_operand_check_failed (int idx, tree t, const char *file,
+omp_clause_operand_check_failed (int idx, const_tree t, const char *file,
                                 int line, const char *function)
 {
   internal_error
@@ -6916,6 +7126,80 @@ make_or_reuse_type (unsigned size, int unsignedp)
     return make_signed_type (size);
 }
 
+/* Create or reuse a fract type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_fract_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_short_fract_type_node
+                        : sat_short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_fract_type_node : sat_fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_fract_type_node
+                        : sat_long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_long_fract_type_node
+                        : sat_long_long_fract_type_node;
+    }
+  else
+    {
+      if (size == SHORT_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_short_fract_type_node
+                        : short_fract_type_node;
+      if (size == FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_fract_type_node : fract_type_node;
+      if (size == LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_long_fract_type_node
+                        : long_fract_type_node;
+      if (size == LONG_LONG_FRACT_TYPE_SIZE)
+       return unsignedp ? unsigned_long_long_fract_type_node
+                        : long_long_fract_type_node;
+    }
+
+  return make_fract_type (size, unsignedp, satp);
+}
+
+/* Create or reuse an accum type by SIZE, UNSIGNEDP, and SATP.  */
+
+static tree
+make_or_reuse_accum_type (unsigned size, int unsignedp, int satp)
+{
+  if (satp)
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_short_accum_type_node
+                        : sat_short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_accum_type_node : sat_accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_accum_type_node
+                        : sat_long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? sat_unsigned_long_long_accum_type_node
+                        : sat_long_long_accum_type_node;
+    }
+  else
+    {
+      if (size == SHORT_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_short_accum_type_node
+                        : short_accum_type_node;
+      if (size == ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_accum_type_node : accum_type_node;
+      if (size == LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_long_accum_type_node
+                        : long_accum_type_node;
+      if (size == LONG_LONG_ACCUM_TYPE_SIZE)
+       return unsignedp ? unsigned_long_long_accum_type_node
+                        : long_long_accum_type_node;
+    }
+
+  return make_accum_type (size, unsignedp, satp);
+}
+
 /* Create nodes for all integer types (and error_mark_node) using the sizes
    of C datatypes.  The caller should call set_sizetype soon after calling
    this function to select one of the types as sizetype.  */
@@ -7063,6 +7347,59 @@ build_common_tree_nodes_2 (int short_double)
   complex_double_type_node = build_complex_type (double_type_node);
   complex_long_double_type_node = build_complex_type (long_double_type_node);
 
+/* Make fixed-point nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \
+  sat_ ## KIND ## _type_node = \
+    make_sat_signed_ ## KIND ## _type (SIZE); \
+  sat_unsigned_ ## KIND ## _type_node = \
+    make_sat_unsigned_ ## KIND ## _type (SIZE); \
+  KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
+  unsigned_ ## KIND ## _type_node = \
+    make_unsigned_ ## KIND ## _type (SIZE);
+
+#define MAKE_FIXED_TYPE_NODE_WIDTH(KIND,WIDTH,SIZE) \
+  sat_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_signed_ ## KIND ## _type (SIZE); \
+  sat_unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_sat_unsigned_ ## KIND ## _type (SIZE); \
+  WIDTH ## KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \
+  unsigned_ ## WIDTH ## KIND ## _type_node = \
+    make_unsigned_ ## KIND ## _type (SIZE);
+
+/* Make fixed-point type nodes based on four different widths.  */
+#define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \
+  MAKE_FIXED_TYPE_NODE_WIDTH (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE (N1, N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \
+  MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE)
+
+/* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned.  */
+#define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \
+  NAME ## _type_node = \
+    make_or_reuse_signed_ ## KIND ## _type (GET_MODE_BITSIZE (MODE ## mode)); \
+  u ## NAME ## _type_node = \
+    make_or_reuse_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode)); \
+  sat_ ## NAME ## _type_node = \
+    make_or_reuse_sat_signed_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (MODE ## mode)); \
+  sat_u ## NAME ## _type_node = \
+    make_or_reuse_sat_unsigned_ ## KIND ## _type \
+      (GET_MODE_BITSIZE (U ## MODE ## mode));
+
+  /* Fixed-point type and mode nodes.  */
+  MAKE_FIXED_TYPE_NODE_FAMILY (fract, FRACT)
+  MAKE_FIXED_TYPE_NODE_FAMILY (accum, ACCUM)
+  MAKE_FIXED_MODE_NODE (fract, qq, QQ)
+  MAKE_FIXED_MODE_NODE (fract, hq, HQ)
+  MAKE_FIXED_MODE_NODE (fract, sq, SQ)
+  MAKE_FIXED_MODE_NODE (fract, dq, DQ)
+  MAKE_FIXED_MODE_NODE (fract, tq, TQ)
+  MAKE_FIXED_MODE_NODE (accum, ha, HA)
+  MAKE_FIXED_MODE_NODE (accum, sa, SA)
+  MAKE_FIXED_MODE_NODE (accum, da, DA)
+  MAKE_FIXED_MODE_NODE (accum, ta, TA)
+
   {
     tree t = targetm.build_builtin_va_list ();
 
@@ -7091,7 +7428,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
   if (ecf_flags & ECF_CONST)
     TREE_READONLY (decl) = 1;
   if (ecf_flags & ECF_PURE)
-    DECL_IS_PURE (decl) = 1;
+    DECL_PURE_P (decl) = 1;
+  if (ecf_flags & ECF_LOOPING_CONST_OR_PURE)
+    DECL_LOOPING_CONST_OR_PURE_P (decl) = 1;
   if (ecf_flags & ECF_NORETURN)
     TREE_THIS_VOLATILE (decl) = 1;
   if (ecf_flags & ECF_NOTHROW)
@@ -7297,23 +7636,24 @@ reconstruct_complex_type (tree type, tree bottom)
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
     {
-      tree argtypes;
       inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
       /* The build_method_type_directly() routine prepends 'this' to argument list,
          so we must compensate by getting rid of it.  */
-      argtypes = TYPE_ARG_TYPES (type);
-      outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner,
-                                         TYPE_ARG_TYPES (type));
-      TYPE_ARG_TYPES (outer) = argtypes;
+      outer 
+       = build_method_type_directly 
+           (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
+            inner,
+            TREE_CHAIN (TYPE_ARG_TYPES (type)));
+    }
+  else if (TREE_CODE (type) == OFFSET_TYPE)
+    {
+      inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
+      outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner);
     }
   else
     return bottom;
 
-  TYPE_READONLY (outer) = TYPE_READONLY (type);
-  TYPE_VOLATILE (outer) = TYPE_VOLATILE (type);
-
-  return outer;
+  return build_qualified_type (outer, TYPE_QUALS (type));
 }
 
 /* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
@@ -7327,6 +7667,10 @@ build_vector_type_for_mode (tree innertype, enum machine_mode mode)
     {
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UACCUM:
       nunits = GET_MODE_NUNITS (mode);
       break;
 
@@ -7369,7 +7713,7 @@ build_resx (int region_number)
 /* Given an initializer INIT, return TRUE if INIT is zero or some
    aggregate of zeros.  Otherwise return FALSE.  */
 bool
-initializer_zerop (tree init)
+initializer_zerop (const_tree init)
 {
   tree elt;
 
@@ -7387,6 +7731,9 @@ initializer_zerop (tree init)
       return real_zerop (init)
        && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
 
+    case FIXED_CST:
+      return fixed_zerop (init);
+
     case COMPLEX_CST:
       return integer_zerop (init)
        || (real_zerop (init)
@@ -7434,7 +7781,7 @@ build_omp_clause (enum omp_clause_code code)
   length = omp_clause_num_ops[code];
   size = (sizeof (struct tree_omp_clause) + (length - 1) * sizeof (tree));
 
-  t = ggc_alloc (size);
+  t = GGC_NEWVAR (union tree_node, size);
   memset (t, 0, size);
   TREE_SET_CODE (t, OMP_CLAUSE);
   OMP_CLAUSE_SET_CODE (t, code);
@@ -7476,7 +7823,7 @@ process_call_operands (tree t)
       /* Calls have side-effects, except those to const or
         pure functions.  */
       i = call_expr_flags (t);
-      if (!(i & (ECF_CONST | ECF_PURE)))
+      if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE)))
        side_effects = 1;
     }
   TREE_SIDE_EFFECTS (t) = side_effects;
@@ -7501,7 +7848,7 @@ build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL)
   tree_node_sizes[(int) e_kind] += length;
 #endif
 
-  t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+  t = (tree) ggc_alloc_zone_pass_stat (length, &tree_zone);
 
   memset (t, 0, length);
 
@@ -7656,7 +8003,7 @@ range_in_array_bounds_p (tree ref)
    location.  */
 
 bool
-needs_to_live_in_memory (tree t)
+needs_to_live_in_memory (const_tree t)
 {
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
@@ -7672,7 +8019,7 @@ needs_to_live_in_memory (tree t)
    are compatible.  It is assumed that the parent records are compatible.  */
 
 bool
-fields_compatible_p (tree f1, tree f2)
+fields_compatible_p (const_tree f1, const_tree f2)
 {
   if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
                        DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
@@ -7682,7 +8029,7 @@ fields_compatible_p (tree f1, tree f2)
                         DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
     return false;
 
-  if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+  if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
     return false;
 
   return true;
@@ -7711,32 +8058,45 @@ find_compatible_field (tree record, tree orig_field)
   return orig_field;
 }
 
-/* Return value of a constant X.  */
+/* Return value of a constant X and sign-extend it.  */
 
 HOST_WIDE_INT
-int_cst_value (tree x)
+int_cst_value (const_tree x)
 {
   unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
   unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
-  bool negative = ((val >> (bits - 1)) & 1) != 0;
 
-  gcc_assert (bits <= HOST_BITS_PER_WIDE_INT);
+  /* Make sure the sign-extended value will fit in a HOST_WIDE_INT.  */
+  gcc_assert (TREE_INT_CST_HIGH (x) == 0
+             || TREE_INT_CST_HIGH (x) == -1);
 
-  if (negative)
-    val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
-  else
-    val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+  if (bits < HOST_BITS_PER_WIDE_INT)
+    {
+      bool negative = ((val >> (bits - 1)) & 1) != 0;
+      if (negative)
+       val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+      else
+       val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+    }
 
   return val;
 }
 
+/* If TYPE is an integral type, return an equivalent type which is
+    unsigned iff UNSIGNEDP is true.  If TYPE is not an integral type,
+    return TYPE itself.  */
 
-/* Return an unsigned type the same as TYPE in other respects.  */
-
-static tree
-get_unsigned_type (tree type)
+tree
+signed_or_unsigned_type_for (int unsignedp, tree type)
 {
-  return get_signed_or_unsigned_type (1, type);
+  tree t = type;
+  if (POINTER_TYPE_P (type))
+    t = size_type_node;
+
+  if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
+    return t;
+  
+  return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
 }
 
 /* Returns unsigned variant of TYPE.  */
@@ -7744,9 +8104,7 @@ get_unsigned_type (tree type)
 tree
 unsigned_type_for (tree type)
 {
-  if (POINTER_TYPE_P (type))
-    return get_unsigned_type (size_type_node);
-  return get_unsigned_type (type);
+  return signed_or_unsigned_type_for (1, type);
 }
 
 /* Returns signed variant of TYPE.  */
@@ -7754,9 +8112,7 @@ unsigned_type_for (tree type)
 tree
 signed_type_for (tree type)
 {
-  if (POINTER_TYPE_P (type))
-    return lang_hooks.types.signed_type (size_type_node);
-  return lang_hooks.types.signed_type (type);
+  return signed_or_unsigned_type_for (0, type);
 }
 
 /* Returns the largest value obtainable by casting something in INNER type to
@@ -7875,7 +8231,7 @@ lower_bound_in_type (tree outer, tree inner)
    and get the same result, only slower.  */
 
 int
-operand_equal_for_phi_arg_p (tree arg0, tree arg1)
+operand_equal_for_phi_arg_p (const_tree arg0, const_tree arg1)
 {
   if (arg0 == arg1)
     return 1;
@@ -7889,7 +8245,7 @@ operand_equal_for_phi_arg_p (tree arg0, tree arg1)
    ??? Use ffs if available?  */
 
 tree
-num_ending_zeros (tree x)
+num_ending_zeros (const_tree x)
 {
   unsigned HOST_WIDE_INT fr, nfr;
   unsigned num, abits;
@@ -7926,7 +8282,7 @@ num_ending_zeros (tree x)
 #define WALK_SUBTREE(NODE)                             \
   do                                                   \
     {                                                  \
-      result = walk_tree (&(NODE), func, data, pset);  \
+      result = walk_tree_1 (&(NODE), func, data, pset, lh);    \
       if (result)                                      \
        return result;                                  \
     }                                                  \
@@ -7938,7 +8294,7 @@ num_ending_zeros (tree x)
 
 static tree
 walk_type_fields (tree type, walk_tree_fn func, void *data,
-                 struct pointer_set_t *pset)
+                 struct pointer_set_t *pset, walk_tree_lh lh)
 {
   tree result = NULL_TREE;
 
@@ -8018,7 +8374,8 @@ walk_type_fields (tree type, walk_tree_fn func, void *data,
    and to avoid visiting a node more than once.  */
 
 tree
-walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
+walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
+            struct pointer_set_t *pset, walk_tree_lh lh)
 {
   enum tree_code code;
   int walk_subtrees;
@@ -8065,10 +8422,12 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        return NULL_TREE;
     }
 
-  result = lang_hooks.tree_inlining.walk_subtrees (tp, &walk_subtrees, func,
-                                                  data, pset);
-  if (result || !walk_subtrees)
-    return result;
+  if (lh)
+    {
+      result = (*lh) (tp, &walk_subtrees, func, data, pset);
+      if (result || !walk_subtrees)
+        return result;
+    }
 
   switch (code)
     {
@@ -8076,6 +8435,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
     case IDENTIFIER_NODE:
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case VECTOR_CST:
     case STRING_CST:
     case BLOCK:
@@ -8157,7 +8517,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        case OMP_CLAUSE_PRIVATE:
        case OMP_CLAUSE_SHARED:
        case OMP_CLAUSE_FIRSTPRIVATE:
-       case OMP_CLAUSE_LASTPRIVATE:
        case OMP_CLAUSE_COPYIN:
        case OMP_CLAUSE_COPYPRIVATE:
        case OMP_CLAUSE_IF:
@@ -8169,8 +8528,22 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_ORDERED:
        case OMP_CLAUSE_DEFAULT:
+       case OMP_CLAUSE_UNTIED:
          WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 
+       case OMP_CLAUSE_LASTPRIVATE:
+         WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
+         WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp));
+         WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
+       case OMP_CLAUSE_COLLAPSE:
+         {
+           int i;
+           for (i = 0; i < 3; i++)
+             WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+           WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+         }
+
        case OMP_CLAUSE_REDUCTION:
          {
            int i;
@@ -8196,6 +8569,10 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
        WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
       }
 
+    case CHANGE_DYNAMIC_TYPE_EXPR:
+      WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
+      WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
+
     case DECL_EXPR:
       /* If this is a TYPE_DECL, walk into the fields of the type that it's
         defining.  We only want to walk into these fields of a type in this
@@ -8221,7 +8598,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          if (result || !walk_subtrees)
            return result;
 
-         result = walk_type_fields (*type_p, func, data, pset);
+         result = walk_type_fields (*type_p, func, data, pset, lh);
          if (result)
            return result;
 
@@ -8254,6 +8631,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          else if (TREE_CODE (*type_p) == BOOLEAN_TYPE
                   || TREE_CODE (*type_p) == ENUMERAL_TYPE
                   || TREE_CODE (*type_p) == INTEGER_TYPE
+                  || TREE_CODE (*type_p) == FIXED_POINT_TYPE
                   || TREE_CODE (*type_p) == REAL_TYPE)
            {
              WALK_SUBTREE (TYPE_MIN_VALUE (*type_p));
@@ -8266,8 +8644,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
       /* FALLTHRU */
 
     default:
-      if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
-         || IS_GIMPLE_STMT_CODE_CLASS (TREE_CODE_CLASS (code)))
+      if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
          int i, len;
 
@@ -8279,13 +8656,13 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
          if (len)
            {
              for (i = 0; i < len - 1; ++i)
-               WALK_SUBTREE (GENERIC_TREE_OPERAND (*tp, i));
-             WALK_SUBTREE_TAIL (GENERIC_TREE_OPERAND (*tp, len - 1));
+               WALK_SUBTREE (TREE_OPERAND (*tp, i));
+             WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
            }
        }
       /* If this is a type, walk the needed fields in the type.  */
       else if (TYPE_P (*tp))
-       return walk_type_fields (*tp, func, data, pset);
+       return walk_type_fields (*tp, func, data, pset, lh);
       break;
     }
 
@@ -8299,43 +8676,19 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset)
 /* Like walk_tree, but does not walk duplicate nodes more than once.  */
 
 tree
-walk_tree_without_duplicates (tree *tp, walk_tree_fn func, void *data)
+walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
+                               walk_tree_lh lh)
 {
   tree result;
   struct pointer_set_t *pset;
 
   pset = pointer_set_create ();
-  result = walk_tree (tp, func, data, pset);
+  result = walk_tree_1 (tp, func, data, pset, lh);
   pointer_set_destroy (pset);
   return result;
 }
 
 
-/* Return true if STMT is an empty statement or contains nothing but
-   empty statements.  */
-
-bool
-empty_body_p (tree stmt)
-{
-  tree_stmt_iterator i;
-  tree body;
-
-  if (IS_EMPTY_STMT (stmt))
-    return true;
-  else if (TREE_CODE (stmt) == BIND_EXPR)
-    body = BIND_EXPR_BODY (stmt);
-  else if (TREE_CODE (stmt) == STATEMENT_LIST)
-    body = stmt;
-  else
-    return false;
-
-  for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
-    if (!empty_body_p (tsi_stmt (i)))
-      return false;
-
-  return true;
-}
-
 tree *
 tree_block (tree t)
 {
@@ -8343,28 +8696,10 @@ tree_block (tree t)
 
   if (IS_EXPR_CODE_CLASS (c))
     return &t->exp.block;
-  else if (IS_GIMPLE_STMT_CODE_CLASS (c))
-    return &GIMPLE_STMT_BLOCK (t);
   gcc_unreachable ();
   return NULL;
 }
 
-tree *
-generic_tree_operand (tree node, int i)
-{
-  if (GIMPLE_STMT_P (node))
-    return &GIMPLE_STMT_OPERAND (node, i);
-  return &TREE_OPERAND (node, i);
-}
-
-tree *
-generic_tree_type (tree node)
-{
-  if (GIMPLE_STMT_P (node))
-    return &void_type_node;
-  return &TREE_TYPE (node);
-}
-
 /* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
    FIXME: don't use this function.  It exists for compatibility with
    the old representation of CALL_EXPRs where a list was used to hold the
@@ -8380,4 +8715,260 @@ call_expr_arglist (tree exp)
   return arglist;
 }
 
+
+/* Create a nameless artificial label and put it in the current function
+   context.  Returns the newly created label.  */
+
+tree
+create_artificial_label (void)
+{
+  tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+
+  DECL_ARTIFICIAL (lab) = 1;
+  DECL_IGNORED_P (lab) = 1;
+  DECL_CONTEXT (lab) = current_function_decl;
+  return lab;
+}
+
+/*  Given a tree, try to return a useful variable name that we can use
+    to prefix a temporary that is being assigned the value of the tree.
+    I.E. given  <temp> = &A, return A.  */
+
+const char *
+get_name (tree t)
+{
+  tree stripped_decl;
+
+  stripped_decl = t;
+  STRIP_NOPS (stripped_decl);
+  if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
+    return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
+  else
+    {
+      switch (TREE_CODE (stripped_decl))
+       {
+       case ADDR_EXPR:
+         return get_name (TREE_OPERAND (stripped_decl, 0));
+       default:
+         return NULL;
+       }
+    }
+}
+
+/* Return true if TYPE has a variable argument list.  */
+
+bool
+stdarg_p (tree fntype)
+{
+  function_args_iterator args_iter;
+  tree n = NULL_TREE, t;
+
+  if (!fntype)
+    return false;
+
+  FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
+    {
+      n = t;
+    }
+
+  return n != NULL_TREE && n != void_type_node;
+}
+
+/* Return true if TYPE has a prototype.  */
+
+bool
+prototype_p (tree fntype)
+{
+  tree t;
+
+  gcc_assert (fntype != NULL_TREE);
+
+  t = TYPE_ARG_TYPES (fntype);
+  return (t != NULL_TREE);
+}
+
+/* Return the number of arguments that a function has.  */
+
+int
+function_args_count (tree fntype)
+{
+  function_args_iterator args_iter;
+  tree t;
+  int num = 0;
+
+  if (fntype)
+    {
+      FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
+       {
+         num++;
+       }
+    }
+
+  return num;
+}
+
+/* If BLOCK is inlined from an __attribute__((__artificial__))
+   routine, return pointer to location from where it has been
+   called.  */
+location_t *
+block_nonartificial_location (tree block)
+{
+  location_t *ret = NULL;
+
+  while (block && TREE_CODE (block) == BLOCK
+        && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+      while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+       ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+       {
+         /* If AO is an artificial inline, point RET to the
+            call site locus at which it has been inlined and continue
+            the loop, in case AO's caller is also an artificial
+            inline.  */
+         if (DECL_DECLARED_INLINE_P (ao)
+             && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
+           ret = &BLOCK_SOURCE_LOCATION (block);
+         else
+           break;
+       }
+      else if (TREE_CODE (ao) != BLOCK)
+       break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+  return ret;
+}
+
+/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
+   nodes.  */
+
+/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code.  */
+
+static hashval_t
+cl_option_hash_hash (const void *x)
+{
+  const_tree const t = (const_tree) x;
+  const char *p;
+  size_t i;
+  size_t len = 0;
+  hashval_t hash = 0;
+
+  if (TREE_CODE (t) == OPTIMIZATION_NODE)
+    {
+      p = (const char *)TREE_OPTIMIZATION (t);
+      len = sizeof (struct cl_optimization);
+    }
+
+  else if (TREE_CODE (t) == TARGET_OPTION_NODE)
+    {
+      p = (const char *)TREE_TARGET_OPTION (t);
+      len = sizeof (struct cl_target_option);
+    }
+
+  else
+    gcc_unreachable ();
+
+  /* assume most opt flags are just 0/1, some are 2-3, and a few might be
+     something else.  */
+  for (i = 0; i < len; i++)
+    if (p[i])
+      hash = (hash << 4) ^ ((i << 2) | p[i]);
+
+  return hash;
+}
+
+/* Return nonzero if the value represented by *X (an OPTIMIZATION or
+   TARGET_OPTION tree node) is the same as that given by *Y, which is the
+   same.  */
+
+static int
+cl_option_hash_eq (const void *x, const void *y)
+{
+  const_tree const xt = (const_tree) x;
+  const_tree const yt = (const_tree) y;
+  const char *xp;
+  const char *yp;
+  size_t len;
+
+  if (TREE_CODE (xt) != TREE_CODE (yt))
+    return 0;
+
+  if (TREE_CODE (xt) == OPTIMIZATION_NODE)
+    {
+      xp = (const char *)TREE_OPTIMIZATION (xt);
+      yp = (const char *)TREE_OPTIMIZATION (yt);
+      len = sizeof (struct cl_optimization);
+    }
+
+  else if (TREE_CODE (xt) == TARGET_OPTION_NODE)
+    {
+      xp = (const char *)TREE_TARGET_OPTION (xt);
+      yp = (const char *)TREE_TARGET_OPTION (yt);
+      len = sizeof (struct cl_target_option);
+    }
+
+  else
+    gcc_unreachable ();
+
+  return (memcmp (xp, yp, len) == 0);
+}
+
+/* Build an OPTIMIZATION_NODE based on the current options.  */
+
+tree
+build_optimization_node (void)
+{
+  tree t;
+  void **slot;
+
+  /* Use the cache of optimization nodes.  */
+
+  cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node));
+
+  slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
+  t = (tree) *slot;
+  if (!t)
+    {
+      /* Insert this one into the hash table.  */
+      t = cl_optimization_node;
+      *slot = t;
+
+      /* Make a new node for next time round.  */
+      cl_optimization_node = make_node (OPTIMIZATION_NODE);
+    }
+
+  return t;
+}
+
+/* Build a TARGET_OPTION_NODE based on the current options.  */
+
+tree
+build_target_option_node (void)
+{
+  tree t;
+  void **slot;
+
+  /* Use the cache of optimization nodes.  */
+
+  cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node));
+
+  slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
+  t = (tree) *slot;
+  if (!t)
+    {
+      /* Insert this one into the hash table.  */
+      t = cl_target_option_node;
+      *slot = t;
+
+      /* Make a new node for next time round.  */
+      cl_target_option_node = make_node (TARGET_OPTION_NODE);
+    }
+
+  return t;
+}
+
 #include "gt-tree.h"