genmatch.c (enum tree_code): Remove CONVERT{0,1,2} and VIEW_CONVERT{0,1,2}.
[gcc.git] / gcc / tree.c
index 472b6082be96beb30bcaac289ced9bb30a4c826c..7a66d1003ee2887d938eaa0483916333f8ce237a 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-independent node constructors for parse phase of GNU compiler.
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -54,7 +54,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimplify.h"
 #include "tree-dfa.h"
-#include "params.h"
 #include "langhooks-def.h"
 #include "tree-diagnostic.h"
 #include "except.h"
@@ -67,6 +66,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl.h"
 #include "regs.h"
 #include "tree-vector-builder.h"
+#include "gimple-fold.h"
+#include "escaped_string.h"
 
 /* Tree code classes.  */
 
@@ -265,6 +266,8 @@ static void print_type_hash_statistics (void);
 static void print_debug_expr_statistics (void);
 static void print_value_expr_statistics (void);
 
+static tree build_array_type_1 (tree, tree, bool, bool);
+
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
@@ -282,11 +285,14 @@ unsigned const char omp_clause_num_ops[] =
   1, /* OMP_CLAUSE_FIRSTPRIVATE  */
   2, /* OMP_CLAUSE_LASTPRIVATE  */
   5, /* OMP_CLAUSE_REDUCTION  */
+  5, /* OMP_CLAUSE_TASK_REDUCTION  */
+  5, /* OMP_CLAUSE_IN_REDUCTION  */
   1, /* OMP_CLAUSE_COPYIN  */
   1, /* OMP_CLAUSE_COPYPRIVATE  */
   3, /* OMP_CLAUSE_LINEAR  */
   2, /* OMP_CLAUSE_ALIGNED  */
   1, /* OMP_CLAUSE_DEPEND  */
+  1, /* OMP_CLAUSE_NONTEMPORAL  */
   1, /* OMP_CLAUSE_UNIFORM  */
   1, /* OMP_CLAUSE_TO_DECLARE  */
   1, /* OMP_CLAUSE_LINK  */
@@ -294,7 +300,10 @@ unsigned const char omp_clause_num_ops[] =
   2, /* OMP_CLAUSE_TO  */
   2, /* OMP_CLAUSE_MAP  */
   1, /* OMP_CLAUSE_USE_DEVICE_PTR  */
+  1, /* OMP_CLAUSE_USE_DEVICE_ADDR  */
   1, /* OMP_CLAUSE_IS_DEVICE_PTR  */
+  1, /* OMP_CLAUSE_INCLUSIVE  */
+  1, /* OMP_CLAUSE_EXCLUSIVE  */
   2, /* OMP_CLAUSE__CACHE_  */
   2, /* OMP_CLAUSE_GANG  */
   1, /* OMP_CLAUSE_ASYNC  */
@@ -302,6 +311,9 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_AUTO  */
   0, /* OMP_CLAUSE_SEQ  */
   1, /* OMP_CLAUSE__LOOPTEMP_  */
+  1, /* OMP_CLAUSE__REDUCTEMP_  */
+  1, /* OMP_CLAUSE__CONDTEMP_  */
+  1, /* OMP_CLAUSE__SCANTEMP_  */
   1, /* OMP_CLAUSE_IF  */
   1, /* OMP_CLAUSE_NUM_THREADS  */
   1, /* OMP_CLAUSE_SCHEDULE  */
@@ -321,6 +333,7 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_PROC_BIND  */
   1, /* OMP_CLAUSE_SAFELEN  */
   1, /* OMP_CLAUSE_SIMDLEN  */
+  0, /* OMP_CLAUSE_DEVICE_TYPE  */
   0, /* OMP_CLAUSE_FOR  */
   0, /* OMP_CLAUSE_PARALLEL  */
   0, /* OMP_CLAUSE_SECTIONS  */
@@ -332,7 +345,9 @@ unsigned const char omp_clause_num_ops[] =
   0, /* OMP_CLAUSE_THREADS  */
   0, /* OMP_CLAUSE_SIMD  */
   1, /* OMP_CLAUSE_HINT  */
-  0, /* OMP_CLAUSE_DEFALTMAP  */
+  0, /* OMP_CLAUSE_DEFAULTMAP  */
+  0, /* OMP_CLAUSE_ORDER  */
+  0, /* OMP_CLAUSE_BIND  */
   1, /* OMP_CLAUSE__SIMDUID_  */
   0, /* OMP_CLAUSE__SIMT_  */
   0, /* OMP_CLAUSE_INDEPENDENT  */
@@ -355,11 +370,14 @@ const char * const omp_clause_code_name[] =
   "firstprivate",
   "lastprivate",
   "reduction",
+  "task_reduction",
+  "in_reduction",
   "copyin",
   "copyprivate",
   "linear",
   "aligned",
   "depend",
+  "nontemporal",
   "uniform",
   "to",
   "link",
@@ -367,7 +385,10 @@ const char * const omp_clause_code_name[] =
   "to",
   "map",
   "use_device_ptr",
+  "use_device_addr",
   "is_device_ptr",
+  "inclusive",
+  "exclusive",
   "_cache_",
   "gang",
   "async",
@@ -375,6 +396,9 @@ const char * const omp_clause_code_name[] =
   "auto",
   "seq",
   "_looptemp_",
+  "_reductemp_",
+  "_condtemp_",
+  "_scantemp_",
   "if",
   "num_threads",
   "schedule",
@@ -394,6 +418,7 @@ const char * const omp_clause_code_name[] =
   "proc_bind",
   "safelen",
   "simdlen",
+  "device_type",
   "for",
   "parallel",
   "sections",
@@ -406,6 +431,8 @@ const char * const omp_clause_code_name[] =
   "simd",
   "hint",
   "defaultmap",
+  "order",
+  "bind",
   "_simduid_",
   "_simt_",
   "independent",
@@ -429,71 +456,61 @@ tree_node_structure_for_code (enum tree_code code)
   switch (TREE_CODE_CLASS (code))
     {
     case tcc_declaration:
-      {
-       switch (code)
-         {
-         case FIELD_DECL:
-           return TS_FIELD_DECL;
-         case PARM_DECL:
-           return TS_PARM_DECL;
-         case VAR_DECL:
-           return TS_VAR_DECL;
-         case LABEL_DECL:
-           return TS_LABEL_DECL;
-         case RESULT_DECL:
-           return TS_RESULT_DECL;
-         case DEBUG_EXPR_DECL:
-           return TS_DECL_WRTL;
-         case CONST_DECL:
-           return TS_CONST_DECL;
-         case TYPE_DECL:
-           return TS_TYPE_DECL;
-         case FUNCTION_DECL:
-           return TS_FUNCTION_DECL;
-         case TRANSLATION_UNIT_DECL:
-           return TS_TRANSLATION_UNIT_DECL;
-         default:
-           return TS_DECL_NON_COMMON;
-         }
-      }
-    case tcc_type:
-      return TS_TYPE_NON_COMMON;
-    case tcc_reference:
-    case tcc_comparison:
-    case tcc_unary:
+      switch (code)
+       {
+       case CONST_DECL:        return TS_CONST_DECL;
+       case DEBUG_EXPR_DECL:   return TS_DECL_WRTL;
+       case FIELD_DECL:        return TS_FIELD_DECL;
+       case FUNCTION_DECL:     return TS_FUNCTION_DECL;
+       case LABEL_DECL:        return TS_LABEL_DECL;
+       case PARM_DECL:         return TS_PARM_DECL;
+       case RESULT_DECL:       return TS_RESULT_DECL;
+       case TRANSLATION_UNIT_DECL: return TS_TRANSLATION_UNIT_DECL;
+       case TYPE_DECL:         return TS_TYPE_DECL;
+       case VAR_DECL:          return TS_VAR_DECL;
+       default:                return TS_DECL_NON_COMMON;
+       }
+
+    case tcc_type:             return TS_TYPE_NON_COMMON;
+
     case tcc_binary:
+    case tcc_comparison:
     case tcc_expression:
+    case tcc_reference:
     case tcc_statement:
-    case tcc_vl_exp:
-      return TS_EXP;
+    case tcc_unary:
+    case tcc_vl_exp:           return TS_EXP;
+
     default:  /* tcc_constant and tcc_exceptional */
       break;
     }
+
   switch (code)
     {
       /* tcc_constant cases.  */
-    case VOID_CST:             return TS_TYPED;
+    case COMPLEX_CST:          return TS_COMPLEX;
+    case FIXED_CST:            return TS_FIXED_CST;
     case INTEGER_CST:          return TS_INT_CST;
     case POLY_INT_CST:         return TS_POLY_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;
+    case VECTOR_CST:           return TS_VECTOR;
+    case VOID_CST:             return TS_TYPED;
+
       /* tcc_exceptional cases.  */
-    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 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 ERROR_MARK:           return TS_COMMON;
+    case IDENTIFIER_NODE:      return TS_IDENTIFIER;
     case OMP_CLAUSE:           return TS_OMP_CLAUSE;
     case OPTIMIZATION_NODE:    return TS_OPTIMIZATION;
+    case PLACEHOLDER_EXPR:     return TS_COMMON;
+    case SSA_NAME:             return TS_SSA_NAME;
+    case STATEMENT_LIST:       return TS_STATEMENT_LIST;
     case TARGET_OPTION_NODE:   return TS_TARGET_OPTION;
+    case TREE_BINFO:           return TS_BINFO;
+    case TREE_LIST:            return TS_LIST;
+    case TREE_VEC:             return TS_VEC;
 
     default:
       gcc_unreachable ();
@@ -1152,6 +1169,10 @@ free_node (tree node)
     vec_free (BLOCK_NONLOCALIZED_VARS (node));
   else if (code == TREE_BINFO)
     vec_free (BINFO_BASE_ACCESSES (node));
+  else if (code == OPTIMIZATION_NODE)
+    cl_optimization_option_free (TREE_OPTIMIZATION (node));
+  else if (code == TARGET_OPTION_NODE)
+    cl_target_option_free (TREE_TARGET_OPTION (node));
   ggc_free (node);
 }
 \f
@@ -1531,15 +1552,15 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst)
          if (TYPE_SIGN (type) == UNSIGNED)
            {
              /* Cache [0, N).  */
-             limit = INTEGER_SHARE_LIMIT;
-             if (IN_RANGE (hwi, 0, INTEGER_SHARE_LIMIT - 1))
+             limit = param_integer_share_limit;
+             if (IN_RANGE (hwi, 0, param_integer_share_limit - 1))
                ix = hwi;
            }
          else
            {
              /* Cache [-1, N).  */
-             limit = INTEGER_SHARE_LIMIT + 1;
-             if (IN_RANGE (hwi, -1, INTEGER_SHARE_LIMIT - 1))
+             limit = param_integer_share_limit + 1;
+             if (IN_RANGE (hwi, -1, param_integer_share_limit - 1))
                ix = hwi + 1;
            }
          break;
@@ -1715,23 +1736,24 @@ cache_integer_cst (tree t)
       if (TYPE_UNSIGNED (type))
        {
          /* Cache 0..N */
-         limit = INTEGER_SHARE_LIMIT;
+         limit = param_integer_share_limit;
 
          /* This is a little hokie, but if the prec is smaller than
-            what is necessary to hold INTEGER_SHARE_LIMIT, then the
+            what is necessary to hold param_integer_share_limit, then the
             obvious test will not get the correct answer.  */
          if (prec < HOST_BITS_PER_WIDE_INT)
            {
-             if (tree_to_uhwi (t) < (unsigned HOST_WIDE_INT) INTEGER_SHARE_LIMIT)
+             if (tree_to_uhwi (t)
+                 < (unsigned HOST_WIDE_INT) param_integer_share_limit)
                ix = tree_to_uhwi (t);
            }
-         else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
+         else if (wi::ltu_p (wi::to_wide (t), param_integer_share_limit))
            ix = tree_to_uhwi (t);
        }
       else
        {
          /* Cache -1..N */
-         limit = INTEGER_SHARE_LIMIT + 1;
+         limit = param_integer_share_limit + 1;
 
          if (integer_minus_onep (t))
            ix = 0;
@@ -1739,10 +1761,10 @@ cache_integer_cst (tree t)
            {
              if (prec < HOST_BITS_PER_WIDE_INT)
                {
-                 if (tree_to_shwi (t) < INTEGER_SHARE_LIMIT)
+                 if (tree_to_shwi (t) < param_integer_share_limit)
                    ix = tree_to_shwi (t) + 1;
                }
-             else if (wi::ltu_p (wi::to_wide (t), INTEGER_SHARE_LIMIT))
+             else if (wi::ltu_p (wi::to_wide (t), param_integer_share_limit))
                ix = tree_to_shwi (t) + 1;
            }
        }
@@ -1836,6 +1858,9 @@ make_vector (unsigned log2_npatterns,
 tree
 build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
 {
+  if (vec_safe_length (v) == 0)
+    return build_zero_cst (type);
+
   unsigned HOST_WIDE_INT idx, nelts;
   tree value;
 
@@ -1896,6 +1921,18 @@ build_vector_from_val (tree vectype, tree sc)
     }
 }
 
+/* If TYPE is not a vector type, just return SC, otherwise return
+   build_vector_from_val (TYPE, SC).  */
+
+tree
+build_uniform_cst (tree type, tree sc)
+{
+  if (!VECTOR_TYPE_P (type))
+    return sc;
+
+  return build_vector_from_val (type, sc);
+}
+
 /* Build a vector series of type TYPE in which element I has the value
    BASE + I * STEP.  The result is a constant if BASE and STEP are constant
    and a VEC_SERIES_EXPR otherwise.  */
@@ -1943,6 +1980,23 @@ build_index_vector (tree vec_type, poly_uint64 base, poly_uint64 step)
   return v.build ();
 }
 
+/* Return a VECTOR_CST of type VEC_TYPE in which the first NUM_A
+   elements are A and the rest are B.  */
+
+tree
+build_vector_a_then_b (tree vec_type, unsigned int num_a, tree a, tree b)
+{
+  gcc_assert (known_le (num_a, TYPE_VECTOR_SUBPARTS (vec_type)));
+  unsigned int count = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_type));
+  /* Optimize the constant case.  */
+  if ((count & 1) == 0 && TYPE_VECTOR_SUBPARTS (vec_type).is_constant ())
+    count /= 2;
+  tree_vector_builder builder (vec_type, count, 2);
+  for (unsigned int i = 0; i < count * 2; ++i)
+    builder.quick_push (i < num_a ? a : b);
+  return builder.build ();
+}
+
 /* Something has messed with the elements of CONSTRUCTOR C after it was built;
    calculate TREE_CONSTANT and TREE_SIDE_EFFECTS.  */
 
@@ -1995,9 +2049,9 @@ verify_constructor_flags (tree c)
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the vec pointed to by VALS.  */
 tree
-build_constructor (tree type, vec<constructor_elt, va_gc> *vals)
+build_constructor (tree type, vec<constructor_elt, va_gc> *vals MEM_STAT_DECL)
 {
-  tree c = make_node (CONSTRUCTOR);
+  tree c = make_node (CONSTRUCTOR PASS_MEM_STAT);
 
   TREE_TYPE (c) = type;
   CONSTRUCTOR_ELTS (c) = vals;
@@ -2186,6 +2240,9 @@ build_string (int len, const char *str)
 tree
 build_complex (tree type, tree real, tree imag)
 {
+  gcc_assert (CONSTANT_CLASS_P (real));
+  gcc_assert (CONSTANT_CLASS_P (imag));
+
   tree t = make_node (COMPLEX_CST);
 
   TREE_REALPART (t) = real;
@@ -2484,11 +2541,13 @@ zerop (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant zero or a complex constant
-   of zero.  */
+   of zero, or a location wrapper for such a constant.  */
 
 bool
 integer_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2506,11 +2565,13 @@ integer_zerop (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant one or the corresponding
-   complex constant.  */
+   complex constant, or a location wrapper for such a constant.  */
 
 bool
 integer_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
@@ -2528,11 +2589,14 @@ integer_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is the integer constant one.  For complex and vector,
-   return 1 if every piece is the integer constant one.  */
+   return 1 if every piece is the integer constant one.
+   Also return 1 for location wrappers for such a constant.  */
 
 bool
 integer_each_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_onep (TREE_REALPART (expr))
            && integer_onep (TREE_IMAGPART (expr)));
@@ -2541,11 +2605,14 @@ integer_each_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer containing all 1's in as much precision as
-   it contains, or a complex or vector whose subparts are such integers.  */
+   it contains, or a complex or vector whose subparts are such integers,
+   or a location wrapper for such a constant.  */
 
 bool
 integer_all_onesp (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_all_onesp (TREE_REALPART (expr))
       && integer_all_onesp (TREE_IMAGPART (expr)))
@@ -2563,11 +2630,14 @@ integer_all_onesp (const_tree expr)
          == wi::to_wide (expr));
 }
 
-/* Return 1 if EXPR is the integer constant minus one.  */
+/* Return 1 if EXPR is the integer constant minus one, or a location wrapper
+   for such a constant.  */
 
 bool
 integer_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST)
     return (integer_all_onesp (TREE_REALPART (expr))
            && integer_zerop (TREE_IMAGPART (expr)));
@@ -2576,11 +2646,13 @@ integer_minus_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer constant that is a power of 2 (i.e., has only
-   one bit on).  */
+   one bit on), or a location wrapper for such a constant.  */
 
 bool
 integer_pow2p (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == COMPLEX_CST
       && integer_pow2p (TREE_REALPART (expr))
       && integer_zerop (TREE_IMAGPART (expr)))
@@ -2593,11 +2665,14 @@ integer_pow2p (const_tree expr)
 }
 
 /* Return 1 if EXPR is an integer constant other than zero or a
-   complex constant other than zero.  */
+   complex constant other than zero, or a location wrapper for such a
+   constant.  */
 
 bool
 integer_nonzerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return ((TREE_CODE (expr) == INTEGER_CST
           && wi::to_wide (expr) != 0)
          || (TREE_CODE (expr) == COMPLEX_CST
@@ -2607,21 +2682,27 @@ integer_nonzerop (const_tree expr)
 
 /* Return 1 if EXPR is the integer constant one.  For vector,
    return 1 if every piece is the integer constant minus one
-   (representing the value TRUE).  */
+   (representing the value TRUE).
+   Also return 1 for location wrappers for such a constant.  */
 
 bool
 integer_truep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   if (TREE_CODE (expr) == VECTOR_CST)
     return integer_all_onesp (expr);
   return integer_onep (expr);
 }
 
-/* Return 1 if EXPR is the fixed-point constant zero.  */
+/* Return 1 if EXPR is the fixed-point constant zero, or a location wrapper
+   for such a constant.  */
 
 bool
 fixed_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   return (TREE_CODE (expr) == FIXED_CST
          && TREE_FIXED_CST (expr).data.is_zero ());
 }
@@ -2762,11 +2843,14 @@ tree_ctz (const_tree expr)
 }
 
 /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
-   decimal float constants, so don't return 1 for them.  */
+   decimal float constants, so don't return 1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_zerop (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2792,11 +2876,14 @@ real_zerop (const_tree expr)
 
 /* Return 1 if EXPR is the real constant one in real or complex form.
    Trailing zeroes matter for decimal float constants, so don't return
-   1 for them.  */
+   1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -2815,11 +2902,14 @@ real_onep (const_tree expr)
 }
 
 /* Return 1 if EXPR is the real constant minus one.  Trailing zeroes
-   matter for decimal float constants, so don't return 1 for them.  */
+   matter for decimal float constants, so don't return 1 for them.
+   Also return 1 for location wrappers around such a constant.  */
 
 bool
 real_minus_onep (const_tree expr)
 {
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
   switch (TREE_CODE (expr))
     {
     case REAL_CST:
@@ -3006,6 +3096,25 @@ first_field (const_tree type)
   return t;
 }
 
+/* Returns the last FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
+   UNION_TYPE TYPE, or NULL_TREE if none.  */
+
+tree
+last_field (const_tree type)
+{
+  tree last = NULL_TREE;
+
+  for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+    {
+      if (TREE_CODE (fld) != FIELD_DECL)
+       continue;
+
+      last = fld;
+    }
+
+  return last;
+}
+
 /* Concatenate two chains of nodes (chained through TREE_CHAIN)
    by modifying the last node in chain 1 to point to chain 2.
    This is the Lisp primitive `nconc'.  */
@@ -4947,7 +5056,8 @@ build_nt_call_vec (tree fn, vec<tree, va_gc> *args)
   return ret;
 }
 \f
-/* Create a DECL_... node of code CODE, name NAME and data type TYPE.
+/* Create a DECL_... node of code CODE, name NAME  (if non-null)
+   and data type TYPE.
    We do NOT enter this node in any sort of symbol table.
 
    LOC is the location of the decl.
@@ -5040,8 +5150,9 @@ protected_set_expr_location (tree t, location_t loc)
 
 /* Data used when collecting DECLs and TYPEs for language data removal.  */
 
-struct free_lang_data_d
+class free_lang_data_d
 {
+public:
   free_lang_data_d () : decls (100), types (100) {}
 
   /* Worklist to avoid excessive recursion.  */
@@ -5062,7 +5173,7 @@ struct free_lang_data_d
    language data removed.  The lists are held inside FLD.  */
 
 static void
-add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
+add_tree_to_fld_list (tree t, class free_lang_data_d *fld)
 {
   if (DECL_P (t))
     fld->decls.safe_push (t);
@@ -5075,7 +5186,7 @@ add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
 /* Push tree node T into FLD->WORKLIST.  */
 
 static inline void
-fld_worklist_push (tree t, struct free_lang_data_d *fld)
+fld_worklist_push (tree t, class free_lang_data_d *fld)
 {
   if (t && !is_lang_specific (t) && !fld->pset.contains (t))
     fld->worklist.safe_push ((t));
@@ -5083,32 +5194,59 @@ fld_worklist_push (tree t, struct free_lang_data_d *fld)
 
 
 \f
+/* Return simplified TYPE_NAME of TYPE.  */
+
+static tree
+fld_simplified_type_name (tree type)
+{
+  if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+    return TYPE_NAME (type);
+  /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the
+     TYPE_DECL if the type doesn't have linkage.
+     this must match fld_  */
+  if (type != TYPE_MAIN_VARIANT (type)
+      || (!DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type))
+         && (TREE_CODE (type) != RECORD_TYPE
+             || !TYPE_BINFO (type)
+             || !BINFO_VTABLE (TYPE_BINFO (type)))))
+    return DECL_NAME (TYPE_NAME (type));
+  return TYPE_NAME (type);
+}
+
 /* Do same comparsion as check_qualified_type skipping lang part of type
    and be more permissive about type names: we only care that names are
-   same (for diagnostics) and that ODR names are the same.  */
+   same (for diagnostics) and that ODR names are the same.
+   If INNER_TYPE is non-NULL, be sure that TREE_TYPE match it.  */
 
 static bool
-fld_type_variant_equal_p (tree t, tree v)
+fld_type_variant_equal_p (tree t, tree v, tree inner_type)
 {
   if (TYPE_QUALS (t) != TYPE_QUALS (v)
-      || TYPE_NAME (t) != TYPE_NAME (v)
-      || TYPE_ALIGN (t) != TYPE_ALIGN (v)
+      /* We want to match incomplete variants with complete types.
+        In this case we need to ignore alignment.   */
+      || ((!RECORD_OR_UNION_TYPE_P (t) || COMPLETE_TYPE_P (v))
+         && (TYPE_ALIGN (t) != TYPE_ALIGN (v)
+             || TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (v)))
+      || fld_simplified_type_name (t) != fld_simplified_type_name (v)
       || !attribute_list_equal (TYPE_ATTRIBUTES (t),
-                               TYPE_ATTRIBUTES (v)))
+                               TYPE_ATTRIBUTES (v))
+      || (inner_type && TREE_TYPE (v) != inner_type))
     return false;
 
   return true;
 }
 
-/* Find variant of FIRST that match T and create new one if necessary.  */
+/* Find variant of FIRST that match T and create new one if necessary.
+   Set TREE_TYPE to INNER_TYPE if non-NULL.  */
 
 static tree
-fld_type_variant (tree first, tree t, struct free_lang_data_d *fld)
+fld_type_variant (tree first, tree t, class free_lang_data_d *fld,
+                 tree inner_type = NULL)
 {
   if (first == TYPE_MAIN_VARIANT (t))
     return t;
   for (tree v = first; v; v = TYPE_NEXT_VARIANT (v))
-    if (fld_type_variant_equal_p (t, v))
+    if (fld_type_variant_equal_p (t, v, inner_type))
       return v;
   tree v = build_variant_type_copy (first);
   TYPE_READONLY (v) = TYPE_READONLY (t);
@@ -5118,7 +5256,19 @@ fld_type_variant (tree first, tree t, struct free_lang_data_d *fld)
   TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t);
   TYPE_NAME (v) = TYPE_NAME (t);
   TYPE_ATTRIBUTES (v) = TYPE_ATTRIBUTES (t);
-  add_tree_to_fld_list (v, fld);
+  TYPE_CANONICAL (v) = TYPE_CANONICAL (t);
+  /* Variants of incomplete types should have alignment 
+     set to BITS_PER_UNIT.  Do not copy the actual alignment.  */
+  if (!RECORD_OR_UNION_TYPE_P (v) || COMPLETE_TYPE_P (v))
+    {
+      SET_TYPE_ALIGN (v, TYPE_ALIGN (t));
+      TYPE_USER_ALIGN (v) = TYPE_USER_ALIGN (t);
+    }
+  if (inner_type)
+    TREE_TYPE (v) = inner_type;
+  gcc_checking_assert (fld_type_variant_equal_p (t,v, inner_type));
+  if (!fld->pset.add (v))
+    add_tree_to_fld_list (v, fld);
   return v;
 }
 
@@ -5126,11 +5276,65 @@ fld_type_variant (tree first, tree t, struct free_lang_data_d *fld)
 
 static hash_map<tree, tree> *fld_incomplete_types;
 
+/* Map types to simplified types.  */
+
+static hash_map<tree, tree> *fld_simplified_types;
+
+/* Produce variant of T whose TREE_TYPE is T2. If it is main variant,
+   use MAP to prevent duplicates.  */
+
+static tree
+fld_process_array_type (tree t, tree t2, hash_map<tree, tree> *map,
+                       class free_lang_data_d *fld)
+{
+  if (TREE_TYPE (t) == t2)
+    return t;
+
+  if (TYPE_MAIN_VARIANT (t) != t)
+    {
+      return fld_type_variant
+              (fld_process_array_type (TYPE_MAIN_VARIANT (t),
+                                       TYPE_MAIN_VARIANT (t2), map, fld),
+               t, fld, t2);
+    }
+
+  bool existed;
+  tree &array
+     = map->get_or_insert (t, &existed);
+  if (!existed)
+    {
+      array = build_array_type_1 (t2, TYPE_DOMAIN (t),
+                                 TYPE_TYPELESS_STORAGE (t), false);
+      TYPE_CANONICAL (array) = TYPE_CANONICAL (t);
+      if (!fld->pset.add (array))
+       add_tree_to_fld_list (array, fld);
+    }
+  return array;
+}
+
+/* Return CTX after removal of contexts that are not relevant  */
+
+static tree
+fld_decl_context (tree ctx)
+{
+  /* Variably modified types are needed for tree_is_indexable to decide
+     whether the type needs to go to local or global section.
+     This code is semi-broken but for now it is easiest to keep contexts
+     as expected.  */
+  if (ctx && TYPE_P (ctx)
+      && !variably_modified_type_p (ctx, NULL_TREE))
+     {
+       while (ctx && TYPE_P (ctx))
+        ctx = TYPE_CONTEXT (ctx);
+     }
+  return ctx;
+}
+
 /* For T being aggregate type try to turn it into a incomplete variant.
    Return T if no simplification is possible.  */
 
 static tree
-fld_incomplete_type_of (tree t, struct free_lang_data_d *fld)
+fld_incomplete_type_of (tree t, class free_lang_data_d *fld)
 {
   if (!t)
     return NULL;
@@ -5146,12 +5350,20 @@ fld_incomplete_type_of (tree t, struct free_lang_data_d *fld)
          else
            first = build_reference_type_for_mode (t2, TYPE_MODE (t),
                                                TYPE_REF_CAN_ALIAS_ALL (t));
-         add_tree_to_fld_list (first, fld);
+         gcc_assert (TYPE_CANONICAL (t2) != t2
+                     && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t)));
+         if (!fld->pset.add (first))
+           add_tree_to_fld_list (first, fld);
          return fld_type_variant (first, t, fld);
        }
       return t;
     }
-  if (!RECORD_OR_UNION_TYPE_P (t) || !COMPLETE_TYPE_P (t))
+  if (TREE_CODE (t) == ARRAY_TYPE)
+    return fld_process_array_type (t,
+                                  fld_incomplete_type_of (TREE_TYPE (t), fld),
+                                  fld_incomplete_types, fld);
+  if ((!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
+      || !COMPLETE_TYPE_P (t))
     return t;
   if (TYPE_MAIN_VARIANT (t) == t)
     {
@@ -5163,19 +5375,52 @@ fld_incomplete_type_of (tree t, struct free_lang_data_d *fld)
        {
          copy = build_distinct_type_copy (t);
 
-         /* It is possible type was not seen by free_lang_data yet.  */
-         add_tree_to_fld_list (copy, fld);
+         /* It is possible that type was not seen by free_lang_data yet.  */
+         if (!fld->pset.add (copy))
+           add_tree_to_fld_list (copy, fld);
          TYPE_SIZE (copy) = NULL;
-         SET_TYPE_MODE (copy, VOIDmode);
-         SET_TYPE_ALIGN (copy, BITS_PER_UNIT);
+         TYPE_USER_ALIGN (copy) = 0;
          TYPE_SIZE_UNIT (copy) = NULL;
+         TYPE_CANONICAL (copy) = TYPE_CANONICAL (t);
+         TREE_ADDRESSABLE (copy) = 0;
          if (AGGREGATE_TYPE_P (t))
            {
+             SET_TYPE_MODE (copy, VOIDmode);
+             SET_TYPE_ALIGN (copy, BITS_PER_UNIT);
+             TYPE_TYPELESS_STORAGE (copy) = 0;
              TYPE_FIELDS (copy) = NULL;
              TYPE_BINFO (copy) = NULL;
+             TYPE_FINAL_P (copy) = 0;
+             TYPE_EMPTY_P (copy) = 0;
            }
          else
-           TYPE_VALUES (copy) = NULL;
+           {
+             TYPE_VALUES (copy) = NULL;
+             ENUM_IS_OPAQUE (copy) = 0;
+             ENUM_IS_SCOPED (copy) = 0;
+           }
+
+         /* Build copy of TYPE_DECL in TYPE_NAME if necessary.
+            This is needed for ODR violation warnings to come out right (we
+            want duplicate TYPE_DECLs whenever the type is duplicated because
+            of ODR violation.  Because lang data in the TYPE_DECL may not
+            have been freed yet, rebuild it from scratch and copy relevant
+            fields.  */
+         TYPE_NAME (copy) = fld_simplified_type_name (copy);
+         tree name = TYPE_NAME (copy);
+
+         if (name && TREE_CODE (name) == TYPE_DECL)
+           {
+             gcc_checking_assert (TREE_TYPE (name) == t);
+             tree name2 = build_decl (DECL_SOURCE_LOCATION (name), TYPE_DECL,
+                                      DECL_NAME (name), copy);
+             if (DECL_ASSEMBLER_NAME_SET_P (name))
+               SET_DECL_ASSEMBLER_NAME (name2, DECL_ASSEMBLER_NAME (name));
+             SET_DECL_ALIGN (name2, 0);
+             DECL_CONTEXT (name2) = fld_decl_context
+                                        (DECL_CONTEXT (name));
+             TYPE_NAME (copy) = name2;
+           }
        }
       return copy;
    }
@@ -5187,10 +5432,16 @@ fld_incomplete_type_of (tree t, struct free_lang_data_d *fld)
    types.  */
 
 static tree
-fld_simplified_type (tree t, struct free_lang_data_d *fld)
+fld_simplified_type (tree t, class free_lang_data_d *fld)
 {
-  if (t && POINTER_TYPE_P (t))
+  if (!t)
+    return t;
+  if (POINTER_TYPE_P (t))
     return fld_incomplete_type_of (t, fld);
+  /* FIXME: This triggers verification error, see PR88140.  */
+  if (TREE_CODE (t) == ARRAY_TYPE && 0)
+    return fld_process_array_type (t, fld_simplified_type (TREE_TYPE (t), fld),
+                                  fld_simplified_types, fld);
   return t;
 }
 
@@ -5230,6 +5481,7 @@ free_lang_data_in_binfo (tree binfo)
   BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
   BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
   BINFO_VPTR_FIELD (binfo) = NULL_TREE;
+  TREE_PUBLIC (binfo) = 0;
 
   FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (binfo), i, t)
     free_lang_data_in_binfo (t);
@@ -5239,7 +5491,7 @@ free_lang_data_in_binfo (tree binfo)
 /* Reset all language specific information still present in TYPE.  */
 
 static void
-free_lang_data_in_type (tree type)
+free_lang_data_in_type (tree type, class free_lang_data_d *fld)
 {
   gcc_assert (TYPE_P (type));
 
@@ -5254,8 +5506,23 @@ free_lang_data_in_type (tree type)
   TREE_LANG_FLAG_5 (type) = 0;
   TREE_LANG_FLAG_6 (type) = 0;
 
+  TYPE_NEEDS_CONSTRUCTING (type) = 0;
+
+  /* Purge non-marked variants from the variants chain, so that they
+     don't reappear in the IL after free_lang_data.  */
+  while (TYPE_NEXT_VARIANT (type)
+        && !fld->pset.contains (TYPE_NEXT_VARIANT (type)))
+    {
+      tree t = TYPE_NEXT_VARIANT (type);
+      TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (t);
+      /* Turn the removed types into distinct types.  */
+      TYPE_MAIN_VARIANT (t) = t;
+      TYPE_NEXT_VARIANT (t) = NULL_TREE;
+    }
+
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
+      TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld);
       /* Remove the const and volatile qualifiers from arguments.  The
         C++ front end removes them, but the C front end does not,
         leading to false ODR violation errors when merging two
@@ -5263,6 +5530,7 @@ free_lang_data_in_type (tree type)
         different front ends.  */
       for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
        {
+          TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld);
          tree arg_type = TREE_VALUE (p);
 
          if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type))
@@ -5271,16 +5539,23 @@ free_lang_data_in_type (tree type)
                          & ~TYPE_QUAL_CONST
                          & ~TYPE_QUAL_VOLATILE;
              TREE_VALUE (p) = build_qualified_type (arg_type, quals);
-             free_lang_data_in_type (TREE_VALUE (p));
+             if (!fld->pset.add (TREE_VALUE (p)))
+               free_lang_data_in_type (TREE_VALUE (p), fld);
            }
          /* C++ FE uses TREE_PURPOSE to store initial values.  */
          TREE_PURPOSE (p) = NULL;
        }
     }
   else if (TREE_CODE (type) == METHOD_TYPE)
-    for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
-      /* C++ FE uses TREE_PURPOSE to store initial values.  */
-      TREE_PURPOSE (p) = NULL;
+    {
+      TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld);
+      for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+       {
+         /* C++ FE uses TREE_PURPOSE to store initial values.  */
+         TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld);
+         TREE_PURPOSE (p) = NULL;
+       }
+    }
   else if (RECORD_OR_UNION_TYPE_P (type))
     {
       /* Remove members that are not FIELD_DECLs from the field list
@@ -5298,8 +5573,7 @@ free_lang_data_in_type (tree type)
          free_lang_data_in_binfo (TYPE_BINFO (type));
          /* We need to preserve link to bases and virtual table for all
             polymorphic types to make devirtualization machinery working.  */
-         if (!BINFO_VTABLE (TYPE_BINFO (type))
-             || !flag_devirtualize)
+         if (!BINFO_VTABLE (TYPE_BINFO (type)))
            TYPE_BINFO (type) = NULL;
        }
     }
@@ -5307,6 +5581,23 @@ free_lang_data_in_type (tree type)
           || SCALAR_FLOAT_TYPE_P (type)
           || FIXED_POINT_TYPE_P (type))
     {
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         ENUM_IS_OPAQUE (type) = 0;
+         ENUM_IS_SCOPED (type) = 0;
+         /* Type values are used only for C++ ODR checking.  Drop them
+            for all type variants and non-ODR types.
+            For ODR types the data is freed in free_odr_warning_data.  */
+         if (TYPE_MAIN_VARIANT (type) != type
+             || !type_with_linkage_p (type))
+           TYPE_VALUES (type) = NULL;
+         else
+         /* Simplify representation by recording only values rather
+            than const decls.  */
+           for (tree e = TYPE_VALUES (type); e; e = TREE_CHAIN (e))
+             if (TREE_CODE (TREE_VALUE (e)) == CONST_DECL)
+               TREE_VALUE (e) = DECL_INITIAL (TREE_VALUE (e));
+       }
       free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
       free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
     }
@@ -5328,13 +5619,8 @@ free_lang_data_in_type (tree type)
       TYPE_CONTEXT (type) = ctx;
     }
 
-  /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the
-     TYPE_DECL if the type doesn't have linkage.  */
-  if (type != TYPE_MAIN_VARIANT (type) || ! type_with_linkage_p (type))
-    {
-      TYPE_NAME (type) = TYPE_IDENTIFIER (type);
-      TYPE_STUB_DECL (type) = NULL;
-    }
+  TYPE_STUB_DECL (type) = NULL;
+  TYPE_NAME (type) = fld_simplified_type_name (type);
 }
 
 
@@ -5360,16 +5646,21 @@ need_assembler_name_p (tree decl)
      e.g.  -fno-signed-char/-fsigned-char mismatches to be handled well.
      See cp/mangle.c:write_builtin_type for details.  */
 
-  if (flag_lto_odr_type_mering
-      && TREE_CODE (decl) == TYPE_DECL
-      && DECL_NAME (decl)
-      && decl == TYPE_NAME (TREE_TYPE (decl))
-      && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
-      && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
-      && (type_with_linkage_p (TREE_TYPE (decl))
-         || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
-      && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
-    return !DECL_ASSEMBLER_NAME_SET_P (decl);
+  if (TREE_CODE (decl) == TYPE_DECL)
+    {
+      if (DECL_NAME (decl)
+         && decl == TYPE_NAME (TREE_TYPE (decl))
+         && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
+         && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
+         && ((TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
+              && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
+             || TYPE_CXX_ODR_P (TREE_TYPE (decl)))
+         && (type_with_linkage_p (TREE_TYPE (decl))
+             || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
+         && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+       return !DECL_ASSEMBLER_NAME_SET_P (decl);
+      return false;
+    }
   /* Only FUNCTION_DECLs and VAR_DECLs are considered.  */
   if (!VAR_OR_FUNCTION_DECL_P (decl))
     return false;
@@ -5417,7 +5708,7 @@ need_assembler_name_p (tree decl)
    DECL.  */
 
 static void
-free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
+free_lang_data_in_decl (tree decl, class free_lang_data_d *fld)
 {
   gcc_assert (DECL_P (decl));
 
@@ -5445,6 +5736,18 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
  if (TREE_CODE (decl) == FUNCTION_DECL)
     {
       struct cgraph_node *node;
+      /* Frontends do not set TREE_ADDRESSABLE on public variables even though
+        the address may be taken in other unit, so this flag has no practical
+        use for middle-end.
+
+        It would make more sense if frontends set TREE_ADDRESSABLE to 0 only
+        for public objects that indeed cannot be adressed, but it is not
+        the case.  Set the flag to true so we do not get merge failures for
+        i.e. virtual tables between units that take address of it and
+        units that don't.  */
+      if (TREE_PUBLIC (decl))
+       TREE_ADDRESSABLE (decl) = true;
+      TREE_TYPE (decl) = fld_simplified_type (TREE_TYPE (decl), fld);
       if (!(node = cgraph_node::get (decl))
          || (!node->definition && !node->clones))
        {
@@ -5499,6 +5802,9 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
     }
   else if (VAR_P (decl))
     {
+      /* See comment above why we set the flag for functoins.  */
+      if (TREE_PUBLIC (decl))
+       TREE_ADDRESSABLE (decl) = true;
       if ((DECL_EXTERNAL (decl)
           && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
          || (decl_function_context (decl) && !TREE_STATIC (decl)))
@@ -5508,8 +5814,15 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
     {
       DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
       DECL_VISIBILITY_SPECIFIED (decl) = 0;
+      TREE_PUBLIC (decl) = 0;
+      TREE_PRIVATE (decl) = 0;
+      DECL_ARTIFICIAL (decl) = 0;
+      TYPE_DECL_SUPPRESS_DEBUG (decl) = 0;
       DECL_INITIAL (decl) = NULL_TREE;
       DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
+      DECL_MODE (decl) = VOIDmode;
+      SET_DECL_ALIGN (decl, 0);
+      /* TREE_TYPE is cleared at WPA time in free_odr_warning_data.  */
     }
   else if (TREE_CODE (decl) == FIELD_DECL)
     {
@@ -5527,7 +5840,8 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
       while (*nextp)
        {
          tree var = *nextp;
-         if (fndecl_built_in_p (var))
+         if (TREE_CODE (var) == FUNCTION_DECL
+             && fndecl_built_in_p (var))
            *nextp = TREE_CHAIN (var);
          else
            nextp = &TREE_CHAIN (var);
@@ -5538,24 +5852,17 @@ free_lang_data_in_decl (tree decl, struct free_lang_data_d *fld)
      not do well with TREE_CHAIN pointers linking them.
 
      Also do not drop containing types for virtual methods and tables because
-     these are needed by devirtualization.  */
+     these are needed by devirtualization.
+     C++ destructors are special because C++ frontends sometimes produces
+     virtual destructor as an alias of non-virtual destructor.  In
+     devirutalization code we always walk through aliases and we need
+     context to be preserved too.  See PR89335  */
   if (TREE_CODE (decl) != FIELD_DECL
       && ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
-          || !DECL_VIRTUAL_P (decl)))
-    {
-      tree ctx = DECL_CONTEXT (decl);
-      /* Variably modified types are needed for tree_is_indexable to decide
-        whether the type needs to go to local or global section.
-        This code is semi-broken but for now it is easiest to keep contexts
-        as expected.  */
-      if (ctx && TYPE_P (ctx)
-         && !variably_modified_type_p (ctx, NULL_TREE))
-        {
-          while (ctx && TYPE_P (ctx))
-            ctx = TYPE_CONTEXT (ctx);
-          DECL_CONTEXT (decl) = ctx;
-        }
-    }
+          || (!DECL_VIRTUAL_P (decl)
+             && (TREE_CODE (decl) != FUNCTION_DECL
+                 || !DECL_CXX_DESTRUCTOR_P (decl)))))
+    DECL_CONTEXT (decl) = fld_decl_context (DECL_CONTEXT (decl));
 }
 
 
@@ -5566,7 +5873,7 @@ static tree
 find_decls_types_r (tree *tp, int *ws, void *data)
 {
   tree t = *tp;
-  struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
+  class free_lang_data_d *fld = (class free_lang_data_d *) data;
 
   if (TREE_CODE (t) == TREE_LIST)
     return NULL_TREE;
@@ -5659,8 +5966,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
            ctx = BLOCK_SUPERCONTEXT (ctx);
          fld_worklist_push (ctx, fld);
        }
-      /* Do not walk TYPE_CANONICAL.  We do not stream it and thus do not
-        and want not to reach unused types this way.  */
+      fld_worklist_push (TYPE_CANONICAL (t), fld);
 
       if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
        {
@@ -5694,8 +6000,9 @@ find_decls_types_r (tree *tp, int *ws, void *data)
     {
       for (tree *tem = &BLOCK_VARS (t); *tem; )
        {
-         if (TREE_CODE (*tem) != VAR_DECL
-             || !auto_var_in_fn_p (*tem, DECL_CONTEXT (*tem)))
+         if (TREE_CODE (*tem) != LABEL_DECL
+             && (TREE_CODE (*tem) != VAR_DECL
+                 || !auto_var_in_fn_p (*tem, DECL_CONTEXT (*tem))))
            {
              gcc_assert (TREE_CODE (*tem) != RESULT_DECL
                          && TREE_CODE (*tem) != PARM_DECL);
@@ -5723,7 +6030,7 @@ find_decls_types_r (tree *tp, int *ws, void *data)
 /* Find decls and types in T.  */
 
 static void
-find_decls_types (tree t, struct free_lang_data_d *fld)
+find_decls_types (tree t, class free_lang_data_d *fld)
 {
   while (1)
     {
@@ -5765,7 +6072,7 @@ get_eh_types_for_runtime (tree list)
    FLD->DECLS and FLD->TYPES.  */
 
 static void
-find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
+find_decls_types_in_eh_region (eh_region r, class free_lang_data_d *fld)
 {
   switch (r->type)
     {
@@ -5808,7 +6115,7 @@ find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
    NAMESPACE_DECLs, etc).  */
 
 static void
-find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
+find_decls_types_in_node (struct cgraph_node *n, class free_lang_data_d *fld)
 {
   basic_block bb;
   struct function *fn;
@@ -5864,6 +6171,13 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
            {
              tree arg = gimple_op (stmt, i);
              find_decls_types (arg, fld);
+             /* find_decls_types doesn't walk TREE_PURPOSE of TREE_LISTs,
+                which we need for asm stmts.  */
+             if (arg
+                 && TREE_CODE (arg) == TREE_LIST
+                 && TREE_PURPOSE (arg)
+                 && gimple_code (stmt) == GIMPLE_ASM)
+               find_decls_types (TREE_PURPOSE (arg), fld);
            }
        }
     }
@@ -5877,7 +6191,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
    NAMESPACE_DECLs, etc).  */
 
 static void
-find_decls_types_in_var (varpool_node *v, struct free_lang_data_d *fld)
+find_decls_types_in_var (varpool_node *v, class free_lang_data_d *fld)
 {
   find_decls_types (v->decl, fld);
 }
@@ -5928,44 +6242,38 @@ assign_assembler_name_if_needed (tree t)
    been set up.  */
 
 static void
-free_lang_data_in_cgraph (void)
+free_lang_data_in_cgraph (class free_lang_data_d *fld)
 {
   struct cgraph_node *n;
   varpool_node *v;
-  struct free_lang_data_d fld;
   tree t;
   unsigned i;
   alias_pair *p;
 
   /* Find decls and types in the body of every function in the callgraph.  */
   FOR_EACH_FUNCTION (n)
-    find_decls_types_in_node (n, &fld);
+    find_decls_types_in_node (n, fld);
 
   FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
-    find_decls_types (p->decl, &fld);
+    find_decls_types (p->decl, fld);
 
   /* Find decls and types in every varpool symbol.  */
   FOR_EACH_VARIABLE (v)
-    find_decls_types_in_var (v, &fld);
+    find_decls_types_in_var (v, fld);
 
   /* Set the assembler name on every decl found.  We need to do this
      now because free_lang_data_in_decl will invalidate data needed
      for mangling.  This breaks mangling on interdependent decls.  */
-  FOR_EACH_VEC_ELT (fld.decls, i, t)
+  FOR_EACH_VEC_ELT (fld->decls, i, t)
     assign_assembler_name_if_needed (t);
 
   /* Traverse every decl found freeing its language data.  */
-  FOR_EACH_VEC_ELT (fld.decls, i, t)
-    free_lang_data_in_decl (t, &fld);
+  FOR_EACH_VEC_ELT (fld->decls, i, t)
+    free_lang_data_in_decl (t, fld);
 
   /* Traverse every type found freeing its language data.  */
-  FOR_EACH_VEC_ELT (fld.types, i, t)
-    free_lang_data_in_type (t);
-  if (flag_checking)
-    {
-      FOR_EACH_VEC_ELT (fld.types, i, t)
-       verify_type (t);
-    }
+  FOR_EACH_VEC_ELT (fld->types, i, t)
+    free_lang_data_in_type (t, fld);
 }
 
 
@@ -5975,13 +6283,20 @@ static unsigned
 free_lang_data (void)
 {
   unsigned i;
+  class free_lang_data_d fld;
 
   /* If we are the LTO frontend we have freed lang-specific data already.  */
   if (in_lto_p
       || (!flag_generate_lto && !flag_generate_offload))
-    return 0;
+    {
+      /* Rebuild type inheritance graph even when not doing LTO to get
+        consistent profile data.  */
+      rebuild_type_inheritance_graph ();
+      return 0;
+    }
 
   fld_incomplete_types = new hash_map<tree, tree>;
+  fld_simplified_types = new hash_map<tree, tree>;
 
   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
   if (vec_safe_is_empty (all_translation_units))
@@ -5995,7 +6310,7 @@ free_lang_data (void)
 
   /* Traverse the IL resetting language specific information for
      operands, expressions, etc.  */
-  free_lang_data_in_cgraph ();
+  free_lang_data_in_cgraph (&fld);
 
   /* Create gimple variants for common types.  */
   for (unsigned i = 0;
@@ -6008,6 +6323,22 @@ free_lang_data (void)
   lang_hooks.dwarf_name = lhd_dwarf_name;
   lang_hooks.decl_printable_name = gimple_decl_printable_name;
   lang_hooks.gimplify_expr = lhd_gimplify_expr;
+  lang_hooks.overwrite_decl_assembler_name = lhd_overwrite_decl_assembler_name;
+  lang_hooks.print_xnode = lhd_print_tree_nothing;
+  lang_hooks.print_decl = lhd_print_tree_nothing;
+  lang_hooks.print_type = lhd_print_tree_nothing;
+  lang_hooks.print_identifier = lhd_print_tree_nothing;
+
+  lang_hooks.tree_inlining.var_mod_type_p = hook_bool_tree_tree_false;
+
+  if (flag_checking)
+    {
+      int i;
+      tree t;
+
+      FOR_EACH_VEC_ELT (fld.types, i, t)
+       verify_type (t);
+    }
 
   /* We do not want the default decl_assembler_name implementation,
      rather if we have fixed everything we want a wrapper around it
@@ -6022,6 +6353,7 @@ free_lang_data (void)
   rebuild_type_inheritance_graph ();
 
   delete fld_incomplete_types;
+  delete fld_simplified_types;
 
   return 0;
 }
@@ -6090,51 +6422,11 @@ check_lang_type (const_tree cand, const_tree base)
   return lang_hooks.types.type_hash_eq (cand, base);
 }
 
-/* Returns true iff unqualified CAND and BASE are equivalent.  */
-
-bool
-check_base_type (const_tree cand, const_tree base)
-{
-  return (TYPE_NAME (cand) == TYPE_NAME (base)
-         /* Apparently this is needed for Objective-C.  */
-         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
-         /* Check alignment.  */
-         && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
-         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
-                                  TYPE_ATTRIBUTES (base)));
-}
-
-/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
-
-bool
-check_qualified_type (const_tree cand, const_tree base, int type_quals)
-{
-  return (TYPE_QUALS (cand) == type_quals
-         && check_base_type (cand, base)
-         && check_lang_type (cand, base));
-}
-
-/* Returns true iff CAND is equivalent to BASE with ALIGN.  */
-
-static bool
-check_aligned_type (const_tree cand, const_tree base, unsigned int align)
-{
-  return (TYPE_QUALS (cand) == TYPE_QUALS (base)
-         && TYPE_NAME (cand) == TYPE_NAME (base)
-         /* Apparently this is needed for Objective-C.  */
-         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
-         /* Check alignment.  */
-         && TYPE_ALIGN (cand) == align
-         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
-                                  TYPE_ATTRIBUTES (base))
-         && check_lang_type (cand, base));
-}
-
 /* This function checks to see if TYPE matches the size one of the built-in 
    atomic types, and returns that core atomic type.  */
 
 static tree
-find_atomic_core_type (tree type)
+find_atomic_core_type (const_tree type)
 {
   tree base_atomic_type;
 
@@ -6171,6 +6463,58 @@ find_atomic_core_type (tree type)
   return base_atomic_type;
 }
 
+/* Returns true iff unqualified CAND and BASE are equivalent.  */
+
+bool
+check_base_type (const_tree cand, const_tree base)
+{
+  if (TYPE_NAME (cand) != TYPE_NAME (base)
+      /* Apparently this is needed for Objective-C.  */
+      || TYPE_CONTEXT (cand) != TYPE_CONTEXT (base)
+      || !attribute_list_equal (TYPE_ATTRIBUTES (cand),
+                               TYPE_ATTRIBUTES (base)))
+    return false;
+  /* Check alignment.  */
+  if (TYPE_ALIGN (cand) == TYPE_ALIGN (base))
+    return true;
+  /* Atomic types increase minimal alignment.  We must to do so as well
+     or we get duplicated canonical types. See PR88686.  */
+  if ((TYPE_QUALS (cand) & TYPE_QUAL_ATOMIC))
+    {
+      /* See if this object can map to a basic atomic type.  */
+      tree atomic_type = find_atomic_core_type (cand);
+      if (atomic_type && TYPE_ALIGN (atomic_type) == TYPE_ALIGN (cand))
+       return true;
+    }
+  return false;
+}
+
+/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS.  */
+
+bool
+check_qualified_type (const_tree cand, const_tree base, int type_quals)
+{
+  return (TYPE_QUALS (cand) == type_quals
+         && check_base_type (cand, base)
+         && check_lang_type (cand, base));
+}
+
+/* Returns true iff CAND is equivalent to BASE with ALIGN.  */
+
+static bool
+check_aligned_type (const_tree cand, const_tree base, unsigned int align)
+{
+  return (TYPE_QUALS (cand) == TYPE_QUALS (base)
+         && TYPE_NAME (cand) == TYPE_NAME (base)
+         /* Apparently this is needed for Objective-C.  */
+         && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+         /* Check alignment.  */
+         && TYPE_ALIGN (cand) == align
+         && attribute_list_equal (TYPE_ATTRIBUTES (cand),
+                                  TYPE_ATTRIBUTES (base))
+         && check_lang_type (cand, base));
+}
+
 /* Return a version of the TYPE, qualified as indicated by the
    TYPE_QUALS, if one exists.  If no qualified version exists yet,
    return NULL_TREE.  */
@@ -6178,17 +6522,28 @@ find_atomic_core_type (tree type)
 tree
 get_qualified_type (tree type, int type_quals)
 {
-  tree t;
-
   if (TYPE_QUALS (type) == type_quals)
     return type;
 
+  tree mv = TYPE_MAIN_VARIANT (type);
+  if (check_qualified_type (mv, type, type_quals))
+    return mv;
+
   /* Search the chain of variants to see if there is already one there just
      like the one we need to have.  If so, use that existing one.  We must
      preserve the TYPE_NAME, since there is code that depends on this.  */
-  for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
-    if (check_qualified_type (t, type, type_quals))
-      return t;
+  for (tree *tp = &TYPE_NEXT_VARIANT (mv); *tp; tp = &TYPE_NEXT_VARIANT (*tp))
+    if (check_qualified_type (*tp, type, type_quals))
+      {
+       /* Put the found variant at the head of the variant list so
+          frequently searched variants get found faster.  The C++ FE
+          benefits greatly from this.  */
+       tree t = *tp;
+       *tp = TYPE_NEXT_VARIANT (t);
+       TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv);
+       TYPE_NEXT_VARIANT (mv) = t;
+       return t;
+      }
 
   return NULL_TREE;
 }
@@ -6852,12 +7207,11 @@ type_list_equal (const_tree l1, const_tree l2)
    then this function counts only the ordinary arguments.  */
 
 int
-type_num_arguments (const_tree type)
+type_num_arguments (const_tree fntype)
 {
   int i = 0;
-  tree t;
 
-  for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+  for (tree t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
     /* If the function does not take a variable number of arguments,
        the last element in the list will have type `void'.  */
     if (VOID_TYPE_P (TREE_VALUE (t)))
@@ -6868,6 +7222,40 @@ type_num_arguments (const_tree type)
   return i;
 }
 
+/* Return the type of the function TYPE's argument ARGNO if known.
+   For vararg function's where ARGNO refers to one of the variadic
+   arguments return null.  Otherwise, return a void_type_node for
+   out-of-bounds ARGNO.  */
+
+tree
+type_argument_type (const_tree fntype, unsigned argno)
+{
+  /* Treat zero the same as an out-of-bounds argument number.  */
+  if (!argno)
+    return void_type_node;
+
+  function_args_iterator iter;
+
+  tree argtype;
+  unsigned i = 1;
+  FOREACH_FUNCTION_ARGS (fntype, argtype, iter)
+    {
+      /* A vararg function's argument list ends in a null.  Otherwise,
+        an ordinary function's argument list ends with void.  Return
+        null if ARGNO refers to a vararg argument, void_type_node if
+        it's out of bounds, and the formal argument type otherwise.  */
+      if (!argtype)
+       break;
+
+      if (i == argno || VOID_TYPE_P (argtype))
+       return argtype;
+
+      ++i;
+    }
+
+  return NULL_TREE;
+}
+
 /* Nonzero if integer constants T1 and T2
    represent the same constant value.  */
 
@@ -6880,6 +7268,9 @@ tree_int_cst_equal (const_tree t1, const_tree t2)
   if (t1 == 0 || t2 == 0)
     return 0;
 
+  STRIP_ANY_LOCATION_WRAPPER (t1);
+  STRIP_ANY_LOCATION_WRAPPER (t2);
+
   if (TREE_CODE (t1) == INTEGER_CST
       && TREE_CODE (t2) == INTEGER_CST
       && wi::to_widest (t1) == wi::to_widest (t2))
@@ -7040,6 +7431,15 @@ simple_cst_equal (const_tree t1, const_tree t2)
   if (t1 == 0 || t2 == 0)
     return 0;
 
+  /* For location wrappers to be the same, they must be at the same
+     source location (and wrap the same thing).  */
+  if (location_wrapper_p (t1) && location_wrapper_p (t2))
+    {
+      if (EXPR_LOCATION (t1) != EXPR_LOCATION (t2))
+       return 0;
+      return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+    }
+
   code1 = TREE_CODE (t1);
   code2 = TREE_CODE (t2);
 
@@ -7216,10 +7616,12 @@ compare_tree_int (const_tree t, unsigned HOST_WIDE_INT u)
 
 /* Return true if SIZE represents a constant size that is in bounds of
    what the middle-end and the backend accepts (covering not more than
-   half of the address-space).  */
+   half of the address-space).
+   When PERR is non-null, set *PERR on failure to the description of
+   why SIZE is not valid.  */
 
 bool
-valid_constant_size_p (const_tree size)
+valid_constant_size_p (const_tree size, cst_size_error *perr /* = NULL */)
 {
   if (POLY_INT_CST_P (size))
     {
@@ -7230,10 +7632,36 @@ valid_constant_size_p (const_tree size)
          return false;
       return true;
     }
-  if (! tree_fits_uhwi_p (size)
-      || TREE_OVERFLOW (size)
-      || tree_int_cst_sign_bit (size) != 0)
-    return false;
+
+  cst_size_error error;
+  if (!perr)
+    perr = &error;
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      *perr = cst_size_not_constant;
+      return false;
+    }
+
+  if (TREE_OVERFLOW_P (size))
+    {
+      *perr = cst_size_overflow;
+      return false;
+    }
+
+  if (tree_int_cst_sgn (size) < 0)
+    {
+      *perr = cst_size_negative;
+      return false;
+    }
+  if (!tree_fits_uhwi_p (size)
+      || (wi::to_widest (TYPE_MAX_VALUE (sizetype))
+         < wi::to_widest (size) * 2))
+    {
+      *perr = cst_size_too_big;
+      return false;
+    }
+
   return true;
 }
 
@@ -7391,284 +7819,13 @@ operation_no_trapping_overflow (tree type, enum tree_code code)
     case LSHIFT_EXPR:
       /* These operators can overflow, but -ftrapv does not generate trapping
         code for these.  */
-      return true;
-    default:
-      /* These operators cannot overflow.  */
-      return true;
-    }
-}
-
-namespace inchash
-{
-
-/* Generate a hash value for an expression.  This can be used iteratively
-   by passing a previous result as the HSTATE argument.
-
-   This function is intended to produce the same hash for expressions which
-   would compare equal using operand_equal_p.  */
-void
-add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
-{
-  int i;
-  enum tree_code code;
-  enum tree_code_class tclass;
-
-  if (t == NULL_TREE || t == error_mark_node)
-    {
-      hstate.merge_hash (0);
-      return;
-    }
-
-  if (!(flags & OEP_ADDRESS_OF))
-    STRIP_NOPS (t);
-
-  code = TREE_CODE (t);
-
-  switch (code)
-    {
-    /* Alas, constants aren't shared, so we can't rely on pointer
-       identity.  */
-    case VOID_CST:
-      hstate.merge_hash (0);
-      return;
-    case INTEGER_CST:
-      gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
-      for (i = 0; i < TREE_INT_CST_EXT_NUNITS (t); i++)
-       hstate.add_hwi (TREE_INT_CST_ELT (t, i));
-      return;
-    case REAL_CST:
-      {
-       unsigned int val2;
-       if (!HONOR_SIGNED_ZEROS (t) && real_zerop (t))
-         val2 = rvc_zero;
-       else
-         val2 = real_hash (TREE_REAL_CST_PTR (t));
-       hstate.merge_hash (val2);
-       return;
-      }
-    case FIXED_CST:
-      {
-       unsigned int val2 = fixed_hash (TREE_FIXED_CST_PTR (t));
-       hstate.merge_hash (val2);
-       return;
-      }
-    case STRING_CST:
-      hstate.add ((const void *) TREE_STRING_POINTER (t),
-                 TREE_STRING_LENGTH (t));
-      return;
-    case COMPLEX_CST:
-      inchash::add_expr (TREE_REALPART (t), hstate, flags);
-      inchash::add_expr (TREE_IMAGPART (t), hstate, flags);
-      return;
-    case VECTOR_CST:
-      {
-       hstate.add_int (VECTOR_CST_NPATTERNS (t));
-       hstate.add_int (VECTOR_CST_NELTS_PER_PATTERN (t));
-       unsigned int count = vector_cst_encoded_nelts (t);
-       for (unsigned int i = 0; i < count; ++i)
-         inchash::add_expr (VECTOR_CST_ENCODED_ELT (t, i), hstate, flags);
-       return;
-      }
-    case SSA_NAME:
-      /* We can just compare by pointer.  */
-      hstate.add_hwi (SSA_NAME_VERSION (t));
-      return;
-    case PLACEHOLDER_EXPR:
-      /* The node itself doesn't matter.  */
-      return;
-    case BLOCK:
-    case OMP_CLAUSE:
-      /* Ignore.  */
-      return;
-    case TREE_LIST:
-      /* A list of expressions, for a CALL_EXPR or as the elements of a
-        VECTOR_CST.  */
-      for (; t; t = TREE_CHAIN (t))
-       inchash::add_expr (TREE_VALUE (t), hstate, flags);
-      return;
-    case CONSTRUCTOR:
-      {
-       unsigned HOST_WIDE_INT idx;
-       tree field, value;
-       flags &= ~OEP_ADDRESS_OF;
-       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
-         {
-           inchash::add_expr (field, hstate, flags);
-           inchash::add_expr (value, hstate, flags);
-         }
-       return;
-      }
-    case STATEMENT_LIST:
-      {
-       tree_stmt_iterator i;
-       for (i = tsi_start (CONST_CAST_TREE (t));
-            !tsi_end_p (i); tsi_next (&i))
-         inchash::add_expr (tsi_stmt (i), hstate, flags);
-       return;
-      }
-    case TREE_VEC:
-      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
-       inchash::add_expr (TREE_VEC_ELT (t, i), hstate, flags);
-      return;
-    case IDENTIFIER_NODE:
-      hstate.add_object (IDENTIFIER_HASH_VALUE (t));
-      return;
-    case FUNCTION_DECL:
-      /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
-        Otherwise nodes that compare equal according to operand_equal_p might
-        get different hash codes.  However, don't do this for machine specific
-        or front end builtins, since the function code is overloaded in those
-        cases.  */
-      if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
-         && builtin_decl_explicit_p (DECL_FUNCTION_CODE (t)))
-       {
-         t = builtin_decl_explicit (DECL_FUNCTION_CODE (t));
-         code = TREE_CODE (t);
-       }
-      /* FALL THROUGH */
-    default:
-      if (POLY_INT_CST_P (t))
-       {
-         for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-           hstate.add_wide_int (wi::to_wide (POLY_INT_CST_COEFF (t, i)));
-         return;
-       }
-      tclass = TREE_CODE_CLASS (code);
-
-      if (tclass == tcc_declaration)
-       {
-         /* DECL's have a unique ID */
-         hstate.add_hwi (DECL_UID (t));
-       }
-      else if (tclass == tcc_comparison && !commutative_tree_code (code))
-       {
-         /* For comparisons that can be swapped, use the lower
-            tree code.  */
-         enum tree_code ccode = swap_tree_comparison (code);
-         if (code < ccode)
-           ccode = code;
-         hstate.add_object (ccode);
-         inchash::add_expr (TREE_OPERAND (t, ccode != code), hstate, flags);
-         inchash::add_expr (TREE_OPERAND (t, ccode == code), hstate, flags);
-       }
-      else if (CONVERT_EXPR_CODE_P (code))
-       {
-         /* NOP_EXPR and CONVERT_EXPR are considered equal by
-            operand_equal_p.  */
-         enum tree_code ccode = NOP_EXPR;
-         hstate.add_object (ccode);
-
-         /* Don't hash the type, that can lead to having nodes which
-            compare equal according to operand_equal_p, but which
-            have different hash codes.  Make sure to include signedness
-            in the hash computation.  */
-         hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
-         inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
-       }
-      /* For OEP_ADDRESS_OF, hash MEM_EXPR[&decl, 0] the same as decl.  */
-      else if (code == MEM_REF
-              && (flags & OEP_ADDRESS_OF) != 0
-              && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
-              && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
-              && integer_zerop (TREE_OPERAND (t, 1)))
-       inchash::add_expr (TREE_OPERAND (TREE_OPERAND (t, 0), 0),
-                          hstate, flags);
-      /* Don't ICE on FE specific trees, or their arguments etc.
-        during operand_equal_p hash verification.  */
-      else if (!IS_EXPR_CODE_CLASS (tclass))
-       gcc_assert (flags & OEP_HASH_CHECK);
-      else
-       {
-         unsigned int sflags = flags;
-
-         hstate.add_object (code);
-
-         switch (code)
-           {
-           case ADDR_EXPR:
-             gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
-             flags |= OEP_ADDRESS_OF;
-             sflags = flags;
-             break;
-
-           case INDIRECT_REF:
-           case MEM_REF:
-           case TARGET_MEM_REF:
-             flags &= ~OEP_ADDRESS_OF;
-             sflags = flags;
-             break;
-
-           case ARRAY_REF:
-           case ARRAY_RANGE_REF:
-           case COMPONENT_REF:
-           case BIT_FIELD_REF:
-             sflags &= ~OEP_ADDRESS_OF;
-             break;
-
-           case COND_EXPR:
-             flags &= ~OEP_ADDRESS_OF;
-             break;
-
-           case WIDEN_MULT_PLUS_EXPR:
-           case WIDEN_MULT_MINUS_EXPR:
-             {
-               /* The multiplication operands are commutative.  */
-               inchash::hash one, two;
-               inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
-               inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
-               hstate.add_commutative (one, two);
-               inchash::add_expr (TREE_OPERAND (t, 2), two, flags);
-               return;
-             }
-
-           case CALL_EXPR:
-             if (CALL_EXPR_FN (t) == NULL_TREE)
-               hstate.add_int (CALL_EXPR_IFN (t));
-             break;
-
-           case TARGET_EXPR:
-             /* For TARGET_EXPR, just hash on the TARGET_EXPR_SLOT.
-                Usually different TARGET_EXPRs just should use
-                different temporaries in their slots.  */
-             inchash::add_expr (TARGET_EXPR_SLOT (t), hstate, flags);
-             return;
-
-           default:
-             break;
-           }
-
-         /* Don't hash the type, that can lead to having nodes which
-            compare equal according to operand_equal_p, but which
-            have different hash codes.  */
-         if (code == NON_LVALUE_EXPR)
-           {
-             /* Make sure to include signness in the hash computation.  */
-             hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
-             inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
-           }
-
-         else if (commutative_tree_code (code))
-           {
-             /* It's a commutative expression.  We want to hash it the same
-                however it appears.  We do this by first hashing both operands
-                and then rehashing based on the order of their independent
-                hashes.  */
-             inchash::hash one, two;
-             inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
-             inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
-             hstate.add_commutative (one, two);
-           }
-         else
-           for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
-             inchash::add_expr (TREE_OPERAND (t, i), hstate,
-                                i == 0 ? flags : sflags);
-       }
-      return;
+      return true;
+    default:
+      /* These operators cannot overflow.  */
+      return true;
     }
 }
 
-}
-
 /* Constructors for pointer, array and function types.
    (RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
    constructed by language-dependent code, not here.)  */
@@ -7845,8 +8002,6 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
   else
     fixup_signed_type (itype);
 
-  ret = itype;
-
   inchash::hash hstate;
   inchash::add_expr (TYPE_MAX_VALUE (itype), hstate);
   ret = type_hash_canon (hstate.end (), itype);
@@ -8175,6 +8330,8 @@ build_function_type (tree value_type, tree arg_types)
   bool any_structural_p, any_noncanonical_p;
   tree canon_argtypes;
 
+  gcc_assert (arg_types != error_mark_node);
+
   if (TREE_CODE (value_type) == FUNCTION_TYPE)
     {
       error ("function return type cannot be function");
@@ -8918,17 +9075,25 @@ get_type_static_bounds (const_tree type, mpz_t min, mpz_t max)
     }
 }
 
+/* Return true if VAR is an automatic variable.  */
+
+bool
+auto_var_p (const_tree var)
+{
+  return ((((VAR_P (var) && ! DECL_EXTERNAL (var))
+           || TREE_CODE (var) == PARM_DECL)
+          && ! TREE_STATIC (var))
+         || TREE_CODE (var) == RESULT_DECL);
+}
+
 /* 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
-         && ((((VAR_P (var) && ! DECL_EXTERNAL (var))
-               || TREE_CODE (var) == PARM_DECL)
-              && ! TREE_STATIC (var))
-             || TREE_CODE (var) == LABEL_DECL
-             || TREE_CODE (var) == RESULT_DECL));
+         && (auto_var_p (var)
+             || TREE_CODE (var) == LABEL_DECL));
 }
 
 /* Subprogram of following function.  Called by walk_tree.
@@ -9224,6 +9389,28 @@ get_call_combined_fn (const_tree call)
   return CFN_LAST;
 }
 
+/* Comparator of indices based on tree_node_counts.  */
+
+static int
+tree_nodes_cmp (const void *p1, const void *p2)
+{
+  const unsigned *n1 = (const unsigned *)p1;
+  const unsigned *n2 = (const unsigned *)p2;
+
+  return tree_node_counts[*n1] - tree_node_counts[*n2];
+}
+
+/* Comparator of indices based on tree_code_counts.  */
+
+static int
+tree_codes_cmp (const void *p1, const void *p2)
+{
+  const unsigned *n1 = (const unsigned *)p1;
+  const unsigned *n2 = (const unsigned *)p2;
+
+  return tree_code_counts[*n1] - tree_code_counts[*n2];
+}
+
 #define TREE_MEM_USAGE_SPACES 40
 
 /* Print debugging information about tree nodes generated during the compile,
@@ -9234,34 +9421,55 @@ dump_tree_statistics (void)
 {
   if (GATHER_STATISTICS)
     {
-      int i;
       uint64_t total_nodes, total_bytes;
       fprintf (stderr, "\nKind                   Nodes      Bytes\n");
       mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
       total_nodes = total_bytes = 0;
-      for (i = 0; i < (int) all_kinds; i++)
-       {
-         fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n",
-                  tree_node_kind_names[i], tree_node_counts[i],
-                  tree_node_sizes[i]);
-         total_nodes += tree_node_counts[i];
-         total_bytes += tree_node_sizes[i];
-       }
-      mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
-      fprintf (stderr, "%-20s %7" PRIu64 " %10" PRIu64 "\n", "Total",
-              total_nodes, total_bytes);
-      mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
-      fprintf (stderr, "Code                   Nodes\n");
-      mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
-      for (i = 0; i < (int) MAX_TREE_CODES; i++)
-       fprintf (stderr, "%-32s %7" PRIu64 "\n",
-                get_tree_code_name ((enum tree_code) i), tree_code_counts[i]);
-      mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
-      fprintf (stderr, "\n");
-      ssanames_print_statistics ();
-      fprintf (stderr, "\n");
-      phinodes_print_statistics ();
-      fprintf (stderr, "\n");
+
+      {
+       auto_vec<unsigned> indices (all_kinds);
+       for (unsigned i = 0; i < all_kinds; i++)
+         indices.quick_push (i);
+       indices.qsort (tree_nodes_cmp);
+
+       for (unsigned i = 0; i < (int) all_kinds; i++)
+         {
+           unsigned j = indices[i];
+           fprintf (stderr, "%-20s %6" PRIu64 "%c %9" PRIu64 "%c\n",
+                    tree_node_kind_names[j], SIZE_AMOUNT (tree_node_counts[j]),
+                    SIZE_AMOUNT (tree_node_sizes[j]));
+           total_nodes += tree_node_counts[j];
+           total_bytes += tree_node_sizes[j];
+         }
+       mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
+       fprintf (stderr, "%-20s %6" PRIu64 "%c %9" PRIu64 "%c\n", "Total",
+                SIZE_AMOUNT (total_nodes), SIZE_AMOUNT (total_bytes));
+       mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
+      }
+
+      {
+       fprintf (stderr, "Code                              Nodes\n");
+       mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
+
+       auto_vec<unsigned> indices (MAX_TREE_CODES);
+       for (unsigned i = 0; i < MAX_TREE_CODES; i++)
+         indices.quick_push (i);
+       indices.qsort (tree_codes_cmp);
+
+       for (unsigned i = 0; i < MAX_TREE_CODES; i++)
+         {
+           unsigned j = indices[i];
+           fprintf (stderr, "%-32s %6" PRIu64 "%c\n",
+                    get_tree_code_name ((enum tree_code) j),
+                    SIZE_AMOUNT (tree_code_counts[j]));
+         }
+       mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
+       fprintf (stderr, "\n");
+       ssanames_print_statistics ();
+       fprintf (stderr, "\n");
+       phinodes_print_statistics ();
+       fprintf (stderr, "\n");
+      }
     }
   else
     fprintf (stderr, "(No per-node statistics)\n");
@@ -9333,40 +9541,32 @@ clean_symbol_name (char *p)
       *p = '_';
 }
 
-/* For anonymous aggregate types, we need some sort of name to
-   hold on to.  In practice, this should not appear, but it should
-   not be harmful if it does.  */
-bool 
-anon_aggrname_p(const_tree id_node)
-{
-#ifndef NO_DOT_IN_LABEL
- return (IDENTIFIER_POINTER (id_node)[0] == '.'
-        && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
-  return (IDENTIFIER_POINTER (id_node)[0] == '$' \
-         && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOLLAR_IN_LABEL */
-#define ANON_AGGRNAME_PREFIX "__anon_"
-  return (!strncmp (IDENTIFIER_POINTER (id_node), ANON_AGGRNAME_PREFIX, 
-                   sizeof (ANON_AGGRNAME_PREFIX) - 1));
-#endif /* NO_DOLLAR_IN_LABEL */
-#endif /* NO_DOT_IN_LABEL */
-}
-
-/* Return a format for an anonymous aggregate name.  */
-const char *
-anon_aggrname_format()
+static GTY(()) unsigned anon_cnt = 0; /* Saved for PCH.  */
+
+/* Create a unique anonymous identifier.  The identifier is still a
+   valid assembly label.  */
+
+tree
+make_anon_name ()
 {
-#ifndef NO_DOT_IN_LABEL
- return "._%d";
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
-  return "$_%d";
-#else /* NO_DOLLAR_IN_LABEL */
-  return "__anon_%d";
-#endif /* NO_DOLLAR_IN_LABEL */
-#endif /* NO_DOT_IN_LABEL */
+  const char *fmt = 
+#if !defined (NO_DOT_IN_LABEL)
+    "."
+#elif !defined (NO_DOLLAR_IN_LABEL)
+    "$"
+#else
+    "_"
+#endif
+    "_anon_%d";
+
+  char buf[24];
+  int len = snprintf (buf, sizeof (buf), fmt, anon_cnt++);
+  gcc_checking_assert (len < int (sizeof (buf)));
+
+  tree id = get_identifier_with_length (buf, len);
+  IDENTIFIER_ANON_P (id) = true;
+
+  return id;
 }
 
 /* Generate a name for a special-purpose function.
@@ -9597,8 +9797,10 @@ void
 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",
-                 omp_clause_code_name[code], get_tree_code_name (TREE_CODE (node)),
+  internal_error ("tree check: expected %<omp_clause %s%>, have %qs "
+                 "in %s, at %s:%d",
+                 omp_clause_code_name[code],
+                 get_tree_code_name (TREE_CODE (node)),
                  function, trim_filename (file), line);
 }
 
@@ -9671,7 +9873,8 @@ tree_int_cst_elt_check_failed (int idx, int len, const char *file, int line,
                               const char *function)
 {
   internal_error
-    ("tree check: accessed elt %d of tree_int_cst with %d elts in %s, at %s:%d",
+    ("tree check: accessed elt %d of %<tree_int_cst%> with %d elts in %s, "
+     "at %s:%d",
      idx + 1, len, function, trim_filename (file), line);
 }
 
@@ -9683,7 +9886,7 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
                           const char *function)
 {
   internal_error
-    ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
+    ("tree check: accessed elt %d of %<tree_vec%> with %d elts in %s, at %s:%d",
      idx + 1, len, function, trim_filename (file), line);
 }
 
@@ -9709,7 +9912,7 @@ omp_clause_operand_check_failed (int idx, const_tree t, const char *file,
                                 int line, const char *function)
 {
   internal_error
-    ("tree check: accessed operand %d of omp_clause %s with %d operands "
+    ("tree check: accessed operand %d of %<omp_clause %s%> with %d operands "
      "in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)],
      omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function,
      trim_filename (file), line);
@@ -9970,10 +10173,12 @@ build_common_tree_nodes (bool signed_char)
       for (i = 0; i < NUM_INT_N_ENTS; i++)
        if (int_n_enabled_p[i])
          {
-           char name[50];
+           char name[50], altname[50];
            sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+           sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
 
-           if (strcmp (name, SIZE_TYPE) == 0)
+           if (strcmp (name, SIZE_TYPE) == 0
+               || strcmp (altname, SIZE_TYPE) == 0)
              {
                size_type_node = int_n_trees[i].unsigned_type;
              }
@@ -9997,9 +10202,12 @@ build_common_tree_nodes (bool signed_char)
       for (int i = 0; i < NUM_INT_N_ENTS; i++)
        if (int_n_enabled_p[i])
          {
-           char name[50];
+           char name[50], altname[50];
            sprintf (name, "__int%d", int_n_data[i].bitsize);
-           if (strcmp (name, PTRDIFF_TYPE) == 0)
+           sprintf (altname, "__int%d__", int_n_data[i].bitsize);
+
+           if (strcmp (name, PTRDIFF_TYPE) == 0
+               || strcmp (altname, PTRDIFF_TYPE) == 0)
              ptrdiff_type_node = int_n_trees[i].signed_type;
          }
       if (ptrdiff_type_node == NULL_TREE)
@@ -10126,23 +10334,23 @@ build_common_tree_nodes (bool signed_char)
   uint64_type_node = make_or_reuse_type (64, 1);
 
   /* Decimal float types. */
-  dfloat32_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
-  SET_TYPE_MODE (dfloat32_type_node, SDmode);
-  layout_type (dfloat32_type_node);
-  dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
-
-  dfloat64_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
-  SET_TYPE_MODE (dfloat64_type_node, DDmode);
-  layout_type (dfloat64_type_node);
-  dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
-
-  dfloat128_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
-  SET_TYPE_MODE (dfloat128_type_node, TDmode);
-  layout_type (dfloat128_type_node);
-  dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
+  if (targetm.decimal_float_supported_p ())
+    {
+      dfloat32_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
+      SET_TYPE_MODE (dfloat32_type_node, SDmode);
+      layout_type (dfloat32_type_node);
+
+      dfloat64_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
+      SET_TYPE_MODE (dfloat64_type_node, DDmode);
+      layout_type (dfloat64_type_node);
+
+      dfloat128_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
+      SET_TYPE_MODE (dfloat128_type_node, TDmode);
+      layout_type (dfloat128_type_node);
+    }
 
   complex_integer_type_node = build_complex_type (integer_type_node, true);
   complex_float_type_node = build_complex_type (float_type_node, true);
@@ -10223,6 +10431,12 @@ build_common_tree_nodes (bool signed_char)
 
     va_list_type_node = t;
   }
+
+  /* SCEV analyzer global shared trees.  */
+  chrec_dont_know = make_node (SCEV_NOT_KNOWN);
+  TREE_TYPE (chrec_dont_know) = void_type_node;
+  chrec_known = make_node (SCEV_KNOWN);
+  TREE_TYPE (chrec_known) = void_type_node;
 }
 
 /* Modify DECL for given flags.
@@ -10662,44 +10876,44 @@ build_vector_type (tree innertype, poly_int64 nunits)
   return make_vector_type (innertype, nunits, VOIDmode);
 }
 
-/* Build truth vector with specified length and number of units.  */
+/* Build a truth vector with NUNITS units, giving it mode MASK_MODE.  */
 
 tree
-build_truth_vector_type (poly_uint64 nunits, poly_uint64 vector_size)
+build_truth_vector_type_for_mode (poly_uint64 nunits, machine_mode mask_mode)
 {
-  machine_mode mask_mode
-    = targetm.vectorize.get_mask_mode (nunits, vector_size).else_blk ();
-
-  poly_uint64 vsize;
-  if (mask_mode == BLKmode)
-    vsize = vector_size * BITS_PER_UNIT;
-  else
-    vsize = GET_MODE_BITSIZE (mask_mode);
+  gcc_assert (mask_mode != BLKmode);
 
+  poly_uint64 vsize = GET_MODE_BITSIZE (mask_mode);
   unsigned HOST_WIDE_INT esize = vector_element_size (vsize, nunits);
-
   tree bool_type = build_nonstandard_boolean_type (esize);
 
   return make_vector_type (bool_type, nunits, mask_mode);
 }
 
-/* Returns a vector type corresponding to a comparison of VECTYPE.  */
+/* Build a vector type that holds one boolean result for each element of
+   vector type VECTYPE.  The public interface for this operation is
+   truth_type_for.  */
 
-tree
-build_same_sized_truth_vector_type (tree vectype)
+static tree
+build_truth_vector_type_for (tree vectype)
 {
-  if (VECTOR_BOOLEAN_TYPE_P (vectype))
-    return vectype;
+  machine_mode vector_mode = TYPE_MODE (vectype);
+  poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
 
-  poly_uint64 size = GET_MODE_SIZE (TYPE_MODE (vectype));
+  machine_mode mask_mode;
+  if (VECTOR_MODE_P (vector_mode)
+      && targetm.vectorize.get_mask_mode (vector_mode).exists (&mask_mode))
+    return build_truth_vector_type_for_mode (nunits, mask_mode);
 
-  if (known_eq (size, 0U))
-    size = tree_to_uhwi (TYPE_SIZE_UNIT (vectype));
+  poly_uint64 vsize = tree_to_poly_uint64 (TYPE_SIZE (vectype));
+  unsigned HOST_WIDE_INT esize = vector_element_size (vsize, nunits);
+  tree bool_type = build_nonstandard_boolean_type (esize);
 
-  return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (vectype), size);
+  return make_vector_type (bool_type, nunits, BLKmode);
 }
 
-/* Similarly, but builds a variant type with TYPE_VECTOR_OPAQUE set.  */
+/* Like build_vector_type, but builds a variant type with TYPE_VECTOR_OPAQUE
+   set.  */
 
 tree
 build_opaque_vector_type (tree innertype, poly_int64 nunits)
@@ -10906,6 +11120,45 @@ initializer_zerop (const_tree init, bool *nonzero /* = NULL */)
     }
 }
 
+/* Return true if EXPR is an initializer expression in which every element
+   is a constant that is numerically equal to 0 or 1.  The elements do not
+   need to be equal to each other.  */
+
+bool
+initializer_each_zero_or_onep (const_tree expr)
+{
+  STRIP_ANY_LOCATION_WRAPPER (expr);
+
+  switch (TREE_CODE (expr))
+    {
+    case INTEGER_CST:
+      return integer_zerop (expr) || integer_onep (expr);
+
+    case REAL_CST:
+      return real_zerop (expr) || real_onep (expr);
+
+    case VECTOR_CST:
+      {
+       unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (expr);
+       if (VECTOR_CST_STEPPED_P (expr)
+           && !TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr)).is_constant (&nelts))
+         return false;
+
+       for (unsigned int i = 0; i < nelts; ++i)
+         {
+           tree elt = vector_cst_elt (expr, i);
+           if (!initializer_each_zero_or_onep (elt))
+             return false;
+         }
+
+       return true;
+      }
+
+    default:
+      return false;
+    }
+}
+
 /* Check if vector VEC consists of all the equal elements and
    that the number of elements corresponds to the type of VEC.
    The function returns first element of the vector
@@ -10955,6 +11208,61 @@ uniform_vector_p (const_tree vec)
   return NULL_TREE;
 }
 
+/* If the argument is INTEGER_CST, return it.  If the argument is vector
+   with all elements the same INTEGER_CST, return that INTEGER_CST.  Otherwise
+   return NULL_TREE.
+   Look through location wrappers. */
+
+tree
+uniform_integer_cst_p (tree t)
+{
+  STRIP_ANY_LOCATION_WRAPPER (t);
+
+  if (TREE_CODE (t) == INTEGER_CST)
+    return t;
+
+  if (VECTOR_TYPE_P (TREE_TYPE (t)))
+    {
+      t = uniform_vector_p (t);
+      if (t && TREE_CODE (t) == INTEGER_CST)
+       return t;
+    }
+
+  return NULL_TREE;
+}
+
+/* If VECTOR_CST T has a single nonzero element, return the index of that
+   element, otherwise return -1.  */
+
+int
+single_nonzero_element (const_tree t)
+{
+  unsigned HOST_WIDE_INT nelts;
+  unsigned int repeat_nelts;
+  if (VECTOR_CST_NELTS (t).is_constant (&nelts))
+    repeat_nelts = nelts;
+  else if (VECTOR_CST_NELTS_PER_PATTERN (t) == 2)
+    {
+      nelts = vector_cst_encoded_nelts (t);
+      repeat_nelts = VECTOR_CST_NPATTERNS (t);
+    }
+  else
+    return -1;
+
+  int res = -1;
+  for (unsigned int i = 0; i < nelts; ++i)
+    {
+      tree elt = vector_cst_elt (t, i);
+      if (!integer_zerop (elt) && !real_zerop (elt))
+       {
+         if (res >= 0 || i >= repeat_nelts)
+           return -1;
+         res = i;
+       }
+    }
+  return res;
+}
+
 /* Build an empty statement at location LOC.  */
 
 tree
@@ -11260,25 +11568,33 @@ build_alloca_call_expr (tree size, unsigned int align, HOST_WIDE_INT max_size)
     }
 }
 
-/* Create a new constant string literal and return a char* pointer to it.
-   The STRING_CST value is the LEN characters at STR.  */
+/* Create a new constant string literal of type ELTYPE[SIZE] (or LEN
+   if SIZE == -1) and return a tree node representing char* pointer to
+   it as an ADDR_EXPR (ARRAY_REF (ELTYPE, ...)).  The STRING_CST value
+   is the LEN bytes at STR (the representation of the string, which may
+   be wide).  */
+
 tree
-build_string_literal (int len, const char *str)
+build_string_literal (int len, const char *str,
+                     tree eltype /* = char_type_node */,
+                     unsigned HOST_WIDE_INT size /* = -1 */)
 {
-  tree t, elem, index, type;
+  tree t = build_string (len, str);
+  /* Set the maximum valid index based on the string length or SIZE.  */
+  unsigned HOST_WIDE_INT maxidx
+    = (size == HOST_WIDE_INT_M1U ? len : size) - 1;
 
-  t = build_string (len, str);
-  elem = build_type_variant (char_type_node, 1, 0);
-  index = build_index_type (size_int (len - 1));
-  type = build_array_type (elem, index);
+  tree index = build_index_type (size_int (maxidx));
+  eltype = build_type_variant (eltype, 1, 0);
+  tree type = build_array_type (eltype, index);
   TREE_TYPE (t) = type;
   TREE_CONSTANT (t) = 1;
   TREE_READONLY (t) = 1;
   TREE_STATIC (t) = 1;
 
-  type = build_pointer_type (elem);
+  type = build_pointer_type (eltype);
   t = build1 (ADDR_EXPR, type,
-             build4 (ARRAY_REF, elem,
+             build4 (ARRAY_REF, eltype,
                      t, integer_zero_node, NULL_TREE, NULL_TREE));
   return t;
 }
@@ -11323,7 +11639,10 @@ int_cst_value (const_tree x)
 
 /* If TYPE is an integral or pointer type, return an integer type with
    the same precision which is unsigned iff UNSIGNEDP is true, or itself
-   if TYPE is already an integer type of signedness UNSIGNEDP.  */
+   if TYPE is already an integer type of signedness UNSIGNEDP.
+   If TYPE is a floating-point type, return an integer type with the same
+   bitsize and with the signedness given by UNSIGNEDP; this is useful
+   when doing bit-level operations on a floating-point value.  */
 
 tree
 signed_or_unsigned_type_for (int unsignedp, tree type)
@@ -11353,17 +11672,23 @@ signed_or_unsigned_type_for (int unsignedp, tree type)
       return build_complex_type (inner2);
     }
 
-  if (!INTEGRAL_TYPE_P (type)
-      && !POINTER_TYPE_P (type)
-      && TREE_CODE (type) != OFFSET_TYPE)
+  unsigned int bits;
+  if (INTEGRAL_TYPE_P (type)
+      || POINTER_TYPE_P (type)
+      || TREE_CODE (type) == OFFSET_TYPE)
+    bits = TYPE_PRECISION (type);
+  else if (TREE_CODE (type) == REAL_TYPE)
+    bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (type));
+  else
     return NULL_TREE;
 
-  return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+  return build_nonstandard_integer_type (bits, unsignedp);
 }
 
 /* If TYPE is an integral or pointer type, return an integer type with
    the same precision which is unsigned, or itself if TYPE is already an
-   unsigned integer type.  */
+   unsigned integer type.  If TYPE is a floating-point type, return an
+   unsigned integer type with the same bitsize as TYPE.  */
 
 tree
 unsigned_type_for (tree type)
@@ -11373,7 +11698,8 @@ unsigned_type_for (tree type)
 
 /* If TYPE is an integral or pointer type, return an integer type with
    the same precision which is signed, or itself if TYPE is already a
-   signed integer type.  */
+   signed integer type.  If TYPE is a floating-point type, return a
+   signed integer type with the same bitsize as TYPE.  */
 
 tree
 signed_type_for (tree type)
@@ -11391,8 +11717,7 @@ truth_type_for (tree type)
     {
       if (VECTOR_BOOLEAN_TYPE_P (type))
        return type;
-      return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (type),
-                                     GET_MODE_SIZE (TYPE_MODE (type)));
+      return build_truth_vector_type_for (type);
     }
   else
     return boolean_type_node;
@@ -11764,6 +12089,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_SCHEDULE:
        case OMP_CLAUSE_UNIFORM:
        case OMP_CLAUSE_DEPEND:
+       case OMP_CLAUSE_NONTEMPORAL:
        case OMP_CLAUSE_NUM_TEAMS:
        case OMP_CLAUSE_THREAD_LIMIT:
        case OMP_CLAUSE_DEVICE:
@@ -11778,8 +12104,14 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_TO_DECLARE:
        case OMP_CLAUSE_LINK:
        case OMP_CLAUSE_USE_DEVICE_PTR:
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
        case OMP_CLAUSE_IS_DEVICE_PTR:
+       case OMP_CLAUSE_INCLUSIVE:
+       case OMP_CLAUSE_EXCLUSIVE:
        case OMP_CLAUSE__LOOPTEMP_:
+       case OMP_CLAUSE__REDUCTEMP_:
+       case OMP_CLAUSE__CONDTEMP_:
+       case OMP_CLAUSE__SCANTEMP_:
        case OMP_CLAUSE__SIMDUID_:
          WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
          /* FALLTHRU */
@@ -11790,6 +12122,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_MERGEABLE:
        case OMP_CLAUSE_PROC_BIND:
+       case OMP_CLAUSE_DEVICE_TYPE:
        case OMP_CLAUSE_INBRANCH:
        case OMP_CLAUSE_NOTINBRANCH:
        case OMP_CLAUSE_FOR:
@@ -11800,6 +12133,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
        case OMP_CLAUSE_THREADS:
        case OMP_CLAUSE_SIMD:
        case OMP_CLAUSE_DEFAULTMAP:
+       case OMP_CLAUSE_ORDER:
+       case OMP_CLAUSE_BIND:
        case OMP_CLAUSE_AUTO:
        case OMP_CLAUSE_SEQ:
        case OMP_CLAUSE_TILE:
@@ -11837,6 +12172,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
          WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
 
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          {
            int i;
            for (i = 0; i < 5; i++)
@@ -12324,13 +12661,10 @@ tree_nop_conversion (const_tree exp)
   if (!CONVERT_EXPR_P (exp)
       && TREE_CODE (exp) != NON_LVALUE_EXPR)
     return false;
-  if (TREE_OPERAND (exp, 0) == error_mark_node)
-    return false;
 
   outer_type = TREE_TYPE (exp);
   inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-
-  if (!inner_type)
+  if (!inner_type || inner_type == error_mark_node)
     return false;
 
   return tree_nop_conversion_p (outer_type, inner_type);
@@ -12491,25 +12825,6 @@ virtual_method_call_p (const_tree target)
   return true;
 }
 
-/* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
-
-tree
-obj_type_ref_class (const_tree ref)
-{
-  gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
-  ref = TREE_TYPE (ref);
-  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
-  ref = TREE_TYPE (ref);
-  /* We look for type THIS points to.  ObjC also builds
-     OBJ_TYPE_REF with non-method calls, Their first parameter
-     ID however also corresponds to class type. */
-  gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
-                      || TREE_CODE (ref) == FUNCTION_TYPE);
-  ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
-  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
-  return TREE_TYPE (ref);
-}
-
 /* Lookup sub-BINFO of BINFO of TYPE at offset POS.  */
 
 static tree
@@ -12606,22 +12921,6 @@ typedef_variant_p (const_tree type)
   return is_typedef_decl (TYPE_NAME (type));
 }
 
-/* A class to handle converting a string that might contain
-   control characters, (eg newline, form-feed, etc), into one
-   in which contains escape sequences instead.  */
-
-class escaped_string
-{
- public:
-  escaped_string () { m_owned = false; m_str = NULL; };
-  ~escaped_string () { if (m_owned) free (m_str); }
-  operator const char *() const { return (const char *) m_str; }
-  void escape (const char *);
- private:
-  char *m_str;
-  bool  m_owned;
-};
-
 /* PR 84195: Replace control characters in "unescaped" with their
    escaped equivalents.  Allow newlines if -fmessage-length has
    been set to a non-zero value.  This is done here, rather than
@@ -12896,6 +13195,9 @@ block_may_fallthru (const_tree block)
       return (block_may_fallthru (TREE_OPERAND (stmt, 0))
              && block_may_fallthru (TREE_OPERAND (stmt, 1)));
 
+    case EH_ELSE_EXPR:
+      return block_may_fallthru (TREE_OPERAND (stmt, 0));
+
     case MODIFY_EXPR:
       if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
        stmt = TREE_OPERAND (stmt, 1);
@@ -12946,7 +13248,11 @@ get_tree_code_name (enum tree_code code)
   const char *invalid = "<invalid tree code>";
 
   if (code >= MAX_TREE_CODES)
-    return invalid;
+    {
+      if (code == 0xa5a5)
+       return "ggc_freed";
+      return invalid;
+    }
 
   return tree_code_name[code];
 }
@@ -13091,8 +13397,8 @@ array_ref_up_bound (tree exp)
   return NULL_TREE;
 }
 
-/* Returns true if REF is an array reference or a component reference
-   to an array at the end of a structure.
+/* Returns true if REF is an array reference, component reference,
+   or memory reference to an array at the end of a structure.
    If this is the case, the array may be allocated larger
    than its upper bound implies.  */
 
@@ -13110,6 +13416,28 @@ array_at_struct_end_p (tree ref)
   else if (TREE_CODE (ref) == COMPONENT_REF
           && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
     atype = TREE_TYPE (TREE_OPERAND (ref, 1));
+  else if (TREE_CODE (ref) == MEM_REF)
+    {
+      tree arg = TREE_OPERAND (ref, 0);
+      if (TREE_CODE (arg) == ADDR_EXPR)
+       arg = TREE_OPERAND (arg, 0);
+      tree argtype = TREE_TYPE (arg);
+      if (TREE_CODE (argtype) == RECORD_TYPE)
+       {
+         if (tree fld = last_field (argtype))
+           {
+             atype = TREE_TYPE (fld);
+             if (TREE_CODE (atype) != ARRAY_TYPE)
+               return false;
+             if (VAR_P (arg) && DECL_SIZE (fld))
+               return false;
+           }
+         else
+           return false;
+       }
+      else
+       return false;
+    }
   else
     return false;
 
@@ -13226,6 +13554,202 @@ component_ref_field_offset (tree exp)
     return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
 }
 
+/* Given the initializer INIT, return the initializer for the field
+   DECL if it exists, otherwise null.  Used to obtain the initializer
+   for a flexible array member and determine its size.  */
+
+static tree
+get_initializer_for (tree init, tree decl)
+{
+  STRIP_NOPS (init);
+
+  tree fld, fld_init;
+  unsigned HOST_WIDE_INT i;
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), i, fld, fld_init)
+    {
+      if (decl == fld)
+       return fld_init;
+
+      if (TREE_CODE (fld) == CONSTRUCTOR)
+       {
+         fld_init = get_initializer_for (fld_init, decl);
+         if (fld_init)
+           return fld_init;
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Determines the size of the member referenced by the COMPONENT_REF
+   REF, using its initializer expression if necessary in order to
+   determine the size of an initialized flexible array member.
+   If non-null, *INTERIOR_ZERO_LENGTH is set when REF refers to
+   an interior zero-length array.
+   Returns the size (which might be zero for an object with
+   an uninitialized flexible array member) or null if the size
+   cannot be determined.  */
+
+tree
+component_ref_size (tree ref, bool *interior_zero_length /* = NULL */)
+{
+  gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
+
+  bool int_0_len = false;
+  if (!interior_zero_length)
+    interior_zero_length = &int_0_len;
+
+  tree member = TREE_OPERAND (ref, 1);
+
+  tree memsize = DECL_SIZE_UNIT (member);
+  if (memsize)
+    {
+      tree memtype = TREE_TYPE (member);
+      if (TREE_CODE (memtype) != ARRAY_TYPE)
+       return memsize;
+
+      bool trailing = array_at_struct_end_p (ref);
+      bool zero_length = integer_zerop (memsize);
+      if (!trailing && (!interior_zero_length || !zero_length))
+       /* MEMBER is either an interior array or is an array with
+          more than one element.  */
+       return memsize;
+
+      *interior_zero_length = zero_length && !trailing;
+      if (*interior_zero_length)
+       memsize = NULL_TREE;
+
+      if (!zero_length)
+       if (tree dom = TYPE_DOMAIN (memtype))
+         if (tree min = TYPE_MIN_VALUE (dom))
+           if (tree max = TYPE_MAX_VALUE (dom))
+             if (TREE_CODE (min) == INTEGER_CST
+                 && TREE_CODE (max) == INTEGER_CST)
+               {
+                 offset_int minidx = wi::to_offset (min);
+                 offset_int maxidx = wi::to_offset (max);
+                 if (maxidx - minidx > 0)
+                   /* MEMBER is an array with more than 1 element.  */
+                   return memsize;
+               }
+    }
+
+  /* MEMBER is either a bona fide flexible array member, or a zero-length
+     array member, or an array of length one treated as such.  */
+
+  /* If the reference is to a declared object and the member a true
+     flexible array, try to determine its size from its initializer.  */
+  poly_int64 baseoff = 0;
+  tree base = get_addr_base_and_unit_offset (ref, &baseoff);
+  if (!base || !VAR_P (base))
+    {
+      if (!*interior_zero_length)
+       return NULL_TREE;
+
+      if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF)
+       return NULL_TREE;
+
+      base = TREE_OPERAND (ref, 0);
+      while (TREE_CODE (base) == COMPONENT_REF)
+       base = TREE_OPERAND (base, 0);
+      baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1)));
+    }
+
+  /* BASE is the declared object of which MEMBER is either a member
+     or that is is cast to REFTYPE (e.g., a char buffer used to store
+     a REFTYPE object).  */
+  tree reftype = TREE_TYPE (TREE_OPERAND (ref, 0));
+  tree basetype = TREE_TYPE (base);
+
+  /* Determine the base type of the referenced object.  If it's
+     the same as REFTYPE and MEMBER has a known size, return it.  */
+  tree bt = basetype;
+  if (!*interior_zero_length)
+    while (TREE_CODE (bt) == ARRAY_TYPE)
+      bt = TREE_TYPE (bt);
+  bool typematch = useless_type_conversion_p (reftype, bt);
+  if (memsize && typematch)
+    return memsize;
+
+  memsize = NULL_TREE;
+
+  if (typematch)
+    /* MEMBER is a true flexible array member.  Compute its size from
+       the initializer of the BASE object if it has one.  */
+    if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE)
+      {
+       init = get_initializer_for (init, member);
+       if (init)
+         {
+           memsize = TYPE_SIZE_UNIT (TREE_TYPE (init));
+           if (tree refsize = TYPE_SIZE_UNIT (reftype))
+             {
+               /* Use the larger of the initializer size and the tail
+                  padding in the enclosing struct.  */
+               poly_int64 rsz = tree_to_poly_int64 (refsize);
+               rsz -= baseoff;
+               if (known_lt (tree_to_poly_int64 (memsize), rsz))
+                 memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz);
+             }
+
+           baseoff = 0;
+         }
+      }
+
+  if (!memsize)
+    {
+      if (typematch)
+       {
+         if (DECL_P (base)
+             && DECL_EXTERNAL (base)
+             && bt == basetype
+             && !*interior_zero_length)
+           /* The size of a flexible array member of an extern struct
+              with no initializer cannot be determined (it's defined
+              in another translation unit and can have an initializer
+              with an arbitrary number of elements).  */
+           return NULL_TREE;
+
+         /* Use the size of the base struct or, for interior zero-length
+            arrays, the size of the enclosing type.  */
+         memsize = TYPE_SIZE_UNIT (bt);
+       }
+      else if (DECL_P (base))
+       /* Use the size of the BASE object (possibly an array of some
+          other type such as char used to store the struct).  */
+       memsize = DECL_SIZE_UNIT (base);
+      else
+       return NULL_TREE;
+    }
+
+  /* If the flexible array member has a known size use the greater
+     of it and the tail padding in the enclosing struct.
+     Otherwise, when the size of the flexible array member is unknown
+     and the referenced object is not a struct, use the size of its
+     type when known.  This detects sizes of array buffers when cast
+     to struct types with flexible array members.  */
+  if (memsize)
+    {
+      poly_int64 memsz64 = memsize ? tree_to_poly_int64 (memsize) : 0;
+      if (known_lt (baseoff, memsz64))
+       {
+         memsz64 -= baseoff;
+         return wide_int_to_tree (TREE_TYPE (memsize), memsz64);
+       }
+      return integer_zero_node;
+    }
+
+  /* Return "don't know" for an external non-array object since its
+     flexible array member can be initialized to have any number of
+     elements.  Otherwise, return zero because the flexible array
+     member has no elements.  */
+  return (DECL_P (base)
+         && DECL_EXTERNAL (base)
+         && (!typematch
+             || TREE_CODE (basetype) != ARRAY_TYPE)
+         ? NULL_TREE : integer_zero_node);
+}
+
 /* Return the machine mode of T.  For vectors, returns the mode of the
    inner type.  The main use case is to feed the result to HONOR_NANS,
    avoiding the BLKmode that a direct TYPE_MODE (T) might return.  */
@@ -13352,11 +13876,11 @@ verify_type_variant (const_tree t, tree tv)
        {
          gcc_assert (!operand_equal_p (TYPE_SIZE_UNIT (t),
                                        TYPE_SIZE_UNIT (tv), 0));
-         error ("type variant has different TYPE_SIZE_UNIT");
+         error ("type variant has different %<TYPE_SIZE_UNIT%>");
          debug_tree (tv);
-         error ("type variant's TYPE_SIZE_UNIT");
+         error ("type variant%'s %<TYPE_SIZE_UNIT%>");
          debug_tree (TYPE_SIZE_UNIT (tv));
-         error ("type's TYPE_SIZE_UNIT");
+         error ("type%'s %<TYPE_SIZE_UNIT%>");
          debug_tree (TYPE_SIZE_UNIT (t));
          return false;
        }
@@ -13373,10 +13897,13 @@ verify_type_variant (const_tree t, tree tv)
      Ada also builds variants of types with different TYPE_CONTEXT.   */
   if ((!in_lto_p || !TYPE_FILE_SCOPE_P (t)) && 0)
     verify_variant_match (TYPE_CONTEXT);
-  verify_variant_match (TYPE_STRING_FLAG);
+  if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == INTEGER_TYPE)
+    verify_variant_match (TYPE_STRING_FLAG);
+  if (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE)
+    verify_variant_match (TYPE_CXX_ODR_P);
   if (TYPE_ALIAS_SET_KNOWN_P (t))
     {
-      error ("type variant with TYPE_ALIAS_SET_KNOWN_P");
+      error ("type variant with %<TYPE_ALIAS_SET_KNOWN_P%>");
       debug_tree (tv);
       return false;
     }
@@ -13389,7 +13916,7 @@ verify_type_variant (const_tree t, tree tv)
       && (in_lto_p || !TYPE_VFIELD (tv)
          || TREE_CODE (TYPE_VFIELD (tv)) != TREE_LIST))
     {
-      error ("type variant has different TYPE_VFIELD");
+      error ("type variant has different %<TYPE_VFIELD%>");
       debug_tree (tv);
       return false;
     }
@@ -13425,17 +13952,18 @@ verify_type_variant (const_tree t, tree tv)
         at LTO time only.  */
       && (in_lto_p && odr_type_p (t)))
     {
-      error ("type variant has different TYPE_BINFO");
+      error ("type variant has different %<TYPE_BINFO%>");
       debug_tree (tv);
-      error ("type variant's TYPE_BINFO");
+      error ("type variant%'s %<TYPE_BINFO%>");
       debug_tree (TYPE_BINFO (tv));
-      error ("type's TYPE_BINFO");
+      error ("type%'s %<TYPE_BINFO%>");
       debug_tree (TYPE_BINFO (t));
       return false;
     }
 
   /* Check various uses of TYPE_VALUES_RAW.  */
-  if (TREE_CODE (t) == ENUMERAL_TYPE)
+  if (TREE_CODE (t) == ENUMERAL_TYPE
+      && TYPE_VALUES (t))
     verify_variant_match (TYPE_VALUES);
   else if (TREE_CODE (t) == ARRAY_TYPE)
     verify_variant_match (TYPE_DOMAIN);
@@ -13467,7 +13995,7 @@ verify_type_variant (const_tree t, tree tv)
          break;
       if (f1 || f2)
        {
-         error ("type variant has different TYPE_FIELDS");
+         error ("type variant has different %<TYPE_FIELDS%>");
          debug_tree (tv);
          error ("first mismatch is field");
          debug_tree (f1);
@@ -13488,11 +14016,11 @@ verify_type_variant (const_tree t, tree tv)
          || TYPE_MAIN_VARIANT (TREE_TYPE (t))
             != TYPE_MAIN_VARIANT (TREE_TYPE (tv))))
     {
-      error ("type variant has different TREE_TYPE");
+      error ("type variant has different %<TREE_TYPE%>");
       debug_tree (tv);
-      error ("type variant's TREE_TYPE");
+      error ("type variant%'s %<TREE_TYPE%>");
       debug_tree (TREE_TYPE (tv));
-      error ("type's TREE_TYPE");
+      error ("type%'s %<TREE_TYPE%>");
       debug_tree (TREE_TYPE (t));
       return false;
     }
@@ -13501,9 +14029,9 @@ verify_type_variant (const_tree t, tree tv)
     {
       error ("type is not compatible with its variant");
       debug_tree (tv);
-      error ("type variant's TREE_TYPE");
+      error ("type variant%'s %<TREE_TYPE%>");
       debug_tree (TREE_TYPE (tv));
-      error ("type's TREE_TYPE");
+      error ("type%'s %<TREE_TYPE%>");
       debug_tree (TREE_TYPE (t));
       return false;
     }
@@ -13583,6 +14111,7 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
 
   gcc_assert (!trust_type_canonical
              || (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
+
   /* If the types have been previously registered and found equal
      they still are.  */
 
@@ -13600,6 +14129,14 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
       return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
     }
 
+  /* For types where we do ODR based TBAA the canonical type is always
+     set correctly, so we know that types are different if their
+     canonical types does not match.  */
+  if (trust_type_canonical
+      && (odr_type_p (t1) && odr_based_tbaa_p (t1))
+         != (odr_type_p (t2) && odr_based_tbaa_p (t2)))
+    return false;
+
   /* Can't be the same type if the types don't have the same code.  */
   enum tree_code code = tree_code_for_canonical_type_merging (TREE_CODE (t1));
   if (code != tree_code_for_canonical_type_merging (TREE_CODE (t2)))
@@ -13802,12 +14339,12 @@ verify_type (const_tree t)
   tree mv = TYPE_MAIN_VARIANT (t);
   if (!mv)
     {
-      error ("Main variant is not defined");
+      error ("main variant is not defined");
       error_found = true;
     }
   else if (mv != TYPE_MAIN_VARIANT (mv))
     {
-      error ("TYPE_MAIN_VARIANT has different TYPE_MAIN_VARIANT");
+      error ("%<TYPE_MAIN_VARIANT%> has different %<TYPE_MAIN_VARIANT%>");
       debug_tree (mv);
       error_found = true;
     }
@@ -13819,11 +14356,11 @@ verify_type (const_tree t)
     ;
   else if (TYPE_CANONICAL (t) != ct)
     {
-      error ("TYPE_CANONICAL has different TYPE_CANONICAL");
+      error ("%<TYPE_CANONICAL%> has different %<TYPE_CANONICAL%>");
       debug_tree (ct);
       error_found = true;
     }
-  /* Method and function types can not be used to address memory and thus
+  /* Method and function types cannot be used to address memory and thus
      TYPE_CANONICAL really matters only for determining useless conversions.
 
      FIXME: C++ FE produce declarations of builtin functions that are not
@@ -13831,13 +14368,14 @@ verify_type (const_tree t)
   else if (TREE_CODE (t) == FUNCTION_TYPE)
     ;
   else if (t != ct
-          /* FIXME: gimple_canonical_types_compatible_p can not compare types
+          /* FIXME: gimple_canonical_types_compatible_p cannot compare types
              with variably sized arrays because their sizes possibly
              gimplified to different variables.  */
           && !variably_modified_type_p (ct, NULL)
-          && !gimple_canonical_types_compatible_p (t, ct, false))
+          && !gimple_canonical_types_compatible_p (t, ct, false)
+          && COMPLETE_TYPE_P (t))
     {
-      error ("TYPE_CANONICAL is not compatible");
+      error ("%<TYPE_CANONICAL%> is not compatible");
       debug_tree (ct);
       error_found = true;
     }
@@ -13845,13 +14383,13 @@ verify_type (const_tree t)
   if (COMPLETE_TYPE_P (t) && TYPE_CANONICAL (t)
       && TYPE_MODE (t) != TYPE_MODE (TYPE_CANONICAL (t)))
     {
-      error ("TYPE_MODE of TYPE_CANONICAL is not compatible");
+      error ("%<TYPE_MODE%> of %<TYPE_CANONICAL%> is not compatible");
       debug_tree (ct);
       error_found = true;
     }
   if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
    {
-      error ("TYPE_CANONICAL of main variant is not main variant");
+      error ("%<TYPE_CANONICAL%> of main variant is not main variant");
       debug_tree (ct);
       debug_tree (TYPE_MAIN_VARIANT (ct));
       error_found = true;
@@ -13867,7 +14405,7 @@ verify_type (const_tree t)
          && TREE_CODE (TYPE_VFIELD (t)) != FIELD_DECL
          && TREE_CODE (TYPE_VFIELD (t)) != TREE_LIST)
        {
-         error ("TYPE_VFIELD is not FIELD_DECL nor TREE_LIST");
+         error ("%<TYPE_VFIELD%> is not %<FIELD_DECL%> nor %<TREE_LIST%>");
          debug_tree (TYPE_VFIELD (t));
          error_found = true;
        }
@@ -13877,7 +14415,7 @@ verify_type (const_tree t)
       if (TYPE_NEXT_PTR_TO (t)
          && TREE_CODE (TYPE_NEXT_PTR_TO (t)) != POINTER_TYPE)
        {
-         error ("TYPE_NEXT_PTR_TO is not POINTER_TYPE");
+         error ("%<TYPE_NEXT_PTR_TO%> is not %<POINTER_TYPE%>");
          debug_tree (TYPE_NEXT_PTR_TO (t));
          error_found = true;
        }
@@ -13887,7 +14425,7 @@ verify_type (const_tree t)
       if (TYPE_NEXT_REF_TO (t)
          && TREE_CODE (TYPE_NEXT_REF_TO (t)) != REFERENCE_TYPE)
        {
-         error ("TYPE_NEXT_REF_TO is not REFERENCE_TYPE");
+         error ("%<TYPE_NEXT_REF_TO%> is not %<REFERENCE_TYPE%>");
          debug_tree (TYPE_NEXT_REF_TO (t));
          error_found = true;
        }
@@ -13908,13 +14446,13 @@ verify_type (const_tree t)
        ;
       else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
        {
-         error ("TYPE_BINFO is not TREE_BINFO");
+         error ("%<TYPE_BINFO%> is not %<TREE_BINFO%>");
          debug_tree (TYPE_BINFO (t));
          error_found = true;
        }
       else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t))
        {
-         error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
+         error ("%<TYPE_BINFO%> type is not %<TYPE_MAIN_VARIANT%>");
          debug_tree (TREE_TYPE (TYPE_BINFO (t)));
          error_found = true;
        }
@@ -13925,7 +14463,7 @@ verify_type (const_tree t)
          && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != RECORD_TYPE
          && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != UNION_TYPE)
        {
-         error ("TYPE_METHOD_BASETYPE is not record nor union");
+         error ("%<TYPE_METHOD_BASETYPE%> is not record nor union");
          debug_tree (TYPE_METHOD_BASETYPE (t));
          error_found = true;
        }
@@ -13936,7 +14474,7 @@ verify_type (const_tree t)
          && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != RECORD_TYPE
          && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != UNION_TYPE)
        {
-         error ("TYPE_OFFSET_BASETYPE is not record nor union");
+         error ("%<TYPE_OFFSET_BASETYPE%> is not record nor union");
          debug_tree (TYPE_OFFSET_BASETYPE (t));
          error_found = true;
        }
@@ -13954,21 +14492,21 @@ verify_type (const_tree t)
       if (TYPE_ARRAY_MAX_SIZE (t)
          && TREE_CODE (TYPE_ARRAY_MAX_SIZE (t)) != INTEGER_CST)
         {
-         error ("TYPE_ARRAY_MAX_SIZE not INTEGER_CST");
+         error ("%<TYPE_ARRAY_MAX_SIZE%> not %<INTEGER_CST%>");
          debug_tree (TYPE_ARRAY_MAX_SIZE (t));
          error_found = true;
         } 
     }
   else if (TYPE_MAX_VALUE_RAW (t))
     {
-      error ("TYPE_MAX_VALUE_RAW non-NULL");
+      error ("%<TYPE_MAX_VALUE_RAW%> non-NULL");
       debug_tree (TYPE_MAX_VALUE_RAW (t));
       error_found = true;
     }
 
   if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
     {
-      error ("TYPE_LANG_SLOT_1 (binfo) field is non-NULL");
+      error ("%<TYPE_LANG_SLOT_1 (binfo)%> field is non-NULL");
       debug_tree (TYPE_LANG_SLOT_1 (t));
       error_found = true;
     }
@@ -13984,7 +14522,7 @@ verify_type (const_tree t)
           CONST_DECL of ENUMERAL TYPE.  */
        if (TREE_CODE (value) != INTEGER_CST && TREE_CODE (value) != CONST_DECL)
          {
-           error ("Enum value is not CONST_DECL or INTEGER_CST");
+           error ("enum value is not %<CONST_DECL%> or %<INTEGER_CST%>");
            debug_tree (value);
            debug_tree (name);
            error_found = true;
@@ -13992,14 +14530,15 @@ verify_type (const_tree t)
        if (TREE_CODE (TREE_TYPE (value)) != INTEGER_TYPE
            && !useless_type_conversion_p (const_cast <tree> (t), TREE_TYPE (value)))
          {
-           error ("Enum value type is not INTEGER_TYPE nor convertible to the enum");
+           error ("enum value type is not %<INTEGER_TYPE%> nor convertible "
+                  "to the enum");
            debug_tree (value);
            debug_tree (name);
            error_found = true;
          }
        if (TREE_CODE (name) != IDENTIFIER_NODE)
          {
-           error ("Enum value name is not IDENTIFIER_NODE");
+           error ("enum value name is not %<IDENTIFIER_NODE%>");
            debug_tree (value);
            debug_tree (name);
            error_found = true;
@@ -14009,7 +14548,7 @@ verify_type (const_tree t)
     {
       if (TYPE_DOMAIN (t) && TREE_CODE (TYPE_DOMAIN (t)) != INTEGER_TYPE)
        {
-         error ("Array TYPE_DOMAIN is not integer type");
+         error ("array %<TYPE_DOMAIN%> is not integer type");
          debug_tree (TYPE_DOMAIN (t));
          error_found = true;
        }
@@ -14018,7 +14557,7 @@ verify_type (const_tree t)
     {
       if (TYPE_FIELDS (t) && !COMPLETE_TYPE_P (t) && in_lto_p)
        {
-         error ("TYPE_FIELDS defined in incomplete type");
+         error ("%<TYPE_FIELDS%> defined in incomplete type");
          error_found = true;
        }
       for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
@@ -14040,7 +14579,7 @@ verify_type (const_tree t)
            ;
          else
            {
-             error ("Wrong tree in TYPE_FIELDS list");
+             error ("wrong tree in %<TYPE_FIELDS%> list");
              debug_tree (fld);
              error_found = true;
            }
@@ -14055,13 +14594,14 @@ verify_type (const_tree t)
     {
       if (TYPE_CACHED_VALUES_P (t) != (TYPE_CACHED_VALUES (t) != NULL))
        {
-         error ("TYPE_CACHED_VALUES_P is %i while TYPE_CACHED_VALUES is %p",
+         error ("%<TYPE_CACHED_VALUES_P%> is %i while %<TYPE_CACHED_VALUES%> "
+                "is %p",
                 TYPE_CACHED_VALUES_P (t), (void *)TYPE_CACHED_VALUES (t));
          error_found = true;
        }
       else if (TYPE_CACHED_VALUES_P (t) && TREE_CODE (TYPE_CACHED_VALUES (t)) != TREE_VEC)
        {
-         error ("TYPE_CACHED_VALUES is not TREE_VEC");
+         error ("%<TYPE_CACHED_VALUES%> is not %<TREE_VEC%>");
          debug_tree (TYPE_CACHED_VALUES (t));
          error_found = true;
        }
@@ -14074,7 +14614,7 @@ verify_type (const_tree t)
            if (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)
                && TREE_TYPE (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)) != t)
              {
-               error ("wrong TYPE_CACHED_VALUES entry");
+               error ("wrong %<TYPE_CACHED_VALUES%> entry");
                debug_tree (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i));
                error_found = true;
                break;
@@ -14087,20 +14627,20 @@ verify_type (const_tree t)
        /* C++ FE uses TREE_PURPOSE to store initial values.  */
        if (TREE_PURPOSE (l) && in_lto_p)
          {
-           error ("TREE_PURPOSE is non-NULL in TYPE_ARG_TYPES list");
+           error ("%<TREE_PURPOSE%> is non-NULL in %<TYPE_ARG_TYPES%> list");
            debug_tree (l);
            error_found = true;
          }
        if (!TYPE_P (TREE_VALUE (l)))
          {
-           error ("Wrong entry in TYPE_ARG_TYPES list");
+           error ("wrong entry in %<TYPE_ARG_TYPES%> list");
            debug_tree (l);
            error_found = true;
          }
       }
   else if (!is_lang_specific (t) && TYPE_VALUES_RAW (t))
     {
-      error ("TYPE_VALUES_RAW field is non-NULL");
+      error ("%<TYPE_VALUES_RAW%> field is non-NULL");
       debug_tree (TYPE_VALUES_RAW (t));
       error_found = true;
     }
@@ -14112,13 +14652,7 @@ verify_type (const_tree t)
       && TREE_CODE (t) != POINTER_TYPE
       && TYPE_CACHED_VALUES_P (t))
     {
-      error ("TYPE_CACHED_VALUES_P is set while it should not");
-      error_found = true;
-    }
-  if (TYPE_STRING_FLAG (t)
-      && TREE_CODE (t) != ARRAY_TYPE && TREE_CODE (t) != INTEGER_TYPE)
-    {
-      error ("TYPE_STRING_FLAG is set on wrong type code");
+      error ("%<TYPE_CACHED_VALUES_P%> is set while it should not be");
       error_found = true;
     }
   
@@ -14128,14 +14662,14 @@ verify_type (const_tree t)
   if (TREE_CODE (t) == METHOD_TYPE
       && TYPE_MAIN_VARIANT (TYPE_METHOD_BASETYPE (t)) != TYPE_METHOD_BASETYPE (t))
     {
-       error ("TYPE_METHOD_BASETYPE is not main variant");
+       error ("%<TYPE_METHOD_BASETYPE%> is not main variant");
        error_found = true;
     }
 
   if (error_found)
     {
       debug_tree (const_cast <tree> (t));
-      internal_error ("verify_type failed");
+      internal_error ("%qs failed", __func__);
     }
 }
 
@@ -14348,6 +14882,11 @@ maybe_wrap_with_location (tree expr, location_t loc)
   if (EXCEPTIONAL_CLASS_P (expr))
     return expr;
 
+  /* If any auto_suppress_location_wrappers are active, don't create
+     wrappers.  */
+  if (suppress_location_wrappers > 0)
+    return expr;
+
   tree_code code
     = (((CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
        || (TREE_CODE (expr) == CONST_DECL && !TREE_STATIC (expr)))
@@ -14358,6 +14897,8 @@ maybe_wrap_with_location (tree expr, location_t loc)
   return wrapper;
 }
 
+int suppress_location_wrappers;
+
 /* Return the name of combined function FN, for debugging purposes.  */
 
 const char *
@@ -14462,6 +15003,41 @@ default_is_empty_record (const_tree type)
   return default_is_empty_type (TYPE_MAIN_VARIANT (type));
 }
 
+/* Determine whether TYPE is a structure with a flexible array member,
+   or a union containing such a structure (possibly recursively).  */
+
+bool
+flexible_array_type_p (const_tree type)
+{
+  tree x, last;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+      last = NULL_TREE;
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+       if (TREE_CODE (x) == FIELD_DECL)
+         last = x;
+      if (last == NULL_TREE)
+       return false;
+      if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE
+         && TYPE_SIZE (TREE_TYPE (last)) == NULL_TREE
+         && TYPE_DOMAIN (TREE_TYPE (last)) != NULL_TREE
+         && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (last))) == NULL_TREE)
+       return true;
+      return false;
+    case UNION_TYPE:
+      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+       {
+         if (TREE_CODE (x) == FIELD_DECL
+             && flexible_array_type_p (TREE_TYPE (x)))
+           return true;
+       }
+      return false;
+    default:
+      return false;
+  }
+}
+
 /* Like int_size_in_bytes, but handle empty records specially.  */
 
 HOST_WIDE_INT
@@ -14573,6 +15149,30 @@ const builtin_structptr_type builtin_structptr_types[6] =
   { const_fexcept_t_ptr_type_node, const_ptr_type_node, "fexcept_t" }
 };
 
+/* Return the maximum object size.  */
+
+tree
+max_object_size (void)
+{
+  /* To do: Make this a configurable parameter.  */
+  return TYPE_MAX_VALUE (ptrdiff_type_node);
+}
+
+/* A wrapper around TARGET_VERIFY_TYPE_CONTEXT that makes the silent_p
+   parameter default to false and that weeds out error_mark_node.  */
+
+bool
+verify_type_context (location_t loc, type_context_kind context,
+                    const_tree type, bool silent_p)
+{
+  if (type == error_mark_node)
+    return true;
+
+  gcc_assert (TYPE_P (type));
+  return (!targetm.verify_type_context
+         || targetm.verify_type_context (loc, context, type, silent_p));
+}
+
 #if CHECKING_P
 
 namespace selftest {
@@ -14848,6 +15448,323 @@ test_location_wrappers ()
   check_strip_nops (wrapped_int_var, int_var);
 }
 
+/* Test various tree predicates.  Verify that location wrappers don't
+   affect the results.  */
+
+static void
+test_predicates ()
+{
+  /* Build various constants and wrappers around them.  */
+
+  location_t loc = BUILTINS_LOCATION;
+
+  tree i_0 = build_int_cst (integer_type_node, 0);
+  tree wr_i_0 = maybe_wrap_with_location (i_0, loc);
+
+  tree i_1 = build_int_cst (integer_type_node, 1);
+  tree wr_i_1 = maybe_wrap_with_location (i_1, loc);
+
+  tree i_m1 = build_int_cst (integer_type_node, -1);
+  tree wr_i_m1 = maybe_wrap_with_location (i_m1, loc);
+
+  tree f_0 = build_real_from_int_cst (float_type_node, i_0);
+  tree wr_f_0 = maybe_wrap_with_location (f_0, loc);
+  tree f_1 = build_real_from_int_cst (float_type_node, i_1);
+  tree wr_f_1 = maybe_wrap_with_location (f_1, loc);
+  tree f_m1 = build_real_from_int_cst (float_type_node, i_m1);
+  tree wr_f_m1 = maybe_wrap_with_location (f_m1, loc);
+
+  tree c_i_0 = build_complex (NULL_TREE, i_0, i_0);
+  tree c_i_1 = build_complex (NULL_TREE, i_1, i_0);
+  tree c_i_m1 = build_complex (NULL_TREE, i_m1, i_0);
+
+  tree c_f_0 = build_complex (NULL_TREE, f_0, f_0);
+  tree c_f_1 = build_complex (NULL_TREE, f_1, f_0);
+  tree c_f_m1 = build_complex (NULL_TREE, f_m1, f_0);
+
+  /* TODO: vector constants.  */
+
+  /* Test integer_onep.  */
+  ASSERT_FALSE (integer_onep (i_0));
+  ASSERT_FALSE (integer_onep (wr_i_0));
+  ASSERT_TRUE (integer_onep (i_1));
+  ASSERT_TRUE (integer_onep (wr_i_1));
+  ASSERT_FALSE (integer_onep (i_m1));
+  ASSERT_FALSE (integer_onep (wr_i_m1));
+  ASSERT_FALSE (integer_onep (f_0));
+  ASSERT_FALSE (integer_onep (wr_f_0));
+  ASSERT_FALSE (integer_onep (f_1));
+  ASSERT_FALSE (integer_onep (wr_f_1));
+  ASSERT_FALSE (integer_onep (f_m1));
+  ASSERT_FALSE (integer_onep (wr_f_m1));
+  ASSERT_FALSE (integer_onep (c_i_0));
+  ASSERT_TRUE (integer_onep (c_i_1));
+  ASSERT_FALSE (integer_onep (c_i_m1));
+  ASSERT_FALSE (integer_onep (c_f_0));
+  ASSERT_FALSE (integer_onep (c_f_1));
+  ASSERT_FALSE (integer_onep (c_f_m1));
+
+  /* Test integer_zerop.  */
+  ASSERT_TRUE (integer_zerop (i_0));
+  ASSERT_TRUE (integer_zerop (wr_i_0));
+  ASSERT_FALSE (integer_zerop (i_1));
+  ASSERT_FALSE (integer_zerop (wr_i_1));
+  ASSERT_FALSE (integer_zerop (i_m1));
+  ASSERT_FALSE (integer_zerop (wr_i_m1));
+  ASSERT_FALSE (integer_zerop (f_0));
+  ASSERT_FALSE (integer_zerop (wr_f_0));
+  ASSERT_FALSE (integer_zerop (f_1));
+  ASSERT_FALSE (integer_zerop (wr_f_1));
+  ASSERT_FALSE (integer_zerop (f_m1));
+  ASSERT_FALSE (integer_zerop (wr_f_m1));
+  ASSERT_TRUE (integer_zerop (c_i_0));
+  ASSERT_FALSE (integer_zerop (c_i_1));
+  ASSERT_FALSE (integer_zerop (c_i_m1));
+  ASSERT_FALSE (integer_zerop (c_f_0));
+  ASSERT_FALSE (integer_zerop (c_f_1));
+  ASSERT_FALSE (integer_zerop (c_f_m1));
+
+  /* Test integer_all_onesp.  */
+  ASSERT_FALSE (integer_all_onesp (i_0));
+  ASSERT_FALSE (integer_all_onesp (wr_i_0));
+  ASSERT_FALSE (integer_all_onesp (i_1));
+  ASSERT_FALSE (integer_all_onesp (wr_i_1));
+  ASSERT_TRUE (integer_all_onesp (i_m1));
+  ASSERT_TRUE (integer_all_onesp (wr_i_m1));
+  ASSERT_FALSE (integer_all_onesp (f_0));
+  ASSERT_FALSE (integer_all_onesp (wr_f_0));
+  ASSERT_FALSE (integer_all_onesp (f_1));
+  ASSERT_FALSE (integer_all_onesp (wr_f_1));
+  ASSERT_FALSE (integer_all_onesp (f_m1));
+  ASSERT_FALSE (integer_all_onesp (wr_f_m1));
+  ASSERT_FALSE (integer_all_onesp (c_i_0));
+  ASSERT_FALSE (integer_all_onesp (c_i_1));
+  ASSERT_FALSE (integer_all_onesp (c_i_m1));
+  ASSERT_FALSE (integer_all_onesp (c_f_0));
+  ASSERT_FALSE (integer_all_onesp (c_f_1));
+  ASSERT_FALSE (integer_all_onesp (c_f_m1));
+
+  /* Test integer_minus_onep.  */
+  ASSERT_FALSE (integer_minus_onep (i_0));
+  ASSERT_FALSE (integer_minus_onep (wr_i_0));
+  ASSERT_FALSE (integer_minus_onep (i_1));
+  ASSERT_FALSE (integer_minus_onep (wr_i_1));
+  ASSERT_TRUE (integer_minus_onep (i_m1));
+  ASSERT_TRUE (integer_minus_onep (wr_i_m1));
+  ASSERT_FALSE (integer_minus_onep (f_0));
+  ASSERT_FALSE (integer_minus_onep (wr_f_0));
+  ASSERT_FALSE (integer_minus_onep (f_1));
+  ASSERT_FALSE (integer_minus_onep (wr_f_1));
+  ASSERT_FALSE (integer_minus_onep (f_m1));
+  ASSERT_FALSE (integer_minus_onep (wr_f_m1));
+  ASSERT_FALSE (integer_minus_onep (c_i_0));
+  ASSERT_FALSE (integer_minus_onep (c_i_1));
+  ASSERT_TRUE (integer_minus_onep (c_i_m1));
+  ASSERT_FALSE (integer_minus_onep (c_f_0));
+  ASSERT_FALSE (integer_minus_onep (c_f_1));
+  ASSERT_FALSE (integer_minus_onep (c_f_m1));
+
+  /* Test integer_each_onep.  */
+  ASSERT_FALSE (integer_each_onep (i_0));
+  ASSERT_FALSE (integer_each_onep (wr_i_0));
+  ASSERT_TRUE (integer_each_onep (i_1));
+  ASSERT_TRUE (integer_each_onep (wr_i_1));
+  ASSERT_FALSE (integer_each_onep (i_m1));
+  ASSERT_FALSE (integer_each_onep (wr_i_m1));
+  ASSERT_FALSE (integer_each_onep (f_0));
+  ASSERT_FALSE (integer_each_onep (wr_f_0));
+  ASSERT_FALSE (integer_each_onep (f_1));
+  ASSERT_FALSE (integer_each_onep (wr_f_1));
+  ASSERT_FALSE (integer_each_onep (f_m1));
+  ASSERT_FALSE (integer_each_onep (wr_f_m1));
+  ASSERT_FALSE (integer_each_onep (c_i_0));
+  ASSERT_FALSE (integer_each_onep (c_i_1));
+  ASSERT_FALSE (integer_each_onep (c_i_m1));
+  ASSERT_FALSE (integer_each_onep (c_f_0));
+  ASSERT_FALSE (integer_each_onep (c_f_1));
+  ASSERT_FALSE (integer_each_onep (c_f_m1));
+
+  /* Test integer_truep.  */
+  ASSERT_FALSE (integer_truep (i_0));
+  ASSERT_FALSE (integer_truep (wr_i_0));
+  ASSERT_TRUE (integer_truep (i_1));
+  ASSERT_TRUE (integer_truep (wr_i_1));
+  ASSERT_FALSE (integer_truep (i_m1));
+  ASSERT_FALSE (integer_truep (wr_i_m1));
+  ASSERT_FALSE (integer_truep (f_0));
+  ASSERT_FALSE (integer_truep (wr_f_0));
+  ASSERT_FALSE (integer_truep (f_1));
+  ASSERT_FALSE (integer_truep (wr_f_1));
+  ASSERT_FALSE (integer_truep (f_m1));
+  ASSERT_FALSE (integer_truep (wr_f_m1));
+  ASSERT_FALSE (integer_truep (c_i_0));
+  ASSERT_TRUE (integer_truep (c_i_1));
+  ASSERT_FALSE (integer_truep (c_i_m1));
+  ASSERT_FALSE (integer_truep (c_f_0));
+  ASSERT_FALSE (integer_truep (c_f_1));
+  ASSERT_FALSE (integer_truep (c_f_m1));
+
+  /* Test integer_nonzerop.  */
+  ASSERT_FALSE (integer_nonzerop (i_0));
+  ASSERT_FALSE (integer_nonzerop (wr_i_0));
+  ASSERT_TRUE (integer_nonzerop (i_1));
+  ASSERT_TRUE (integer_nonzerop (wr_i_1));
+  ASSERT_TRUE (integer_nonzerop (i_m1));
+  ASSERT_TRUE (integer_nonzerop (wr_i_m1));
+  ASSERT_FALSE (integer_nonzerop (f_0));
+  ASSERT_FALSE (integer_nonzerop (wr_f_0));
+  ASSERT_FALSE (integer_nonzerop (f_1));
+  ASSERT_FALSE (integer_nonzerop (wr_f_1));
+  ASSERT_FALSE (integer_nonzerop (f_m1));
+  ASSERT_FALSE (integer_nonzerop (wr_f_m1));
+  ASSERT_FALSE (integer_nonzerop (c_i_0));
+  ASSERT_TRUE (integer_nonzerop (c_i_1));
+  ASSERT_TRUE (integer_nonzerop (c_i_m1));
+  ASSERT_FALSE (integer_nonzerop (c_f_0));
+  ASSERT_FALSE (integer_nonzerop (c_f_1));
+  ASSERT_FALSE (integer_nonzerop (c_f_m1));
+
+  /* Test real_zerop.  */
+  ASSERT_FALSE (real_zerop (i_0));
+  ASSERT_FALSE (real_zerop (wr_i_0));
+  ASSERT_FALSE (real_zerop (i_1));
+  ASSERT_FALSE (real_zerop (wr_i_1));
+  ASSERT_FALSE (real_zerop (i_m1));
+  ASSERT_FALSE (real_zerop (wr_i_m1));
+  ASSERT_TRUE (real_zerop (f_0));
+  ASSERT_TRUE (real_zerop (wr_f_0));
+  ASSERT_FALSE (real_zerop (f_1));
+  ASSERT_FALSE (real_zerop (wr_f_1));
+  ASSERT_FALSE (real_zerop (f_m1));
+  ASSERT_FALSE (real_zerop (wr_f_m1));
+  ASSERT_FALSE (real_zerop (c_i_0));
+  ASSERT_FALSE (real_zerop (c_i_1));
+  ASSERT_FALSE (real_zerop (c_i_m1));
+  ASSERT_TRUE (real_zerop (c_f_0));
+  ASSERT_FALSE (real_zerop (c_f_1));
+  ASSERT_FALSE (real_zerop (c_f_m1));
+
+  /* Test real_onep.  */
+  ASSERT_FALSE (real_onep (i_0));
+  ASSERT_FALSE (real_onep (wr_i_0));
+  ASSERT_FALSE (real_onep (i_1));
+  ASSERT_FALSE (real_onep (wr_i_1));
+  ASSERT_FALSE (real_onep (i_m1));
+  ASSERT_FALSE (real_onep (wr_i_m1));
+  ASSERT_FALSE (real_onep (f_0));
+  ASSERT_FALSE (real_onep (wr_f_0));
+  ASSERT_TRUE (real_onep (f_1));
+  ASSERT_TRUE (real_onep (wr_f_1));
+  ASSERT_FALSE (real_onep (f_m1));
+  ASSERT_FALSE (real_onep (wr_f_m1));
+  ASSERT_FALSE (real_onep (c_i_0));
+  ASSERT_FALSE (real_onep (c_i_1));
+  ASSERT_FALSE (real_onep (c_i_m1));
+  ASSERT_FALSE (real_onep (c_f_0));
+  ASSERT_TRUE (real_onep (c_f_1));
+  ASSERT_FALSE (real_onep (c_f_m1));
+
+  /* Test real_minus_onep.  */
+  ASSERT_FALSE (real_minus_onep (i_0));
+  ASSERT_FALSE (real_minus_onep (wr_i_0));
+  ASSERT_FALSE (real_minus_onep (i_1));
+  ASSERT_FALSE (real_minus_onep (wr_i_1));
+  ASSERT_FALSE (real_minus_onep (i_m1));
+  ASSERT_FALSE (real_minus_onep (wr_i_m1));
+  ASSERT_FALSE (real_minus_onep (f_0));
+  ASSERT_FALSE (real_minus_onep (wr_f_0));
+  ASSERT_FALSE (real_minus_onep (f_1));
+  ASSERT_FALSE (real_minus_onep (wr_f_1));
+  ASSERT_TRUE (real_minus_onep (f_m1));
+  ASSERT_TRUE (real_minus_onep (wr_f_m1));
+  ASSERT_FALSE (real_minus_onep (c_i_0));
+  ASSERT_FALSE (real_minus_onep (c_i_1));
+  ASSERT_FALSE (real_minus_onep (c_i_m1));
+  ASSERT_FALSE (real_minus_onep (c_f_0));
+  ASSERT_FALSE (real_minus_onep (c_f_1));
+  ASSERT_TRUE (real_minus_onep (c_f_m1));
+
+  /* Test zerop.  */
+  ASSERT_TRUE (zerop (i_0));
+  ASSERT_TRUE (zerop (wr_i_0));
+  ASSERT_FALSE (zerop (i_1));
+  ASSERT_FALSE (zerop (wr_i_1));
+  ASSERT_FALSE (zerop (i_m1));
+  ASSERT_FALSE (zerop (wr_i_m1));
+  ASSERT_TRUE (zerop (f_0));
+  ASSERT_TRUE (zerop (wr_f_0));
+  ASSERT_FALSE (zerop (f_1));
+  ASSERT_FALSE (zerop (wr_f_1));
+  ASSERT_FALSE (zerop (f_m1));
+  ASSERT_FALSE (zerop (wr_f_m1));
+  ASSERT_TRUE (zerop (c_i_0));
+  ASSERT_FALSE (zerop (c_i_1));
+  ASSERT_FALSE (zerop (c_i_m1));
+  ASSERT_TRUE (zerop (c_f_0));
+  ASSERT_FALSE (zerop (c_f_1));
+  ASSERT_FALSE (zerop (c_f_m1));
+
+  /* Test tree_expr_nonnegative_p.  */
+  ASSERT_TRUE (tree_expr_nonnegative_p (i_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_i_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (i_1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_i_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (i_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (wr_i_m1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (f_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_f_0));
+  ASSERT_TRUE (tree_expr_nonnegative_p (f_1));
+  ASSERT_TRUE (tree_expr_nonnegative_p (wr_f_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (f_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (wr_f_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_0));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_i_m1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_0));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_1));
+  ASSERT_FALSE (tree_expr_nonnegative_p (c_f_m1));
+
+  /* Test tree_expr_nonzero_p.  */
+  ASSERT_FALSE (tree_expr_nonzero_p (i_0));
+  ASSERT_FALSE (tree_expr_nonzero_p (wr_i_0));
+  ASSERT_TRUE (tree_expr_nonzero_p (i_1));
+  ASSERT_TRUE (tree_expr_nonzero_p (wr_i_1));
+  ASSERT_TRUE (tree_expr_nonzero_p (i_m1));
+  ASSERT_TRUE (tree_expr_nonzero_p (wr_i_m1));
+
+  /* Test integer_valued_real_p.  */
+  ASSERT_FALSE (integer_valued_real_p (i_0));
+  ASSERT_TRUE (integer_valued_real_p (f_0));
+  ASSERT_TRUE (integer_valued_real_p (wr_f_0));
+  ASSERT_TRUE (integer_valued_real_p (f_1));
+  ASSERT_TRUE (integer_valued_real_p (wr_f_1));
+
+  /* Test integer_pow2p.  */
+  ASSERT_FALSE (integer_pow2p (i_0));
+  ASSERT_TRUE (integer_pow2p (i_1));
+  ASSERT_TRUE (integer_pow2p (wr_i_1));
+
+  /* Test uniform_integer_cst_p.  */
+  ASSERT_TRUE (uniform_integer_cst_p (i_0));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_0));
+  ASSERT_TRUE (uniform_integer_cst_p (i_1));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_1));
+  ASSERT_TRUE (uniform_integer_cst_p (i_m1));
+  ASSERT_TRUE (uniform_integer_cst_p (wr_i_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (f_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (wr_f_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_0));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_i_m1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_0));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_1));
+  ASSERT_FALSE (uniform_integer_cst_p (c_f_m1));
+}
+
 /* Check that string escaping works correctly.  */
 
 static void
@@ -14901,6 +15818,7 @@ tree_c_tests ()
   test_labels ();
   test_vector_cst_patterns ();
   test_location_wrappers ();
+  test_predicates ();
   test_escaped_strings ();
 }