IA MCU psABI support: changes to libraries
[gcc.git] / gcc / gimple.c
index d27e94b218c61ea6c5897bac5f26d5e7c5bc18d5..b32c6b5ada48b122ed35e9dd8fce6045c601c737 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR support functions.
 
-   Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2007-2015 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com>
 
 This file is part of GCC.
@@ -24,31 +24,41 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "target.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
-#include "ggc.h"
+#include "fold-const.h"
+#include "calls.h"
+#include "stmt.h"
+#include "stor-layout.h"
 #include "hard-reg-set.h"
+#include "predict.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
 #include "gimple.h"
+#include "gimplify.h"
 #include "diagnostic.h"
-#include "tree-flow.h"
 #include "value-prof.h"
 #include "flags.h"
 #include "alias.h"
 #include "demangle.h"
 #include "langhooks.h"
+#include "bitmap.h"
+#include "stringpool.h"
+#include "tree-ssanames.h"
+#include "lto-streamer.h"
+#include "cgraph.h"
+#include "gimple-ssa.h"
 
-/* Global type table.  FIXME lto, it should be possible to re-use some
-   of the type hashing routines in tree.c (type_hash_canon, type_hash_lookup,
-   etc), but those assume that types were built with the various
-   build_*_type routines which is not the case with the streamer.  */
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-  htab_t gimple_types;
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-  htab_t gimple_canonical_types;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
-  htab_t type_hash_cache;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
-  htab_t canonical_type_hash_cache;
 
 /* All the tuples have their operand vector (if present) at the very bottom
    of the structure.  Therefore, the offset required to find the
@@ -61,7 +71,7 @@ EXPORTED_CONST size_t gimple_ops_offset_[] = {
 };
 #undef DEFGSSTRUCT
 
-#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof(struct STRUCT),
+#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof (struct STRUCT),
 static const size_t gsstruct_code_size[] = {
 #include "gsstruct.def"
 };
@@ -79,7 +89,6 @@ EXPORTED_CONST enum gimple_statement_structure_enum gss_for_code_[] = {
 };
 #undef DEFGSCODE
 
-#ifdef GATHER_STATISTICS
 /* Gimple stats.  */
 
 int gimple_alloc_counts[(int) gimple_alloc_kind_all];
@@ -90,21 +99,9 @@ static const char * const gimple_alloc_kind_names[] = {
     "assignments",
     "phi nodes",
     "conditionals",
-    "sequences",
     "everything else"
 };
 
-#endif /* GATHER_STATISTICS */
-
-/* A cache of gimple_seq objects.  Sequences are created and destroyed
-   fairly often during gimplification.  */
-static GTY ((deletable)) struct gimple_seq_d *gimple_seq_cache;
-
-/* Private API manipulation functions shared only with some
-   other files.  */
-extern void gimple_set_stored_syms (gimple, bitmap, bitmap_obstack *);
-extern void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
-
 /* Gimple tuple constructors.
    Note: Any constructor taking a ``gimple_seq'' as a parameter, can
    be passed a NULL to start with an empty sequence.  */
@@ -114,7 +111,7 @@ extern void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
 static inline void
 gimple_set_code (gimple g, enum gimple_code code)
 {
-  g->gsbase.code = code;
+  g->code = code;
 }
 
 /* Return the number of bytes needed to hold a GIMPLE statement with
@@ -139,21 +136,21 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
   if (num_ops > 0)
     size += sizeof (tree) * (num_ops - 1);
 
-#ifdef GATHER_STATISTICS
-  {
-    enum gimple_alloc_kind kind = gimple_alloc_kind (code);
-    gimple_alloc_counts[(int) kind]++;
-    gimple_alloc_sizes[(int) kind] += size;
-  }
-#endif
+  if (GATHER_STATISTICS)
+    {
+      enum gimple_alloc_kind kind = gimple_alloc_kind (code);
+      gimple_alloc_counts[(int) kind]++;
+      gimple_alloc_sizes[(int) kind] += size;
+    }
 
-  stmt = ggc_alloc_cleared_gimple_statement_d_stat (size PASS_MEM_STAT);
+  stmt = ggc_alloc_cleared_gimple_statement_stat (size PASS_MEM_STAT);
   gimple_set_code (stmt, code);
   gimple_set_num_ops (stmt, num_ops);
 
   /* Do not call gimple_set_modified here as it has other side
      effects and this tuple is still not completely built.  */
-  stmt->gsbase.modified = 1;
+  stmt->modified = 1;
+  gimple_init_singleton (stmt);
 
   return stmt;
 }
@@ -166,13 +163,13 @@ gimple_set_subcode (gimple g, unsigned subcode)
   /* We only have 16 bits for the RHS code.  Assert that we are not
      overflowing it.  */
   gcc_assert (subcode < (1 << 16));
-  g->gsbase.subcode = subcode;
+  g->subcode = subcode;
 }
 
 
 
 /* Build a tuple with operands.  CODE is the statement to build (which
-   must be one of the GIMPLE_WITH_OPS tuples).  SUBCODE is the sub-code
+   must be one of the GIMPLE_WITH_OPS tuples).  SUBCODE is the subcode
    for the new tuple.  NUM_OPS is the number of operands to allocate.  */
 
 #define gimple_build_with_ops(c, s, n) \
@@ -191,10 +188,12 @@ gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
 
 /* Build a GIMPLE_RETURN statement returning RETVAL.  */
 
-gimple
+greturn *
 gimple_build_return (tree retval)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
+  greturn *s
+    = as_a <greturn *> (gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK,
+                                              2));
   if (retval)
     gimple_return_set_retval (s, retval);
   return s;
@@ -203,7 +202,7 @@ gimple_build_return (tree retval)
 /* Reset alias information on call S.  */
 
 void
-gimple_call_reset_alias_info (gimple s)
+gimple_call_reset_alias_info (gcall *s)
 {
   if (gimple_call_flags (s) & ECF_CONST)
     memset (gimple_call_use_set (s), 0, sizeof (struct pt_solution));
@@ -220,10 +219,12 @@ gimple_call_reset_alias_info (gimple s)
    components of a GIMPLE_CALL statement to function FN with NARGS
    arguments.  */
 
-static inline gimple
+static inline gcall *
 gimple_build_call_1 (tree fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+  gcall *s
+    = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+                                            nargs + 3));
   if (TREE_CODE (fn) == FUNCTION_DECL)
     fn = build_fold_addr_expr (fn);
   gimple_set_op (s, 1, fn);
@@ -236,15 +237,15 @@ gimple_build_call_1 (tree fn, unsigned nargs)
 /* Build a GIMPLE_CALL statement to function FN with the arguments
    specified in vector ARGS.  */
 
-gimple
-gimple_build_call_vec (tree fn, VEC(tree, heap) *args)
+gcall *
+gimple_build_call_vec (tree fn, vec<tree> args)
 {
   unsigned i;
-  unsigned nargs = VEC_length (tree, args);
-  gimple call = gimple_build_call_1 (fn, nargs);
+  unsigned nargs = args.length ();
+  gcall *call = gimple_build_call_1 (fn, nargs);
 
   for (i = 0; i < nargs; i++)
-    gimple_call_set_arg (call, i, VEC_index (tree, args, i));
+    gimple_call_set_arg (call, i, args[i]);
 
   return call;
 }
@@ -253,11 +254,11 @@ gimple_build_call_vec (tree fn, VEC(tree, heap) *args)
 /* Build a GIMPLE_CALL statement to function FN.  NARGS is the number of
    arguments.  The ... are the arguments.  */
 
-gimple
+gcall *
 gimple_build_call (tree fn, unsigned nargs, ...)
 {
   va_list ap;
-  gimple call;
+  gcall *call;
   unsigned i;
 
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
@@ -276,10 +277,10 @@ gimple_build_call (tree fn, unsigned nargs, ...)
 /* Build a GIMPLE_CALL statement to function FN.  NARGS is the number of
    arguments.  AP contains the arguments.  */
 
-gimple
+gcall *
 gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
 {
-  gimple call;
+  gcall *call;
   unsigned i;
 
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
@@ -297,11 +298,13 @@ gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
    Build the basic components of a GIMPLE_CALL statement to internal
    function FN with NARGS arguments.  */
 
-static inline gimple
+static inline gcall *
 gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
-  s->gsbase.subcode |= GF_CALL_INTERNAL;
+  gcall *s
+    = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+                                            nargs + 3));
+  s->subcode |= GF_CALL_INTERNAL;
   gimple_call_set_internal_fn (s, fn);
   gimple_call_reset_alias_info (s);
   return s;
@@ -311,11 +314,11 @@ gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 /* Build a GIMPLE_CALL statement to internal function FN.  NARGS is
    the number of arguments.  The ... are the arguments.  */
 
-gimple
+gcall *
 gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
 {
   va_list ap;
-  gimple call;
+  gcall *call;
   unsigned i;
 
   call = gimple_build_call_internal_1 (fn, nargs);
@@ -331,16 +334,16 @@ gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
 /* Build a GIMPLE_CALL statement to internal function FN with the arguments
    specified in vector ARGS.  */
 
-gimple
-gimple_build_call_internal_vec (enum internal_fn fn, VEC(tree, heap) *args)
+gcall *
+gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
 {
   unsigned i, nargs;
-  gimple call;
+  gcall *call;
 
-  nargs = VEC_length (tree, args);
+  nargs = args.length ();
   call = gimple_build_call_internal_1 (fn, nargs);
   for (i = 0; i < nargs; i++)
-    gimple_call_set_arg (call, i, VEC_index (tree, args, i));
+    gimple_call_set_arg (call, i, args[i]);
 
   return call;
 }
@@ -350,11 +353,11 @@ gimple_build_call_internal_vec (enum internal_fn fn, VEC(tree, heap) *args)
    assumed to be in GIMPLE form already.  Minimal checking is done of
    this fact.  */
 
-gimple
+gcall *
 gimple_build_call_from_tree (tree t)
 {
   unsigned i, nargs;
-  gimple call;
+  gcall *call;
   tree fndecl = get_callee_fndecl (t);
 
   gcc_assert (TREE_CODE (t) == CALL_EXPR);
@@ -370,7 +373,6 @@ gimple_build_call_from_tree (tree t)
   /* Carry all the CALL_EXPR flags to the new GIMPLE_CALL.  */
   gimple_call_set_chain (call, CALL_EXPR_STATIC_CHAIN (t));
   gimple_call_set_tail (call, CALL_EXPR_TAILCALL (t));
-  gimple_call_set_cannot_inline (call, CALL_CANNOT_INLINE_P (t));
   gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
   if (fndecl
       && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
@@ -382,86 +384,45 @@ gimple_build_call_from_tree (tree t)
   gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
   gimple_call_set_nothrow (call, TREE_NOTHROW (t));
   gimple_set_no_warning (call, TREE_NO_WARNING (t));
+  gimple_call_set_with_bounds (call, CALL_WITH_BOUNDS_P (t));
 
   return call;
 }
 
 
-/* Extract the operands and code for expression EXPR into *SUBCODE_P,
-   *OP1_P, *OP2_P and *OP3_P respectively.  */
-
-void
-extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
-                        tree *op2_p, tree *op3_p)
-{
-  enum gimple_rhs_class grhs_class;
-
-  *subcode_p = TREE_CODE (expr);
-  grhs_class = get_gimple_rhs_class (*subcode_p);
-
-  if (grhs_class == GIMPLE_TERNARY_RHS)
-    {
-      *op1_p = TREE_OPERAND (expr, 0);
-      *op2_p = TREE_OPERAND (expr, 1);
-      *op3_p = TREE_OPERAND (expr, 2);
-    }
-  else if (grhs_class == GIMPLE_BINARY_RHS)
-    {
-      *op1_p = TREE_OPERAND (expr, 0);
-      *op2_p = TREE_OPERAND (expr, 1);
-      *op3_p = NULL_TREE;
-    }
-  else if (grhs_class == GIMPLE_UNARY_RHS)
-    {
-      *op1_p = TREE_OPERAND (expr, 0);
-      *op2_p = NULL_TREE;
-      *op3_p = NULL_TREE;
-    }
-  else if (grhs_class == GIMPLE_SINGLE_RHS)
-    {
-      *op1_p = expr;
-      *op2_p = NULL_TREE;
-      *op3_p = NULL_TREE;
-    }
-  else
-    gcc_unreachable ();
-}
-
-
 /* Build a GIMPLE_ASSIGN statement.
 
    LHS of the assignment.
    RHS of the assignment which can be unary or binary.  */
 
-gimple
-gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
+gassign *
+gimple_build_assign (tree lhs, tree rhs MEM_STAT_DECL)
 {
   enum tree_code subcode;
   tree op1, op2, op3;
 
   extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3);
-  return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2, op3
-                                           PASS_MEM_STAT);
+  return gimple_build_assign (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
 }
 
 
-/* Build a GIMPLE_ASSIGN statement with sub-code SUBCODE and operands
-   OP1 and OP2.  If OP2 is NULL then SUBCODE must be of class
-   GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS.  */
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+   OP1, OP2 and OP3.  */
 
-gimple
-gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
-                                   tree op2, tree op3 MEM_STAT_DECL)
+static inline gassign *
+gimple_build_assign_1 (tree lhs, enum tree_code subcode, tree op1,
+                      tree op2, tree op3 MEM_STAT_DECL)
 {
   unsigned num_ops;
-  gimple p;
+  gassign *p;
 
   /* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the
      code).  */
   num_ops = get_gimple_rhs_num_ops (subcode) + 1;
 
-  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
-                                 PASS_MEM_STAT);
+  p = as_a <gassign *> (
+        gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
+                                   PASS_MEM_STAT));
   gimple_assign_set_lhs (p, lhs);
   gimple_assign_set_rhs1 (p, op1);
   if (op2)
@@ -479,22 +440,34 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1,
   return p;
 }
 
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+   OP1, OP2 and OP3.  */
 
-/* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
+                    tree op2, tree op3 MEM_STAT_DECL)
+{
+  return gimple_build_assign_1 (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
+}
 
-   DST/SRC are the destination and source respectively.  You can pass
-   ungimplified trees in DST or SRC, in which case they will be
-   converted to a gimple operand if necessary.
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+   OP1 and OP2.  */
 
-   This function returns the newly created GIMPLE_ASSIGN tuple.  */
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
+                    tree op2 MEM_STAT_DECL)
+{
+  return gimple_build_assign_1 (lhs, subcode, op1, op2, NULL_TREE
+                               PASS_MEM_STAT);
+}
 
-gimple
-gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operand OP1.  */
+
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1 MEM_STAT_DECL)
 {
-  tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
-  gimplify_and_add (t, seq_p);
-  ggc_free (t);
-  return gimple_seq_last_stmt (*seq_p);
+  return gimple_build_assign_1 (lhs, subcode, op1, NULL_TREE, NULL_TREE
+                               PASS_MEM_STAT);
 }
 
 
@@ -504,14 +477,14 @@ gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
    T_LABEL is the label to jump to if the condition is true.
    F_LABEL is the label to jump to otherwise.  */
 
-gimple
+gcond *
 gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
                   tree t_label, tree f_label)
 {
-  gimple p;
+  gcond *p;
 
   gcc_assert (TREE_CODE_CLASS (pred_code) == tcc_comparison);
-  p = gimple_build_with_ops (GIMPLE_COND, pred_code, 4);
+  p = as_a <gcond *> (gimple_build_with_ops (GIMPLE_COND, pred_code, 4));
   gimple_cond_set_lhs (p, lhs);
   gimple_cond_set_rhs (p, rhs);
   gimple_cond_set_true_label (p, t_label);
@@ -519,41 +492,10 @@ gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
   return p;
 }
 
-
-/* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND.  */
-
-void
-gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
-                               tree *lhs_p, tree *rhs_p)
-{
-  gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
-             || TREE_CODE (cond) == TRUTH_NOT_EXPR
-             || is_gimple_min_invariant (cond)
-             || SSA_VAR_P (cond));
-
-  extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
-
-  /* Canonicalize conditionals of the form 'if (!VAL)'.  */
-  if (*code_p == TRUTH_NOT_EXPR)
-    {
-      *code_p = EQ_EXPR;
-      gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
-    }
-  /* Canonicalize conditionals of the form 'if (VAL)'  */
-  else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
-    {
-      *code_p = NE_EXPR;
-      gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-      *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
-    }
-}
-
-
 /* Build a GIMPLE_COND statement from the conditional expression tree
    COND.  T_LABEL and F_LABEL are as in gimple_build_cond.  */
 
-gimple
+gcond *
 gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
 {
   enum tree_code code;
@@ -567,7 +509,7 @@ gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
    boolean expression tree COND.  */
 
 void
-gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
+gimple_cond_set_condition_from_tree (gcond *stmt, tree cond)
 {
   enum tree_code code;
   tree lhs, rhs;
@@ -578,20 +520,22 @@ gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
 
 /* Build a GIMPLE_LABEL statement for LABEL.  */
 
-gimple
+glabel *
 gimple_build_label (tree label)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1);
+  glabel *p
+    = as_a <glabel *> (gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1));
   gimple_label_set_label (p, label);
   return p;
 }
 
 /* Build a GIMPLE_GOTO statement to label DEST.  */
 
-gimple
+ggoto *
 gimple_build_goto (tree dest)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1);
+  ggoto *p
+    = as_a <ggoto *> (gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1));
   gimple_goto_set_dest (p, dest);
   return p;
 }
@@ -610,10 +554,10 @@ gimple_build_nop (void)
    VARS are the variables in BODY.
    BLOCK is the containing block.  */
 
-gimple
+gbind *
 gimple_build_bind (tree vars, gimple_seq body, tree block)
 {
-  gimple p = gimple_alloc (GIMPLE_BIND, 0);
+  gbind *p = as_a <gbind *> (gimple_alloc (GIMPLE_BIND, 0));
   gimple_bind_set_vars (p, vars);
   if (body)
     gimple_bind_set_body (p, body);
@@ -630,29 +574,29 @@ gimple_build_bind (tree vars, gimple_seq body, tree block)
    NCLOBBERS is the number of clobbered registers.
    */
 
-static inline gimple
+static inline gasm *
 gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
                     unsigned nclobbers, unsigned nlabels)
 {
-  gimple p;
+  gasm *p;
   int size = strlen (string);
 
   /* ASMs with labels cannot have outputs.  This should have been
      enforced by the front end.  */
   gcc_assert (nlabels == 0 || noutputs == 0);
 
-  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
-                            ninputs + noutputs + nclobbers + nlabels);
+  p = as_a <gasm *> (
+        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
+                              ninputs + noutputs + nclobbers + nlabels));
 
-  p->gimple_asm.ni = ninputs;
-  p->gimple_asm.no = noutputs;
-  p->gimple_asm.nc = nclobbers;
-  p->gimple_asm.nl = nlabels;
-  p->gimple_asm.string = ggc_alloc_string (string, size);
+  p->ni = ninputs;
+  p->no = noutputs;
+  p->nc = nclobbers;
+  p->nl = nlabels;
+  p->string = ggc_alloc_string (string, size);
 
-#ifdef GATHER_STATISTICS
-  gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
-#endif
+  if (GATHER_STATISTICS)
+    gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
 
   return p;
 }
@@ -668,31 +612,31 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
    CLOBBERS is a vector of the clobbered register parameters.
    LABELS is a vector of destination labels.  */
 
-gimple
-gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs,
-                      VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers,
-                     VEC(tree,gc)* labels)
+gasm *
+gimple_build_asm_vec (const char *string, vec<tree, va_gc> *inputs,
+                      vec<tree, va_gc> *outputs, vec<tree, va_gc> *clobbers,
+                     vec<tree, va_gc> *labels)
 {
-  gimple p;
+  gasm *p;
   unsigned i;
 
   p = gimple_build_asm_1 (string,
-                          VEC_length (tree, inputs),
-                          VEC_length (tree, outputs),
-                          VEC_length (tree, clobbers),
-                         VEC_length (tree, labels));
+                          vec_safe_length (inputs),
+                          vec_safe_length (outputs),
+                          vec_safe_length (clobbers),
+                         vec_safe_length (labels));
 
-  for (i = 0; i < VEC_length (tree, inputs); i++)
-    gimple_asm_set_input_op (p, i, VEC_index (tree, inputs, i));
+  for (i = 0; i < vec_safe_length (inputs); i++)
+    gimple_asm_set_input_op (p, i, (*inputs)[i]);
 
-  for (i = 0; i < VEC_length (tree, outputs); i++)
-    gimple_asm_set_output_op (p, i, VEC_index (tree, outputs, i));
+  for (i = 0; i < vec_safe_length (outputs); i++)
+    gimple_asm_set_output_op (p, i, (*outputs)[i]);
 
-  for (i = 0; i < VEC_length (tree, clobbers); i++)
-    gimple_asm_set_clobber_op (p, i, VEC_index (tree, clobbers, i));
+  for (i = 0; i < vec_safe_length (clobbers); i++)
+    gimple_asm_set_clobber_op (p, i, (*clobbers)[i]);
 
-  for (i = 0; i < VEC_length (tree, labels); i++)
-    gimple_asm_set_label_op (p, i, VEC_index (tree, labels, i));
+  for (i = 0; i < vec_safe_length (labels); i++)
+    gimple_asm_set_label_op (p, i, (*labels)[i]);
 
   return p;
 }
@@ -702,10 +646,10 @@ gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs,
   TYPES are the catch types.
   HANDLER is the exception handler.  */
 
-gimple
+gcatch *
 gimple_build_catch (tree types, gimple_seq handler)
 {
-  gimple p = gimple_alloc (GIMPLE_CATCH, 0);
+  gcatch *p = as_a <gcatch *> (gimple_alloc (GIMPLE_CATCH, 0));
   gimple_catch_set_types (p, types);
   if (handler)
     gimple_catch_set_handler (p, handler);
@@ -718,10 +662,10 @@ gimple_build_catch (tree types, gimple_seq handler)
    TYPES are the filter's types.
    FAILURE is the filter's failure action.  */
 
-gimple
+geh_filter *
 gimple_build_eh_filter (tree types, gimple_seq failure)
 {
-  gimple p = gimple_alloc (GIMPLE_EH_FILTER, 0);
+  geh_filter *p = as_a <geh_filter *> (gimple_alloc (GIMPLE_EH_FILTER, 0));
   gimple_eh_filter_set_types (p, types);
   if (failure)
     gimple_eh_filter_set_failure (p, failure);
@@ -731,10 +675,10 @@ gimple_build_eh_filter (tree types, gimple_seq failure)
 
 /* Build a GIMPLE_EH_MUST_NOT_THROW statement.  */
 
-gimple
+geh_mnt *
 gimple_build_eh_must_not_throw (tree decl)
 {
-  gimple p = gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0);
+  geh_mnt *p = as_a <geh_mnt *> (gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0));
 
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
   gcc_assert (flags_from_decl_or_type (decl) & ECF_NORETURN);
@@ -745,10 +689,10 @@ gimple_build_eh_must_not_throw (tree decl)
 
 /* Build a GIMPLE_EH_ELSE statement.  */
 
-gimple
+geh_else *
 gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
 {
-  gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0);
+  geh_else *p = as_a <geh_else *> (gimple_alloc (GIMPLE_EH_ELSE, 0));
   gimple_eh_else_set_n_body (p, n_body);
   gimple_eh_else_set_e_body (p, e_body);
   return p;
@@ -761,14 +705,14 @@ gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
    KIND is either GIMPLE_TRY_CATCH or GIMPLE_TRY_FINALLY depending on
    whether this is a try/catch or a try/finally respectively.  */
 
-gimple
+gtry *
 gimple_build_try (gimple_seq eval, gimple_seq cleanup,
                  enum gimple_try_flags kind)
 {
-  gimple p;
+  gtry *p;
 
   gcc_assert (kind == GIMPLE_TRY_CATCH || kind == GIMPLE_TRY_FINALLY);
-  p = gimple_alloc (GIMPLE_TRY, 0);
+  p = as_a <gtry *> (gimple_alloc (GIMPLE_TRY, 0));
   gimple_set_subcode (p, kind);
   if (eval)
     gimple_try_set_eval (p, eval);
@@ -795,11 +739,12 @@ gimple_build_wce (gimple_seq cleanup)
 
 /* Build a GIMPLE_RESX statement.  */
 
-gimple
+gresx *
 gimple_build_resx (int region)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0);
-  p->gimple_eh_ctrl.region = region;
+  gresx *p
+    = as_a <gresx *> (gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
+  p->region = region;
   return p;
 }
 
@@ -809,70 +754,48 @@ gimple_build_resx (int region)
    NLABELS is the number of labels in the switch excluding the default.
    DEFAULT_LABEL is the default label for the switch statement.  */
 
-gimple
+gswitch *
 gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
 {
   /* nlabels + 1 default label + 1 index.  */
-  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
-                                   1 + (default_label != NULL) + nlabels);
+  gcc_checking_assert (default_label);
+  gswitch *p = as_a <gswitch *> (gimple_build_with_ops (GIMPLE_SWITCH,
+                                                       ERROR_MARK,
+                                                       1 + 1 + nlabels));
   gimple_switch_set_index (p, index);
-  if (default_label)
-    gimple_switch_set_default_label (p, default_label);
-  return p;
-}
-
-
-/* Build a GIMPLE_SWITCH statement.
-
-   INDEX is the switch's index.
-   NLABELS is the number of labels in the switch excluding the DEFAULT_LABEL.
-   ... are the labels excluding the default.  */
-
-gimple
-gimple_build_switch (unsigned nlabels, tree index, tree default_label, ...)
-{
-  va_list al;
-  unsigned i, offset;
-  gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
-
-  /* Store the rest of the labels.  */
-  va_start (al, default_label);
-  offset = (default_label != NULL);
-  for (i = 0; i < nlabels; i++)
-    gimple_switch_set_label (p, i + offset, va_arg (al, tree));
-  va_end (al);
-
+  gimple_switch_set_default_label (p, default_label);
   return p;
 }
 
-
 /* Build a GIMPLE_SWITCH statement.
 
    INDEX is the switch's index.
    DEFAULT_LABEL is the default label
    ARGS is a vector of labels excluding the default.  */
 
-gimple
-gimple_build_switch_vec (tree index, tree default_label, VEC(tree, heap) *args)
+gswitch *
+gimple_build_switch (tree index, tree default_label, vec<tree> args)
 {
-  unsigned i, offset, nlabels = VEC_length (tree, args);
-  gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
+  unsigned i, nlabels = args.length ();
+
+  gswitch *p = gimple_build_switch_nlabels (nlabels, index, default_label);
 
   /* Copy the labels from the vector to the switch statement.  */
-  offset = (default_label != NULL);
   for (i = 0; i < nlabels; i++)
-    gimple_switch_set_label (p, i + offset, VEC_index (tree, args, i));
+    gimple_switch_set_label (p, i + 1, args[i]);
 
   return p;
 }
 
 /* Build a GIMPLE_EH_DISPATCH statement.  */
 
-gimple
+geh_dispatch *
 gimple_build_eh_dispatch (int region)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0);
-  p->gimple_eh_ctrl.region = region;
+  geh_dispatch *p
+    = as_a <geh_dispatch *> (
+       gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
+  p->region = region;
   return p;
 }
 
@@ -880,20 +803,17 @@ gimple_build_eh_dispatch (int region)
 
    VAR is bound to VALUE; block and location are taken from STMT.  */
 
-gimple
+gdebug *
 gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
 {
-  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
-                                        (unsigned)GIMPLE_DEBUG_BIND, 2
-                                        PASS_MEM_STAT);
-
+  gdebug *p
+    = as_a <gdebug *> (gimple_build_with_ops_stat (GIMPLE_DEBUG,
+                                                  (unsigned)GIMPLE_DEBUG_BIND, 2
+                                                  PASS_MEM_STAT));
   gimple_debug_bind_set_var (p, var);
   gimple_debug_bind_set_value (p, value);
   if (stmt)
-    {
-      gimple_set_block (p, gimple_block (stmt));
-      gimple_set_location (p, gimple_location (stmt));
-    }
+    gimple_set_location (p, gimple_location (stmt));
 
   return p;
 }
@@ -903,21 +823,20 @@ gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
 
    VAR is bound to VALUE; block and location are taken from STMT.  */
 
-gimple
+gdebug *
 gimple_build_debug_source_bind_stat (tree var, tree value,
                                     gimple stmt MEM_STAT_DECL)
 {
-  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
-                                        (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
-                                        PASS_MEM_STAT);
+  gdebug *p
+    = as_a <gdebug *> (
+        gimple_build_with_ops_stat (GIMPLE_DEBUG,
+                                   (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
+                                   PASS_MEM_STAT));
 
   gimple_debug_source_bind_set_var (p, var);
   gimple_debug_source_bind_set_value (p, value);
   if (stmt)
-    {
-      gimple_set_block (p, gimple_block (stmt));
-      gimple_set_location (p, gimple_location (stmt));
-    }
+    gimple_set_location (p, gimple_location (stmt));
 
   return p;
 }
@@ -928,10 +847,11 @@ gimple_build_debug_source_bind_stat (tree var, tree value,
    BODY is the sequence of statements for which only one thread can execute.
    NAME is optional identifier for this critical block.  */
 
-gimple
+gomp_critical *
 gimple_build_omp_critical (gimple_seq body, tree name)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
+  gomp_critical *p
+    = as_a <gomp_critical *> (gimple_alloc (GIMPLE_OMP_CRITICAL, 0));
   gimple_omp_critical_set_name (p, name);
   if (body)
     gimple_omp_set_body (p, body);
@@ -942,22 +862,23 @@ gimple_build_omp_critical (gimple_seq body, tree name)
 /* Build a GIMPLE_OMP_FOR statement.
 
    BODY is sequence of statements inside the for loop.
-   CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate,
-   lastprivate, reductions, ordered, schedule, and nowait.
+   KIND is the `for' variant.
+   CLAUSES, are any of the construct's clauses.
    COLLAPSE is the collapse count.
    PRE_BODY is the sequence of statements that are loop invariant.  */
 
-gimple
-gimple_build_omp_for (gimple_seq body, tree clauses, size_t collapse,
+gomp_for *
+gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
                      gimple_seq pre_body)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_FOR, 0);
+  gomp_for *p = as_a <gomp_for *> (gimple_alloc (GIMPLE_OMP_FOR, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_for_set_clauses (p, clauses);
-  p->gimple_omp_for.collapse = collapse;
-  p->gimple_omp_for.iter
-      = ggc_alloc_cleared_vec_gimple_omp_for_iter (collapse);
+  gimple_omp_for_set_kind (p, kind);
+  p->collapse = collapse;
+  p->iter =  ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
+
   if (pre_body)
     gimple_omp_for_set_pre_body (p, pre_body);
 
@@ -972,11 +893,12 @@ gimple_build_omp_for (gimple_seq body, tree clauses, size_t collapse,
    CHILD_FN is the function created for the parallel threads to execute.
    DATA_ARG are the shared data argument(s).  */
 
-gimple
+gomp_parallel *
 gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
                           tree data_arg)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0);
+  gomp_parallel *p
+    = as_a <gomp_parallel *> (gimple_alloc (GIMPLE_OMP_PARALLEL, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_parallel_set_clauses (p, clauses);
@@ -996,12 +918,12 @@ gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
    COPY_FN is the optional function for firstprivate initialization.
    ARG_SIZE and ARG_ALIGN are size and alignment of the data block.  */
 
-gimple
+gomp_task *
 gimple_build_omp_task (gimple_seq body, tree clauses, tree child_fn,
                       tree data_arg, tree copy_fn, tree arg_size,
                       tree arg_align)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_TASK, 0);
+  gomp_task *p = as_a <gomp_task *> (gimple_alloc (GIMPLE_OMP_TASK, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_task_set_clauses (p, clauses);
@@ -1045,15 +967,32 @@ gimple_build_omp_master (gimple_seq body)
 }
 
 
+/* Build a GIMPLE_OMP_TASKGROUP statement.
+
+   BODY is the sequence of statements to be executed by the taskgroup
+   construct.  */
+
+gimple
+gimple_build_omp_taskgroup (gimple_seq body)
+{
+  gimple p = gimple_alloc (GIMPLE_OMP_TASKGROUP, 0);
+  if (body)
+    gimple_omp_set_body (p, body);
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_CONTINUE statement.
 
    CONTROL_DEF is the definition of the control variable.
    CONTROL_USE is the use of the control variable.  */
 
-gimple
+gomp_continue *
 gimple_build_omp_continue (tree control_def, tree control_use)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE, 0);
+  gomp_continue *p
+    = as_a <gomp_continue *> (gimple_alloc (GIMPLE_OMP_CONTINUE, 0));
   gimple_omp_continue_set_control_def (p, control_def);
   gimple_omp_continue_set_control_use (p, control_use);
   return p;
@@ -1095,10 +1034,11 @@ gimple_build_omp_return (bool wait_p)
    CLAUSES are any of the OMP sections contsruct's clauses: private,
    firstprivate, lastprivate, reduction, and nowait.  */
 
-gimple
+gomp_sections *
 gimple_build_omp_sections (gimple_seq body, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0);
+  gomp_sections *p
+    = as_a <gomp_sections *> (gimple_alloc (GIMPLE_OMP_SECTIONS, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_sections_set_clauses (p, clauses);
@@ -1122,10 +1062,11 @@ gimple_build_omp_sections_switch (void)
    CLAUSES are any of the OMP single construct's clauses: private, firstprivate,
    copyprivate, nowait.  */
 
-gimple
+gomp_single *
 gimple_build_omp_single (gimple_seq body, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0);
+  gomp_single *p
+    = as_a <gomp_single *> (gimple_alloc (GIMPLE_OMP_SINGLE, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_single_set_clauses (p, clauses);
@@ -1134,12 +1075,50 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
 }
 
 
+/* Build a GIMPLE_OMP_TARGET statement.
+
+   BODY is the sequence of statements that will be executed.
+   KIND is the kind of the region.
+   CLAUSES are any of the construct's clauses.  */
+
+gomp_target *
+gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
+{
+  gomp_target *p
+    = as_a <gomp_target *> (gimple_alloc (GIMPLE_OMP_TARGET, 0));
+  if (body)
+    gimple_omp_set_body (p, body);
+  gimple_omp_target_set_clauses (p, clauses);
+  gimple_omp_target_set_kind (p, kind);
+
+  return p;
+}
+
+
+/* Build a GIMPLE_OMP_TEAMS statement.
+
+   BODY is the sequence of statements that will be executed.
+   CLAUSES are any of the OMP teams construct's clauses.  */
+
+gomp_teams *
+gimple_build_omp_teams (gimple_seq body, tree clauses)
+{
+  gomp_teams *p = as_a <gomp_teams *> (gimple_alloc (GIMPLE_OMP_TEAMS, 0));
+  if (body)
+    gimple_omp_set_body (p, body);
+  gimple_omp_teams_set_clauses (p, clauses);
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_ATOMIC_LOAD statement.  */
 
-gimple
+gomp_atomic_load *
 gimple_build_omp_atomic_load (tree lhs, tree rhs)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0);
+  gomp_atomic_load *p
+    = as_a <gomp_atomic_load *> (gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0));
   gimple_omp_atomic_load_set_lhs (p, lhs);
   gimple_omp_atomic_load_set_rhs (p, rhs);
   return p;
@@ -1149,20 +1128,22 @@ gimple_build_omp_atomic_load (tree lhs, tree rhs)
 
    VAL is the value we are storing.  */
 
-gimple
+gomp_atomic_store *
 gimple_build_omp_atomic_store (tree val)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0);
+  gomp_atomic_store *p
+    = as_a <gomp_atomic_store *> (gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0));
   gimple_omp_atomic_store_set_val (p, val);
   return p;
 }
 
 /* Build a GIMPLE_TRANSACTION statement.  */
 
-gimple
+gtransaction *
 gimple_build_transaction (gimple_seq body, tree label)
 {
-  gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0);
+  gtransaction *p
+    = as_a <gtransaction *> (gimple_alloc (GIMPLE_TRANSACTION, 0));
   gimple_transaction_set_body (p, body);
   gimple_transaction_set_label (p, label);
   return p;
@@ -1192,82 +1173,48 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
 {
   internal_error ("gimple check: expected %s(%s), have %s(%s) in %s, at %s:%d",
                  gimple_code_name[code],
-                 tree_code_name[subcode],
+                 get_tree_code_name (subcode),
                  gimple_code_name[gimple_code (gs)],
-                 gs->gsbase.subcode > 0
-                   ? tree_code_name[gs->gsbase.subcode]
+                 gs->subcode > 0
+                   ? get_tree_code_name ((enum tree_code) gs->subcode)
                    : "",
                  function, trim_filename (file), line);
 }
 #endif /* ENABLE_GIMPLE_CHECKING */
 
 
-/* Allocate a new GIMPLE sequence in GC memory and return it.  If
-   there are free sequences in GIMPLE_SEQ_CACHE return one of those
-   instead.  */
-
-gimple_seq
-gimple_seq_alloc (void)
-{
-  gimple_seq seq = gimple_seq_cache;
-  if (seq)
-    {
-      gimple_seq_cache = gimple_seq_cache->next_free;
-      gcc_assert (gimple_seq_cache != seq);
-      memset (seq, 0, sizeof (*seq));
-    }
-  else
-    {
-      seq = ggc_alloc_cleared_gimple_seq_d ();
-#ifdef GATHER_STATISTICS
-      gimple_alloc_counts[(int) gimple_alloc_kind_seq]++;
-      gimple_alloc_sizes[(int) gimple_alloc_kind_seq] += sizeof (*seq);
-#endif
-    }
-
-  return seq;
-}
-
-/* Return SEQ to the free pool of GIMPLE sequences.  */
+/* Link gimple statement GS to the end of the sequence *SEQ_P.  If
+   *SEQ_P is NULL, a new sequence is allocated.  */
 
 void
-gimple_seq_free (gimple_seq seq)
+gimple_seq_add_stmt (gimple_seq *seq_p, gimple gs)
 {
-  if (seq == NULL)
+  gimple_stmt_iterator si;
+  if (gs == NULL)
     return;
 
-  gcc_assert (gimple_seq_first (seq) == NULL);
-  gcc_assert (gimple_seq_last (seq) == NULL);
-
-  /* If this triggers, it's a sign that the same list is being freed
-     twice.  */
-  gcc_assert (seq != gimple_seq_cache || gimple_seq_cache == NULL);
-
-  /* Add SEQ to the pool of free sequences.  */
-  seq->next_free = gimple_seq_cache;
-  gimple_seq_cache = seq;
+  si = gsi_last (*seq_p);
+  gsi_insert_after (&si, gs, GSI_NEW_STMT);
 }
 
-
 /* Link gimple statement GS to the end of the sequence *SEQ_P.  If
-   *SEQ_P is NULL, a new sequence is allocated.  */
+   *SEQ_P is NULL, a new sequence is allocated.  This function is
+   similar to gimple_seq_add_stmt, but does not scan the operands.
+   During gimplification, we need to manipulate statement sequences
+   before the def/use vectors have been constructed.  */
 
 void
-gimple_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
 {
   gimple_stmt_iterator si;
 
   if (gs == NULL)
     return;
 
-  if (*seq_p == NULL)
-    *seq_p = gimple_seq_alloc ();
-
   si = gsi_last (*seq_p);
-  gsi_insert_after (&si, gs, GSI_NEW_STMT);
+  gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
 }
 
-
 /* Append sequence SRC to the end of sequence *DST_P.  If *DST_P is
    NULL, a new sequence is allocated.  */
 
@@ -1275,17 +1222,86 @@ void
 gimple_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
 {
   gimple_stmt_iterator si;
-
   if (src == NULL)
     return;
 
-  if (*dst_p == NULL)
-    *dst_p = gimple_seq_alloc ();
-
   si = gsi_last (*dst_p);
   gsi_insert_seq_after (&si, src, GSI_NEW_STMT);
 }
 
+/* Append sequence SRC to the end of sequence *DST_P.  If *DST_P is
+   NULL, a new sequence is allocated.  This function is
+   similar to gimple_seq_add_seq, but does not scan the operands.  */
+
+void
+gimple_seq_add_seq_without_update (gimple_seq *dst_p, gimple_seq src)
+{
+  gimple_stmt_iterator si;
+  if (src == NULL)
+    return;
+
+  si = gsi_last (*dst_p);
+  gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
+}
+
+/* Determine whether to assign a location to the statement GS.  */
+
+static bool
+should_carry_location_p (gimple gs)
+{
+  /* Don't emit a line note for a label.  We particularly don't want to
+     emit one for the break label, since it doesn't actually correspond
+     to the beginning of the loop/switch.  */
+  if (gimple_code (gs) == GIMPLE_LABEL)
+    return false;
+
+  return true;
+}
+
+/* Set the location for gimple statement GS to LOCATION.  */
+
+static void
+annotate_one_with_location (gimple gs, location_t location)
+{
+  if (!gimple_has_location (gs)
+      && !gimple_do_not_emit_location_p (gs)
+      && should_carry_location_p (gs))
+    gimple_set_location (gs, location);
+}
+
+/* Set LOCATION for all the statements after iterator GSI in sequence
+   SEQ.  If GSI is pointing to the end of the sequence, start with the
+   first statement in SEQ.  */
+
+void
+annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi,
+                                 location_t location)
+{
+  if (gsi_end_p (gsi))
+    gsi = gsi_start (seq);
+  else
+    gsi_next (&gsi);
+
+  for (; !gsi_end_p (gsi); gsi_next (&gsi))
+    annotate_one_with_location (gsi_stmt (gsi), location);
+}
+
+/* Set the location for all the statements in a sequence STMT_P to LOCATION.  */
+
+void
+annotate_all_with_location (gimple_seq stmt_p, location_t location)
+{
+  gimple_stmt_iterator i;
+
+  if (gimple_seq_empty_p (stmt_p))
+    return;
+
+  for (i = gsi_start (stmt_p); !gsi_end_p (i); gsi_next (&i))
+    {
+      gimple gs = gsi_stmt (i);
+      annotate_one_with_location (gs, location);
+    }
+}
 
 /* Helper function of empty_body_p.  Return true if STMT is an empty
    statement.  */
@@ -1295,8 +1311,8 @@ empty_stmt_p (gimple stmt)
 {
   if (gimple_code (stmt) == GIMPLE_NOP)
     return true;
-  if (gimple_code (stmt) == GIMPLE_BIND)
-    return empty_body_p (gimple_bind_body (stmt));
+  if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
+    return empty_body_p (gimple_bind_body (bind_stmt));
   return false;
 }
 
@@ -1325,7 +1341,7 @@ gimple_seq
 gimple_seq_copy (gimple_seq src)
 {
   gimple_stmt_iterator gsi;
-  gimple_seq new_seq = gimple_seq_alloc ();
+  gimple_seq new_seq = NULL;
   gimple stmt;
 
   for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -1338,663 +1354,70 @@ gimple_seq_copy (gimple_seq src)
 }
 
 
-/* Walk all the statements in the sequence SEQ calling walk_gimple_stmt
-   on each one.  WI is as in walk_gimple_stmt.
-
-   If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
-   value is stored in WI->CALLBACK_RESULT.  Also, the statement that
-   produced the value is returned if this statement has not been
-   removed by a callback (wi->removed_stmt).  If the statement has
-   been removed, NULL is returned.
 
-   Otherwise, all the statements are walked and NULL returned.  */
+/* Return true if calls C1 and C2 are known to go to the same function.  */
 
-gimple
-walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
-                walk_tree_fn callback_op, struct walk_stmt_info *wi)
+bool
+gimple_call_same_target_p (const_gimple c1, const_gimple c2)
 {
-  gimple_stmt_iterator gsi;
+  if (gimple_call_internal_p (c1))
+    return (gimple_call_internal_p (c2)
+           && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
+  else
+    return (gimple_call_fn (c1) == gimple_call_fn (c2)
+           || (gimple_call_fndecl (c1)
+               && gimple_call_fndecl (c1) == gimple_call_fndecl (c2)));
+}
 
-  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
-    {
-      tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
-      if (ret)
-       {
-         /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
-            to hold it.  */
-         gcc_assert (wi);
-         wi->callback_result = ret;
+/* Detect flags from a GIMPLE_CALL.  This is just like
+   call_expr_flags, but for gimple tuples.  */
 
-         return wi->removed_stmt ? NULL : gsi_stmt (gsi);
-       }
+int
+gimple_call_flags (const_gimple stmt)
+{
+  int flags;
+  tree decl = gimple_call_fndecl (stmt);
 
-      if (!wi->removed_stmt)
-       gsi_next (&gsi);
-    }
+  if (decl)
+    flags = flags_from_decl_or_type (decl);
+  else if (gimple_call_internal_p (stmt))
+    flags = internal_fn_flags (gimple_call_internal_fn (stmt));
+  else
+    flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
 
-  if (wi)
-    wi->callback_result = NULL_TREE;
+  if (stmt->subcode & GF_CALL_NOTHROW)
+    flags |= ECF_NOTHROW;
 
-  return NULL;
+  return flags;
 }
 
+/* Return the "fn spec" string for call STMT.  */
 
-/* Helper function for walk_gimple_stmt.  Walk operands of a GIMPLE_ASM.  */
-
-static tree
-walk_gimple_asm (gimple stmt, walk_tree_fn callback_op,
-                struct walk_stmt_info *wi)
+static const_tree
+gimple_call_fnspec (const gcall *stmt)
 {
-  tree ret, op;
-  unsigned noutputs;
-  const char **oconstraints;
-  unsigned i, n;
-  const char *constraint;
-  bool allows_mem, allows_reg, is_inout;
+  tree type, attr;
 
-  noutputs = gimple_asm_noutputs (stmt);
-  oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
+  if (gimple_call_internal_p (stmt))
+    return internal_fn_fnspec (gimple_call_internal_fn (stmt));
 
-  if (wi)
-    wi->is_lhs = true;
+  type = gimple_call_fntype (stmt);
+  if (!type)
+    return NULL_TREE;
 
-  for (i = 0; i < noutputs; i++)
-    {
-      op = gimple_asm_output_op (stmt, i);
-      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-      oconstraints[i] = constraint;
-      parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg,
-                              &is_inout);
-      if (wi)
-       wi->val_only = (allows_reg || !allows_mem);
-      ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-      if (ret)
-       return ret;
-    }
+  attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+  if (!attr)
+    return NULL_TREE;
 
-  n = gimple_asm_ninputs (stmt);
-  for (i = 0; i < n; i++)
-    {
-      op = gimple_asm_input_op (stmt, i);
-      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
-                             oconstraints, &allows_mem, &allows_reg);
-      if (wi)
-       {
-         wi->val_only = (allows_reg || !allows_mem);
-          /* Although input "m" is not really a LHS, we need a lvalue.  */
-         wi->is_lhs = !wi->val_only;
-       }
-      ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-      if (ret)
-       return ret;
-    }
-
-  if (wi)
-    {
-      wi->is_lhs = false;
-      wi->val_only = true;
-    }
-
-  n = gimple_asm_nlabels (stmt);
-  for (i = 0; i < n; i++)
-    {
-      op = gimple_asm_label_op (stmt, i);
-      ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-      if (ret)
-       return ret;
-    }
-
-  return NULL_TREE;
-}
-
-
-/* Helper function of WALK_GIMPLE_STMT.  Walk every tree operand in
-   STMT.  CALLBACK_OP and WI are as in WALK_GIMPLE_STMT.
-
-   CALLBACK_OP is called on each operand of STMT via walk_tree.
-   Additional parameters to walk_tree must be stored in WI.  For each operand
-   OP, walk_tree is called as:
-
-       walk_tree (&OP, CALLBACK_OP, WI, WI->PSET)
-
-   If CALLBACK_OP returns non-NULL for an operand, the remaining
-   operands are not scanned.
-
-   The return value is that returned by the last call to walk_tree, or
-   NULL_TREE if no CALLBACK_OP is specified.  */
-
-tree
-walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
-               struct walk_stmt_info *wi)
-{
-  struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
-  unsigned i;
-  tree ret = NULL_TREE;
-
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_ASSIGN:
-      /* Walk the RHS operands.  If the LHS is of a non-renamable type or
-         is a register variable, we may use a COMPONENT_REF on the RHS.  */
-      if (wi)
-       {
-         tree lhs = gimple_assign_lhs (stmt);
-         wi->val_only
-           = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
-             || !gimple_assign_single_p (stmt);
-       }
-
-      for (i = 1; i < gimple_num_ops (stmt); i++)
-       {
-         ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
-                          pset);
-         if (ret)
-           return ret;
-       }
-
-      /* Walk the LHS.  If the RHS is appropriate for a memory, we
-        may use a COMPONENT_REF on the LHS.  */
-      if (wi)
-       {
-          /* If the RHS has more than 1 operand, it is not appropriate
-             for the memory.  */
-         wi->val_only = !(is_gimple_mem_rhs (gimple_assign_rhs1 (stmt))
-                          || TREE_CODE (gimple_assign_rhs1 (stmt))
-                             == CONSTRUCTOR)
-                         || !gimple_assign_single_p (stmt);
-         wi->is_lhs = true;
-       }
-
-      ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
-      if (ret)
-       return ret;
-
-      if (wi)
-       {
-         wi->val_only = true;
-         wi->is_lhs = false;
-       }
-      break;
-
-    case GIMPLE_CALL:
-      if (wi)
-       {
-         wi->is_lhs = false;
-         wi->val_only = true;
-       }
-
-      ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-        return ret;
-
-      ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-        return ret;
-
-      for (i = 0; i < gimple_call_num_args (stmt); i++)
-       {
-         if (wi)
-           wi->val_only
-             = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
-         ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
-                          pset);
-         if (ret)
-           return ret;
-       }
-
-      if (gimple_call_lhs (stmt))
-       {
-         if (wi)
-           {
-             wi->is_lhs = true;
-             wi->val_only
-               = is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
-           }
-
-         ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
-         if (ret)
-           return ret;
-       }
-
-      if (wi)
-       {
-         wi->is_lhs = false;
-         wi->val_only = true;
-       }
-      break;
-
-    case GIMPLE_CATCH:
-      ret = walk_tree (gimple_catch_types_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_EH_FILTER:
-      ret = walk_tree (gimple_eh_filter_types_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_ASM:
-      ret = walk_gimple_asm (stmt, callback_op, wi);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_CONTINUE:
-      ret = walk_tree (gimple_omp_continue_control_def_ptr (stmt),
-                      callback_op, wi, pset);
-      if (ret)
-       return ret;
-
-      ret = walk_tree (gimple_omp_continue_control_use_ptr (stmt),
-                      callback_op, wi, pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_CRITICAL:
-      ret = walk_tree (gimple_omp_critical_name_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_FOR:
-      ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
-       {
-         ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
-                          wi, pset);
-         if (ret)
-           return ret;
-         ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
-                          wi, pset);
-         if (ret)
-           return ret;
-         ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
-                          wi, pset);
-         if (ret)
-           return ret;
-         ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
-                          wi, pset);
-       }
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_PARALLEL:
-      ret = walk_tree (gimple_omp_parallel_clauses_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_parallel_child_fn_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_parallel_data_arg_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_TASK:
-      ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_SECTIONS:
-      ret = walk_tree (gimple_omp_sections_clauses_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-
-      ret = walk_tree (gimple_omp_sections_control_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-
-      break;
-
-    case GIMPLE_OMP_SINGLE:
-      ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_ATOMIC_LOAD:
-      ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-
-      ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_ATOMIC_STORE:
-      ret = walk_tree (gimple_omp_atomic_store_val_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_TRANSACTION:
-      ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
-                      wi, pset);
-      if (ret)
-       return ret;
-      break;
-
-      /* Tuples that do not have operands.  */
-    case GIMPLE_NOP:
-    case GIMPLE_RESX:
-    case GIMPLE_OMP_RETURN:
-    case GIMPLE_PREDICT:
-      break;
-
-    default:
-      {
-       enum gimple_statement_structure_enum gss;
-       gss = gimple_statement_structure (stmt);
-       if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
-         for (i = 0; i < gimple_num_ops (stmt); i++)
-           {
-             ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
-             if (ret)
-               return ret;
-           }
-      }
-      break;
-    }
-
-  return NULL_TREE;
-}
-
-
-/* Walk the current statement in GSI (optionally using traversal state
-   stored in WI).  If WI is NULL, no state is kept during traversal.
-   The callback CALLBACK_STMT is called.  If CALLBACK_STMT indicates
-   that it has handled all the operands of the statement, its return
-   value is returned.  Otherwise, the return value from CALLBACK_STMT
-   is discarded and its operands are scanned.
-
-   If CALLBACK_STMT is NULL or it didn't handle the operands,
-   CALLBACK_OP is called on each operand of the statement via
-   walk_gimple_op.  If walk_gimple_op returns non-NULL for any
-   operand, the remaining operands are not scanned.  In this case, the
-   return value from CALLBACK_OP is returned.
-
-   In any other case, NULL_TREE is returned.  */
-
-tree
-walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
-                 walk_tree_fn callback_op, struct walk_stmt_info *wi)
-{
-  gimple ret;
-  tree tree_ret;
-  gimple stmt = gsi_stmt (*gsi);
-
-  if (wi)
-    {
-      wi->gsi = *gsi;
-      wi->removed_stmt = false;
-
-      if (wi->want_locations && gimple_has_location (stmt))
-       input_location = gimple_location (stmt);
-    }
-
-  ret = NULL;
-
-  /* Invoke the statement callback.  Return if the callback handled
-     all of STMT operands by itself.  */
-  if (callback_stmt)
-    {
-      bool handled_ops = false;
-      tree_ret = callback_stmt (gsi, &handled_ops, wi);
-      if (handled_ops)
-       return tree_ret;
-
-      /* If CALLBACK_STMT did not handle operands, it should not have
-        a value to return.  */
-      gcc_assert (tree_ret == NULL);
-
-      if (wi && wi->removed_stmt)
-       return NULL;
-
-      /* Re-read stmt in case the callback changed it.  */
-      stmt = gsi_stmt (*gsi);
-    }
-
-  /* If CALLBACK_OP is defined, invoke it on every operand of STMT.  */
-  if (callback_op)
-    {
-      tree_ret = walk_gimple_op (stmt, callback_op, wi);
-      if (tree_ret)
-       return tree_ret;
-    }
-
-  /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them.  */
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_BIND:
-      ret = walk_gimple_seq (gimple_bind_body (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_CATCH:
-      ret = walk_gimple_seq (gimple_catch_handler (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_EH_FILTER:
-      ret = walk_gimple_seq (gimple_eh_filter_failure (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_EH_ELSE:
-      ret = walk_gimple_seq (gimple_eh_else_n_body (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      ret = walk_gimple_seq (gimple_eh_else_e_body (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_TRY:
-      ret = walk_gimple_seq (gimple_try_eval (stmt), callback_stmt, callback_op,
-                            wi);
-      if (ret)
-       return wi->callback_result;
-
-      ret = walk_gimple_seq (gimple_try_cleanup (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_OMP_FOR:
-      ret = walk_gimple_seq (gimple_omp_for_pre_body (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-
-      /* FALL THROUGH.  */
-    case GIMPLE_OMP_CRITICAL:
-    case GIMPLE_OMP_MASTER:
-    case GIMPLE_OMP_ORDERED:
-    case GIMPLE_OMP_SECTION:
-    case GIMPLE_OMP_PARALLEL:
-    case GIMPLE_OMP_TASK:
-    case GIMPLE_OMP_SECTIONS:
-    case GIMPLE_OMP_SINGLE:
-      ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_WITH_CLEANUP_EXPR:
-      ret = walk_gimple_seq (gimple_wce_cleanup (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_TRANSACTION:
-      ret = walk_gimple_seq (gimple_transaction_body (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    default:
-      gcc_assert (!gimple_has_substatements (stmt));
-      break;
-    }
-
-  return NULL;
-}
-
-
-/* Set sequence SEQ to be the GIMPLE body for function FN.  */
-
-void
-gimple_set_body (tree fndecl, gimple_seq seq)
-{
-  struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-  if (fn == NULL)
-    {
-      /* If FNDECL still does not have a function structure associated
-        with it, then it does not make sense for it to receive a
-        GIMPLE body.  */
-      gcc_assert (seq == NULL);
-    }
-  else
-    fn->gimple_body = seq;
-}
-
-
-/* Return the body of GIMPLE statements for function FN.  After the
-   CFG pass, the function body doesn't exist anymore because it has
-   been split up into basic blocks.  In this case, it returns
-   NULL.  */
-
-gimple_seq
-gimple_body (tree fndecl)
-{
-  struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-  return fn ? fn->gimple_body : NULL;
-}
-
-/* Return true when FNDECL has Gimple body either in unlowered
-   or CFG form.  */
-bool
-gimple_has_body_p (tree fndecl)
-{
-  struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-  return (gimple_body (fndecl) || (fn && fn->cfg));
-}
-
-/* Return true if calls C1 and C2 are known to go to the same function.  */
-
-bool
-gimple_call_same_target_p (const_gimple c1, const_gimple c2)
-{
-  if (gimple_call_internal_p (c1))
-    return (gimple_call_internal_p (c2)
-           && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
-  else
-    return (gimple_call_fn (c1) == gimple_call_fn (c2)
-           || (gimple_call_fndecl (c1)
-               && gimple_call_fndecl (c1) == gimple_call_fndecl (c2)));
-}
-
-/* Detect flags from a GIMPLE_CALL.  This is just like
-   call_expr_flags, but for gimple tuples.  */
-
-int
-gimple_call_flags (const_gimple stmt)
-{
-  int flags;
-  tree decl = gimple_call_fndecl (stmt);
-
-  if (decl)
-    flags = flags_from_decl_or_type (decl);
-  else if (gimple_call_internal_p (stmt))
-    flags = internal_fn_flags (gimple_call_internal_fn (stmt));
-  else
-    flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
-
-  if (stmt->gsbase.subcode & GF_CALL_NOTHROW)
-    flags |= ECF_NOTHROW;
-
-  return flags;
-}
-
-/* Return the "fn spec" string for call STMT.  */
-
-static tree
-gimple_call_fnspec (const_gimple stmt)
-{
-  tree type, attr;
-
-  type = gimple_call_fntype (stmt);
-  if (!type)
-    return NULL_TREE;
-
-  attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
-  if (!attr)
-    return NULL_TREE;
-
-  return TREE_VALUE (TREE_VALUE (attr));
-}
+  return TREE_VALUE (TREE_VALUE (attr));
+}
 
 /* Detects argument flags for argument number ARG on call STMT.  */
 
 int
-gimple_call_arg_flags (const_gimple stmt, unsigned arg)
+gimple_call_arg_flags (const gcall *stmt, unsigned arg)
 {
-  tree attr = gimple_call_fnspec (stmt);
+  const_tree attr = gimple_call_fnspec (stmt);
 
   if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
     return 0;
@@ -2026,9 +1449,9 @@ gimple_call_arg_flags (const_gimple stmt, unsigned arg)
 /* Detects return flags for the call STMT.  */
 
 int
-gimple_call_return_flags (const_gimple stmt)
+gimple_call_return_flags (const gcall *stmt)
 {
-  tree attr;
+  const_tree attr;
 
   if (gimple_call_flags (stmt) & ECF_MALLOC)
     return ERF_NOALIAS;
@@ -2106,31 +1529,35 @@ gimple_assign_unary_nop_p (gimple gs)
 void
 gimple_set_bb (gimple stmt, basic_block bb)
 {
-  stmt->gsbase.bb = bb;
+  stmt->bb = bb;
+
+  if (gimple_code (stmt) != GIMPLE_LABEL)
+    return;
 
   /* If the statement is a label, add the label to block-to-labels map
      so that we can speed up edge creation for GIMPLE_GOTOs.  */
-  if (cfun->cfg && gimple_code (stmt) == GIMPLE_LABEL)
+  if (cfun->cfg)
     {
       tree t;
       int uid;
 
-      t = gimple_label_label (stmt);
+      t = gimple_label_label (as_a <glabel *> (stmt));
       uid = LABEL_DECL_UID (t);
       if (uid == -1)
        {
-         unsigned old_len = VEC_length (basic_block, label_to_block_map);
+         unsigned old_len =
+           vec_safe_length (label_to_block_map_for_fn (cfun));
          LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
          if (old_len <= (unsigned) uid)
            {
              unsigned new_len = 3 * uid / 2 + 1;
 
-             VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
+             vec_safe_grow_cleared (label_to_block_map_for_fn (cfun),
                                     new_len);
            }
        }
 
-      VEC_replace (basic_block, label_to_block_map, uid, bb);
+      (*label_to_block_map_for_fn (cfun))[uid] = bb;
     }
 }
 
@@ -2159,7 +1586,7 @@ gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr)
   tree op1, op2, op3;
 
   extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3);
-  gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3);
+  gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2, op3);
 }
 
 
@@ -2170,8 +1597,8 @@ gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr)
    did not have enough operand slots.  */
 
 void
-gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code,
-                                 tree op1, tree op2, tree op3)
+gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
+                               tree op1, tree op2, tree op3)
 {
   unsigned new_rhs_ops = get_gimple_rhs_num_ops (code);
   gimple stmt = gsi_stmt (*gsi);
@@ -2182,6 +1609,7 @@ gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code
       tree lhs = gimple_assign_lhs (stmt);
       gimple new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
       memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
+      gimple_init_singleton (new_stmt);
       gsi_replace (gsi, new_stmt, true);
       stmt = new_stmt;
 
@@ -2232,46 +1660,14 @@ gimple_set_lhs (gimple stmt, tree lhs)
   else if (code == GIMPLE_CALL)
     gimple_call_set_lhs (stmt, lhs);
   else
-    gcc_unreachable();
+    gcc_unreachable ();
 }
 
-/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a
-   GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an
-   expression with a different value.
-
-   This will update any annotations (say debug bind stmts) referring
-   to the original LHS, so that they use the RHS instead.  This is
-   done even if NLHS and LHS are the same, for it is understood that
-   the RHS will be modified afterwards, and NLHS will not be assigned
-   an equivalent value.
-
-   Adjusting any non-annotation uses of the LHS, if needed, is a
-   responsibility of the caller.
-
-   The effect of this call should be pretty much the same as that of
-   inserting a copy of STMT before STMT, and then removing the
-   original stmt, at which time gsi_remove() would have update
-   annotations, but using this function saves all the inserting,
-   copying and removing.  */
-
-void
-gimple_replace_lhs (gimple stmt, tree nlhs)
-{
-  if (MAY_HAVE_DEBUG_STMTS)
-    {
-      tree lhs = gimple_get_lhs (stmt);
-
-      gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);
-
-      insert_debug_temp_for_var_def (NULL, lhs);
-    }
-
-  gimple_set_lhs (stmt, nlhs);
-}
 
 /* Return a deep copy of statement STMT.  All the operands from STMT
    are reallocated and copied using unshare_expr.  The DEF, USE, VDEF
-   and VUSE operand arrays are set to empty in the new copy.  */
+   and VUSE operand arrays are set to empty in the new copy.  The new
+   copy isn't part of any sequence.  */
 
 gimple
 gimple_copy (gimple stmt)
@@ -2283,6 +1679,7 @@ gimple_copy (gimple stmt)
 
   /* Shallow copy all the fields from STMT.  */
   memcpy (copy, stmt, gimple_size (code));
+  gimple_init_singleton (copy);
 
   /* If STMT has sub-statements, deep-copy them as well.  */
   if (gimple_has_substatements (stmt))
@@ -2293,38 +1690,60 @@ gimple_copy (gimple stmt)
       switch (gimple_code (stmt))
        {
        case GIMPLE_BIND:
-         new_seq = gimple_seq_copy (gimple_bind_body (stmt));
-         gimple_bind_set_body (copy, new_seq);
-         gimple_bind_set_vars (copy, unshare_expr (gimple_bind_vars (stmt)));
-         gimple_bind_set_block (copy, gimple_bind_block (stmt));
+         {
+           gbind *bind_stmt = as_a <gbind *> (stmt);
+           gbind *bind_copy = as_a <gbind *> (copy);
+           new_seq = gimple_seq_copy (gimple_bind_body (bind_stmt));
+           gimple_bind_set_body (bind_copy, new_seq);
+           gimple_bind_set_vars (bind_copy,
+                                 unshare_expr (gimple_bind_vars (bind_stmt)));
+           gimple_bind_set_block (bind_copy, gimple_bind_block (bind_stmt));
+         }
          break;
 
        case GIMPLE_CATCH:
-         new_seq = gimple_seq_copy (gimple_catch_handler (stmt));
-         gimple_catch_set_handler (copy, new_seq);
-         t = unshare_expr (gimple_catch_types (stmt));
-         gimple_catch_set_types (copy, t);
+         {
+           gcatch *catch_stmt = as_a <gcatch *> (stmt);
+           gcatch *catch_copy = as_a <gcatch *> (copy);
+           new_seq = gimple_seq_copy (gimple_catch_handler (catch_stmt));
+           gimple_catch_set_handler (catch_copy, new_seq);
+           t = unshare_expr (gimple_catch_types (catch_stmt));
+           gimple_catch_set_types (catch_copy, t);
+         }
          break;
 
        case GIMPLE_EH_FILTER:
-         new_seq = gimple_seq_copy (gimple_eh_filter_failure (stmt));
-         gimple_eh_filter_set_failure (copy, new_seq);
-         t = unshare_expr (gimple_eh_filter_types (stmt));
-         gimple_eh_filter_set_types (copy, t);
+         {
+           geh_filter *eh_filter_stmt = as_a <geh_filter *> (stmt);
+           geh_filter *eh_filter_copy = as_a <geh_filter *> (copy);
+           new_seq
+             = gimple_seq_copy (gimple_eh_filter_failure (eh_filter_stmt));
+           gimple_eh_filter_set_failure (eh_filter_copy, new_seq);
+           t = unshare_expr (gimple_eh_filter_types (eh_filter_stmt));
+           gimple_eh_filter_set_types (eh_filter_copy, t);
+         }
          break;
 
        case GIMPLE_EH_ELSE:
-         new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt));
-         gimple_eh_else_set_n_body (copy, new_seq);
-         new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt));
-         gimple_eh_else_set_e_body (copy, new_seq);
+         {
+           geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
+           geh_else *eh_else_copy = as_a <geh_else *> (copy);
+           new_seq = gimple_seq_copy (gimple_eh_else_n_body (eh_else_stmt));
+           gimple_eh_else_set_n_body (eh_else_copy, new_seq);
+           new_seq = gimple_seq_copy (gimple_eh_else_e_body (eh_else_stmt));
+           gimple_eh_else_set_e_body (eh_else_copy, new_seq);
+         }
          break;
 
        case GIMPLE_TRY:
-         new_seq = gimple_seq_copy (gimple_try_eval (stmt));
-         gimple_try_set_eval (copy, new_seq);
-         new_seq = gimple_seq_copy (gimple_try_cleanup (stmt));
-         gimple_try_set_cleanup (copy, new_seq);
+         {
+           gtry *try_stmt = as_a <gtry *> (stmt);
+           gtry *try_copy = as_a <gtry *> (copy);
+           new_seq = gimple_seq_copy (gimple_try_eval (try_stmt));
+           gimple_try_set_eval (try_copy, new_seq);
+           new_seq = gimple_seq_copy (gimple_try_cleanup (try_stmt));
+           gimple_try_set_cleanup (try_copy, new_seq);
+         }
          break;
 
        case GIMPLE_OMP_FOR:
@@ -2332,9 +1751,11 @@ gimple_copy (gimple stmt)
          gimple_omp_for_set_pre_body (copy, new_seq);
          t = unshare_expr (gimple_omp_for_clauses (stmt));
          gimple_omp_for_set_clauses (copy, t);
-         copy->gimple_omp_for.iter
-           = ggc_alloc_vec_gimple_omp_for_iter
-           (gimple_omp_for_collapse (stmt));
+         {
+           gomp_for *omp_for_copy = as_a <gomp_for *> (copy);
+           omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
+             ( gimple_omp_for_collapse (stmt));
+          }
          for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
            {
              gimple_omp_for_set_cond (copy, i,
@@ -2351,12 +1772,16 @@ gimple_copy (gimple stmt)
          goto copy_omp_body;
 
        case GIMPLE_OMP_PARALLEL:
-         t = unshare_expr (gimple_omp_parallel_clauses (stmt));
-         gimple_omp_parallel_set_clauses (copy, t);
-         t = unshare_expr (gimple_omp_parallel_child_fn (stmt));
-         gimple_omp_parallel_set_child_fn (copy, t);
-         t = unshare_expr (gimple_omp_parallel_data_arg (stmt));
-         gimple_omp_parallel_set_data_arg (copy, t);
+         {
+           gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
+           gomp_parallel *omp_par_copy = as_a <gomp_parallel *> (copy);
+           t = unshare_expr (gimple_omp_parallel_clauses (omp_par_stmt));
+           gimple_omp_parallel_set_clauses (omp_par_copy, t);
+           t = unshare_expr (gimple_omp_parallel_child_fn (omp_par_stmt));
+           gimple_omp_parallel_set_child_fn (omp_par_copy, t);
+           t = unshare_expr (gimple_omp_parallel_data_arg (omp_par_stmt));
+           gimple_omp_parallel_set_data_arg (omp_par_copy, t);
+         }
          goto copy_omp_body;
 
        case GIMPLE_OMP_TASK:
@@ -2375,8 +1800,9 @@ gimple_copy (gimple stmt)
          goto copy_omp_body;
 
        case GIMPLE_OMP_CRITICAL:
-         t = unshare_expr (gimple_omp_critical_name (stmt));
-         gimple_omp_critical_set_name (copy, t);
+         t = unshare_expr (gimple_omp_critical_name (
+                             as_a <gomp_critical *> (stmt)));
+         gimple_omp_critical_set_name (as_a <gomp_critical *> (copy), t);
          goto copy_omp_body;
 
        case GIMPLE_OMP_SECTIONS:
@@ -2387,8 +1813,11 @@ gimple_copy (gimple stmt)
          /* FALLTHRU  */
 
        case GIMPLE_OMP_SINGLE:
+       case GIMPLE_OMP_TARGET:
+       case GIMPLE_OMP_TEAMS:
        case GIMPLE_OMP_SECTION:
        case GIMPLE_OMP_MASTER:
+       case GIMPLE_OMP_TASKGROUP:
        case GIMPLE_OMP_ORDERED:
        copy_omp_body:
          new_seq = gimple_seq_copy (gimple_omp_body (stmt));
@@ -2396,8 +1825,10 @@ gimple_copy (gimple stmt)
          break;
 
        case GIMPLE_TRANSACTION:
-         new_seq = gimple_seq_copy (gimple_transaction_body (stmt));
-         gimple_transaction_set_body (copy, new_seq);
+         new_seq = gimple_seq_copy (gimple_transaction_body (
+                                      as_a <gtransaction *> (stmt)));
+         gimple_transaction_set_body (as_a <gtransaction *> (copy),
+                                      new_seq);
          break;
 
        case GIMPLE_WITH_CLEANUP_EXPR:
@@ -2411,23 +1842,19 @@ gimple_copy (gimple stmt)
     }
 
   /* Make copy of operands.  */
-  if (num_ops > 0)
-    {
-      for (i = 0; i < num_ops; i++)
-       gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
+  for (i = 0; i < num_ops; i++)
+    gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
 
-      /* Clear out SSA operand vectors on COPY.  */
-      if (gimple_has_ops (stmt))
-       {
-         gimple_set_def_ops (copy, NULL);
-         gimple_set_use_ops (copy, NULL);
-       }
+  if (gimple_has_mem_ops (stmt))
+    {
+      gimple_set_vdef (copy, gimple_vdef (stmt));
+      gimple_set_vuse (copy, gimple_vuse (stmt));
+    }
 
-      if (gimple_has_mem_ops (stmt))
-       {
-         gimple_set_vdef (copy, gimple_vdef (stmt));
-         gimple_set_vuse (copy, gimple_vuse (stmt));
-       }
+  /* Clear out SSA operand vectors on COPY.  */
+  if (gimple_has_ops (stmt))
+    {
+      gimple_set_use_ops (copy, NULL);
 
       /* SSA operands need to be updated.  */
       gimple_set_modified (copy, true);
@@ -2437,19 +1864,8 @@ gimple_copy (gimple stmt)
 }
 
 
-/* Set the MODIFIED flag to MODIFIEDP, iff the gimple statement G has
-   a MODIFIED field.  */
-
-void
-gimple_set_modified (gimple s, bool modifiedp)
-{
-  if (gimple_has_ops (s))
-    s->gsbase.modified = (unsigned) modifiedp;
-}
-
-
-/* Return true if statement S has side-effects.  We consider a
-   statement to have side effects if:
+/* Return true if statement S has side-effects.  We consider a
+   statement to have side effects if:
 
    - It is a GIMPLE_CALL not marked with ECF_PURE or ECF_CONST.
    - Any of its operands are marked TREE_THIS_VOLATILE or TREE_SIDE_EFFECTS.  */
@@ -2467,7 +1883,7 @@ gimple_has_side_effects (const_gimple s)
     return true;
 
   if (gimple_code (s) == GIMPLE_ASM
-      && gimple_asm_volatile_p (s))
+      && gimple_asm_volatile_p (as_a <const gasm *> (s)))
     return true;
 
   if (is_gimple_call (s))
@@ -2485,69 +1901,6 @@ gimple_has_side_effects (const_gimple s)
   return false;
 }
 
-/* Return true if the RHS of statement S has side effects.
-   We may use it to determine if it is admissable to replace
-   an assignment or call with a copy of a previously-computed
-   value.  In such cases, side-effects due to the LHS are
-   preserved.  */
-
-bool
-gimple_rhs_has_side_effects (const_gimple s)
-{
-  unsigned i;
-
-  if (is_gimple_call (s))
-    {
-      unsigned nargs = gimple_call_num_args (s);
-      tree fn;
-
-      if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
-        return true;
-
-      /* We cannot use gimple_has_volatile_ops here,
-         because we must ignore a volatile LHS.  */
-      fn = gimple_call_fn (s);
-      if (fn && (TREE_SIDE_EFFECTS (fn) || TREE_THIS_VOLATILE (fn)))
-       {
-         gcc_assert (gimple_has_volatile_ops (s));
-         return true;
-       }
-
-      for (i = 0; i < nargs; i++)
-        if (TREE_SIDE_EFFECTS (gimple_call_arg (s, i))
-            || TREE_THIS_VOLATILE (gimple_call_arg (s, i)))
-          return true;
-
-      return false;
-    }
-  else if (is_gimple_assign (s))
-    {
-      /* Skip the first operand, the LHS. */
-      for (i = 1; i < gimple_num_ops (s); i++)
-       if (TREE_SIDE_EFFECTS (gimple_op (s, i))
-            || TREE_THIS_VOLATILE (gimple_op (s, i)))
-         {
-           gcc_assert (gimple_has_volatile_ops (s));
-           return true;
-         }
-    }
-  else if (is_gimple_debug (s))
-    return false;
-  else
-    {
-      /* For statements without an LHS, examine all arguments.  */
-      for (i = 0; i < gimple_num_ops (s); i++)
-       if (TREE_SIDE_EFFECTS (gimple_op (s, i))
-            || TREE_THIS_VOLATILE (gimple_op (s, i)))
-         {
-           gcc_assert (gimple_has_volatile_ops (s));
-           return true;
-         }
-    }
-
-  return false;
-}
-
 /* Helper for gimple_could_trap_p and gimple_assign_rhs_could_trap_p.
    Return true if S can trap.  When INCLUDE_MEM is true, check whether
    the memory operations could trap.  When INCLUDE_STORES is true and
@@ -2571,7 +1924,7 @@ gimple_could_trap_p_1 (gimple s, bool include_mem, bool include_stores)
   switch (gimple_code (s))
     {
     case GIMPLE_ASM:
-      return gimple_asm_volatile_p (s);
+      return gimple_asm_volatile_p (as_a <gasm *> (s));
 
     case GIMPLE_CALL:
       t = gimple_call_fndecl (s);
@@ -2620,9 +1973,14 @@ gimple_assign_rhs_could_trap_p (gimple s)
 void
 dump_gimple_statistics (void)
 {
-#ifdef GATHER_STATISTICS
   int i, total_tuples = 0, total_bytes = 0;
 
+  if (! GATHER_STATISTICS)
+    {
+      fprintf (stderr, "No gimple statistics\n");
+      return;
+    }
+
   fprintf (stderr, "\nGIMPLE statements\n");
   fprintf (stderr, "Kind                   Stmts      Bytes\n");
   fprintf (stderr, "---------------------------------------\n");
@@ -2636,9 +1994,6 @@ dump_gimple_statistics (void)
   fprintf (stderr, "---------------------------------------\n");
   fprintf (stderr, "%-20s %7d %10d\n", "Total", total_tuples, total_bytes);
   fprintf (stderr, "---------------------------------------\n");
-#else
-  fprintf (stderr, "No gimple statistics\n");
-#endif
 }
 
 
@@ -2676,6 +2031,7 @@ get_gimple_rhs_num_ops (enum tree_code code)
       || (SYM) == WIDEN_MULT_PLUS_EXPR                                     \
       || (SYM) == WIDEN_MULT_MINUS_EXPR                                            \
       || (SYM) == DOT_PROD_EXPR                                                    \
+      || (SYM) == SAD_EXPR                                                 \
       || (SYM) == REALIGN_LOAD_EXPR                                        \
       || (SYM) == VEC_COND_EXPR                                                    \
       || (SYM) == VEC_PERM_EXPR                                             \
@@ -2696,716 +2052,95 @@ const unsigned char gimple_rhs_class_table[] = {
 #undef DEFTREECODE
 #undef END_OF_BASE_TREE_CODES
 
-/* For the definitive definition of GIMPLE, see doc/tree-ssa.texi.  */
-
-/* Validation of GIMPLE expressions.  */
-
-/* Returns true iff T is a valid RHS for an assignment to a renamed
-   user -- or front-end generated artificial -- variable.  */
-
-bool
-is_gimple_reg_rhs (tree t)
-{
-  return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
-}
-
-/* Returns true iff T is a valid RHS for an assignment to an un-renamed
-   LHS, or for a call argument.  */
-
-bool
-is_gimple_mem_rhs (tree t)
-{
-  /* If we're dealing with a renamable type, either source or dest must be
-     a renamed variable.  */
-  if (is_gimple_reg_type (TREE_TYPE (t)))
-    return is_gimple_val (t);
-  else
-    return is_gimple_val (t) || is_gimple_lvalue (t);
-}
-
-/*  Return true if T is a valid LHS for a GIMPLE assignment expression.  */
-
-bool
-is_gimple_lvalue (tree t)
-{
-  return (is_gimple_addressable (t)
-         || TREE_CODE (t) == WITH_SIZE_EXPR
-         /* These are complex lvalues, but don't have addresses, so they
-            go here.  */
-         || TREE_CODE (t) == BIT_FIELD_REF);
-}
-
-/*  Return true if T is a GIMPLE condition.  */
-
-bool
-is_gimple_condexpr (tree t)
-{
-  return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
-                               && !tree_could_throw_p (t)
-                               && is_gimple_val (TREE_OPERAND (t, 0))
-                               && is_gimple_val (TREE_OPERAND (t, 1))));
-}
-
-/*  Return true if T is something whose address can be taken.  */
-
-bool
-is_gimple_addressable (tree t)
-{
-  return (is_gimple_id (t) || handled_component_p (t)
-         || TREE_CODE (t) == MEM_REF);
-}
-
-/* Return true if T is a valid gimple constant.  */
-
-bool
-is_gimple_constant (const_tree t)
-{
-  switch (TREE_CODE (t))
-    {
-    case INTEGER_CST:
-    case REAL_CST:
-    case FIXED_CST:
-    case STRING_CST:
-    case COMPLEX_CST:
-    case VECTOR_CST:
-      return true;
-
-    /* Vector constant constructors are gimple invariant.  */
-    case CONSTRUCTOR:
-      if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-       return TREE_CONSTANT (t);
-      else
-       return false;
-
-    default:
-      return false;
-    }
-}
-
-/* Return true if T is a gimple address.  */
+/* Canonicalize a tree T for use in a COND_EXPR as conditional.  Returns
+   a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
+   we failed to create one.  */
 
-bool
-is_gimple_address (const_tree t)
+tree
+canonicalize_cond_expr_cond (tree t)
 {
-  tree op;
-
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return false;
-
-  op = TREE_OPERAND (t, 0);
-  while (handled_component_p (op))
-    {
-      if ((TREE_CODE (op) == ARRAY_REF
-          || TREE_CODE (op) == ARRAY_RANGE_REF)
-         && !is_gimple_val (TREE_OPERAND (op, 1)))
-           return false;
-
-      op = TREE_OPERAND (op, 0);
-    }
-
-  if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
-    return true;
+  /* Strip conversions around boolean operations.  */
+  if (CONVERT_EXPR_P (t)
+      && (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
+          || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
+            == BOOLEAN_TYPE))
+    t = TREE_OPERAND (t, 0);
 
-  switch (TREE_CODE (op))
+  /* For !x use x == 0.  */
+  if (TREE_CODE (t) == TRUTH_NOT_EXPR)
     {
-    case PARM_DECL:
-    case RESULT_DECL:
-    case LABEL_DECL:
-    case FUNCTION_DECL:
-    case VAR_DECL:
-    case CONST_DECL:
-      return true;
-
-    default:
-      return false;
+      tree top0 = TREE_OPERAND (t, 0);
+      t = build2 (EQ_EXPR, TREE_TYPE (t),
+                 top0, build_int_cst (TREE_TYPE (top0), 0));
     }
-}
-
-/* Return true if T is a gimple invariant address.  */
-
-bool
-is_gimple_invariant_address (const_tree t)
-{
-  const_tree op;
-
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return false;
-
-  op = strip_invariant_refs (TREE_OPERAND (t, 0));
-  if (!op)
-    return false;
-
-  if (TREE_CODE (op) == MEM_REF)
+  /* For cmp ? 1 : 0 use cmp.  */
+  else if (TREE_CODE (t) == COND_EXPR
+          && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
+          && integer_onep (TREE_OPERAND (t, 1))
+          && integer_zerop (TREE_OPERAND (t, 2)))
     {
-      const_tree op0 = TREE_OPERAND (op, 0);
-      return (TREE_CODE (op0) == ADDR_EXPR
-             && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
-                 || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
+      tree top0 = TREE_OPERAND (t, 0);
+      t = build2 (TREE_CODE (top0), TREE_TYPE (t),
+                 TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
     }
+  /* For x ^ y use x != y.  */
+  else if (TREE_CODE (t) == BIT_XOR_EXPR)
+    t = build2 (NE_EXPR, TREE_TYPE (t),
+               TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+  
+  if (is_gimple_condexpr (t))
+    return t;
 
-  return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+  return NULL_TREE;
 }
 
-/* Return true if T is a gimple invariant address at IPA level
-   (so addresses of variables on stack are not allowed).  */
+/* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
+   the positions marked by the set ARGS_TO_SKIP.  */
 
-bool
-is_gimple_ip_invariant_address (const_tree t)
+gcall *
+gimple_call_copy_skip_args (gcall *stmt, bitmap args_to_skip)
 {
-  const_tree op;
+  int i;
+  int nargs = gimple_call_num_args (stmt);
+  auto_vec<tree> vargs (nargs);
+  gcall *new_stmt;
 
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return false;
+  for (i = 0; i < nargs; i++)
+    if (!bitmap_bit_p (args_to_skip, i))
+      vargs.quick_push (gimple_call_arg (stmt, i));
 
-  op = strip_invariant_refs (TREE_OPERAND (t, 0));
-  if (!op)
-    return false;
+  if (gimple_call_internal_p (stmt))
+    new_stmt = gimple_build_call_internal_vec (gimple_call_internal_fn (stmt),
+                                              vargs);
+  else
+    new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
 
-  if (TREE_CODE (op) == MEM_REF)
-    {
-      const_tree op0 = TREE_OPERAND (op, 0);
-      return (TREE_CODE (op0) == ADDR_EXPR
-             && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
-                 || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
-    }
+  if (gimple_call_lhs (stmt))
+    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
 
-  return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
-}
+  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+  gimple_set_vdef (new_stmt, gimple_vdef (stmt));
 
-/* Return true if T is a GIMPLE minimal invariant.  It's a restricted
-   form of function invariant.  */
+  if (gimple_has_location (stmt))
+    gimple_set_location (new_stmt, gimple_location (stmt));
+  gimple_call_copy_flags (new_stmt, stmt);
+  gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
 
-bool
-is_gimple_min_invariant (const_tree t)
-{
-  if (TREE_CODE (t) == ADDR_EXPR)
-    return is_gimple_invariant_address (t);
+  gimple_set_modified (new_stmt, true);
 
-  return is_gimple_constant (t);
+  return new_stmt;
 }
 
-/* Return true if T is a GIMPLE interprocedural invariant.  It's a restricted
-   form of gimple minimal invariant.  */
 
-bool
-is_gimple_ip_invariant (const_tree t)
-{
-  if (TREE_CODE (t) == ADDR_EXPR)
-    return is_gimple_ip_invariant_address (t);
 
-  return is_gimple_constant (t);
-}
+/* Return true if the field decls F1 and F2 are at the same offset.
 
-/* Return true if T looks like a valid GIMPLE statement.  */
+   This is intended to be used on GIMPLE types only.  */
 
 bool
-is_gimple_stmt (tree t)
+gimple_compare_field_offset (tree f1, tree f2)
 {
-  const enum tree_code code = TREE_CODE (t);
-
-  switch (code)
-    {
-    case NOP_EXPR:
-      /* The only valid NOP_EXPR is the empty statement.  */
-      return IS_EMPTY_STMT (t);
-
-    case BIND_EXPR:
-    case COND_EXPR:
-      /* These are only valid if they're void.  */
-      return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
-
-    case SWITCH_EXPR:
-    case GOTO_EXPR:
-    case RETURN_EXPR:
-    case LABEL_EXPR:
-    case CASE_LABEL_EXPR:
-    case TRY_CATCH_EXPR:
-    case TRY_FINALLY_EXPR:
-    case EH_FILTER_EXPR:
-    case CATCH_EXPR:
-    case ASM_EXPR:
-    case STATEMENT_LIST:
-    case OMP_PARALLEL:
-    case OMP_FOR:
-    case OMP_SECTIONS:
-    case OMP_SECTION:
-    case OMP_SINGLE:
-    case OMP_MASTER:
-    case OMP_ORDERED:
-    case OMP_CRITICAL:
-    case OMP_TASK:
-      /* These are always void.  */
-      return true;
-
-    case CALL_EXPR:
-    case MODIFY_EXPR:
-    case PREDICT_EXPR:
-      /* These are valid regardless of their type.  */
-      return true;
-
-    default:
-      return false;
-    }
-}
-
-/* Return true if T is a variable.  */
-
-bool
-is_gimple_variable (tree t)
-{
-  return (TREE_CODE (t) == VAR_DECL
-         || TREE_CODE (t) == PARM_DECL
-         || TREE_CODE (t) == RESULT_DECL
-         || TREE_CODE (t) == SSA_NAME);
-}
-
-/*  Return true if T is a GIMPLE identifier (something with an address).  */
-
-bool
-is_gimple_id (tree t)
-{
-  return (is_gimple_variable (t)
-         || TREE_CODE (t) == FUNCTION_DECL
-         || TREE_CODE (t) == LABEL_DECL
-         || TREE_CODE (t) == CONST_DECL
-         /* Allow string constants, since they are addressable.  */
-         || TREE_CODE (t) == STRING_CST);
-}
-
-/* Return true if TYPE is a suitable type for a scalar register variable.  */
-
-bool
-is_gimple_reg_type (tree type)
-{
-  return !AGGREGATE_TYPE_P (type);
-}
-
-/* Return true if T is a non-aggregate register variable.  */
-
-bool
-is_gimple_reg (tree t)
-{
-  if (TREE_CODE (t) == SSA_NAME)
-    t = SSA_NAME_VAR (t);
-
-  if (!is_gimple_variable (t))
-    return false;
-
-  if (!is_gimple_reg_type (TREE_TYPE (t)))
-    return false;
-
-  /* A volatile decl is not acceptable because we can't reuse it as
-     needed.  We need to copy it into a temp first.  */
-  if (TREE_THIS_VOLATILE (t))
-    return false;
-
-  /* We define "registers" as things that can be renamed as needed,
-     which with our infrastructure does not apply to memory.  */
-  if (needs_to_live_in_memory (t))
-    return false;
-
-  /* Hard register variables are an interesting case.  For those that
-     are call-clobbered, we don't know where all the calls are, since
-     we don't (want to) take into account which operations will turn
-     into libcalls at the rtl level.  For those that are call-saved,
-     we don't currently model the fact that calls may in fact change
-     global hard registers, nor do we examine ASM_CLOBBERS at the tree
-     level, and so miss variable changes that might imply.  All around,
-     it seems safest to not do too much optimization with these at the
-     tree level at all.  We'll have to rely on the rtl optimizers to
-     clean this up, as there we've got all the appropriate bits exposed.  */
-  if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
-    return false;
-
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
-  return true;
-}
-
-
-/* Return true if T is a GIMPLE variable whose address is not needed.  */
-
-bool
-is_gimple_non_addressable (tree t)
-{
-  if (TREE_CODE (t) == SSA_NAME)
-    t = SSA_NAME_VAR (t);
-
-  return (is_gimple_variable (t) && ! needs_to_live_in_memory (t));
-}
-
-/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant.  */
-
-bool
-is_gimple_val (tree t)
-{
-  /* Make loads from volatiles and memory vars explicit.  */
-  if (is_gimple_variable (t)
-      && is_gimple_reg_type (TREE_TYPE (t))
-      && !is_gimple_reg (t))
-    return false;
-
-  return (is_gimple_variable (t) || is_gimple_min_invariant (t));
-}
-
-/* Similarly, but accept hard registers as inputs to asm statements.  */
-
-bool
-is_gimple_asm_val (tree t)
-{
-  if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
-    return true;
-
-  return is_gimple_val (t);
-}
-
-/* Return true if T is a GIMPLE minimal lvalue.  */
-
-bool
-is_gimple_min_lval (tree t)
-{
-  if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
-    return false;
-  return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
-}
-
-/* Return true if T is a valid function operand of a CALL_EXPR.  */
-
-bool
-is_gimple_call_addr (tree t)
-{
-  return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
-}
-
-/* Return true if T is a valid address operand of a MEM_REF.  */
-
-bool
-is_gimple_mem_ref_addr (tree t)
-{
-  return (is_gimple_reg (t)
-         || TREE_CODE (t) == INTEGER_CST
-         || (TREE_CODE (t) == ADDR_EXPR
-             && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
-                 || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
-}
-
-
-/* Given a memory reference expression T, return its base address.
-   The base address of a memory reference expression is the main
-   object being referenced.  For instance, the base address for
-   'array[i].fld[j]' is 'array'.  You can think of this as stripping
-   away the offset part from a memory address.
-
-   This function calls handled_component_p to strip away all the inner
-   parts of the memory reference until it reaches the base object.  */
-
-tree
-get_base_address (tree t)
-{
-  while (handled_component_p (t))
-    t = TREE_OPERAND (t, 0);
-
-  if ((TREE_CODE (t) == MEM_REF
-       || TREE_CODE (t) == TARGET_MEM_REF)
-      && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
-    t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
-
-  if (TREE_CODE (t) == SSA_NAME
-      || DECL_P (t)
-      || TREE_CODE (t) == STRING_CST
-      || TREE_CODE (t) == CONSTRUCTOR
-      || INDIRECT_REF_P (t)
-      || TREE_CODE (t) == MEM_REF
-      || TREE_CODE (t) == TARGET_MEM_REF)
-    return t;
-  else
-    return NULL_TREE;
-}
-
-void
-recalculate_side_effects (tree t)
-{
-  enum tree_code code = TREE_CODE (t);
-  int len = TREE_OPERAND_LENGTH (t);
-  int i;
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    case tcc_expression:
-      switch (code)
-       {
-       case INIT_EXPR:
-       case MODIFY_EXPR:
-       case VA_ARG_EXPR:
-       case PREDECREMENT_EXPR:
-       case PREINCREMENT_EXPR:
-       case POSTDECREMENT_EXPR:
-       case POSTINCREMENT_EXPR:
-         /* All of these have side-effects, no matter what their
-            operands are.  */
-         return;
-
-       default:
-         break;
-       }
-      /* Fall through.  */
-
-    case tcc_comparison:  /* a comparison expression */
-    case tcc_unary:       /* a unary arithmetic expression */
-    case tcc_binary:      /* a binary arithmetic expression */
-    case tcc_reference:   /* a reference */
-    case tcc_vl_exp:        /* a function call */
-      TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
-      for (i = 0; i < len; ++i)
-       {
-         tree op = TREE_OPERAND (t, i);
-         if (op && TREE_SIDE_EFFECTS (op))
-           TREE_SIDE_EFFECTS (t) = 1;
-       }
-      break;
-
-    case tcc_constant:
-      /* No side-effects.  */
-      return;
-
-    default:
-      gcc_unreachable ();
-   }
-}
-
-/* Canonicalize a tree T for use in a COND_EXPR as conditional.  Returns
-   a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
-   we failed to create one.  */
-
-tree
-canonicalize_cond_expr_cond (tree t)
-{
-  /* Strip conversions around boolean operations.  */
-  if (CONVERT_EXPR_P (t)
-      && (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
-          || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
-            == BOOLEAN_TYPE))
-    t = TREE_OPERAND (t, 0);
-
-  /* For !x use x == 0.  */
-  if (TREE_CODE (t) == TRUTH_NOT_EXPR)
-    {
-      tree top0 = TREE_OPERAND (t, 0);
-      t = build2 (EQ_EXPR, TREE_TYPE (t),
-                 top0, build_int_cst (TREE_TYPE (top0), 0));
-    }
-  /* For cmp ? 1 : 0 use cmp.  */
-  else if (TREE_CODE (t) == COND_EXPR
-          && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
-          && integer_onep (TREE_OPERAND (t, 1))
-          && integer_zerop (TREE_OPERAND (t, 2)))
-    {
-      tree top0 = TREE_OPERAND (t, 0);
-      t = build2 (TREE_CODE (top0), TREE_TYPE (t),
-                 TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
-    }
-
-  if (is_gimple_condexpr (t))
-    return t;
-
-  return NULL_TREE;
-}
-
-/* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
-   the positions marked by the set ARGS_TO_SKIP.  */
-
-gimple
-gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
-{
-  int i;
-  int nargs = gimple_call_num_args (stmt);
-  VEC(tree, heap) *vargs = VEC_alloc (tree, heap, nargs);
-  gimple new_stmt;
-
-  for (i = 0; i < nargs; i++)
-    if (!bitmap_bit_p (args_to_skip, i))
-      VEC_quick_push (tree, vargs, gimple_call_arg (stmt, i));
-
-  if (gimple_call_internal_p (stmt))
-    new_stmt = gimple_build_call_internal_vec (gimple_call_internal_fn (stmt),
-                                              vargs);
-  else
-    new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
-  VEC_free (tree, heap, vargs);
-  if (gimple_call_lhs (stmt))
-    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
-
-  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
-  gimple_set_vdef (new_stmt, gimple_vdef (stmt));
-
-  gimple_set_block (new_stmt, gimple_block (stmt));
-  if (gimple_has_location (stmt))
-    gimple_set_location (new_stmt, gimple_location (stmt));
-  gimple_call_copy_flags (new_stmt, stmt);
-  gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
-
-  gimple_set_modified (new_stmt, true);
-
-  return new_stmt;
-}
-
-
-enum gtc_mode { GTC_MERGE = 0, GTC_DIAG = 1 };
-
-static hashval_t gimple_type_hash (const void *);
-
-/* Structure used to maintain a cache of some type pairs compared by
-   gimple_types_compatible_p when comparing aggregate types.  There are
-   three possible values for SAME_P:
-
-       -2: The pair (T1, T2) has just been inserted in the table.
-        0: T1 and T2 are different types.
-        1: T1 and T2 are the same type.
-
-   The two elements in the SAME_P array are indexed by the comparison
-   mode gtc_mode.  */
-
-struct type_pair_d
-{
-  unsigned int uid1;
-  unsigned int uid2;
-  signed char same_p[2];
-};
-typedef struct type_pair_d *type_pair_t;
-DEF_VEC_P(type_pair_t);
-DEF_VEC_ALLOC_P(type_pair_t,heap);
-
-#define GIMPLE_TYPE_PAIR_SIZE 16381
-struct type_pair_d *type_pair_cache;
-
-
-/* Lookup the pair of types T1 and T2 in *VISITED_P.  Insert a new
-   entry if none existed.  */
-
-static inline type_pair_t
-lookup_type_pair (tree t1, tree t2)
-{
-  unsigned int index;
-  unsigned int uid1, uid2;
-
-  if (type_pair_cache == NULL)
-    type_pair_cache = XCNEWVEC (struct type_pair_d, GIMPLE_TYPE_PAIR_SIZE);
-
-  if (TYPE_UID (t1) < TYPE_UID (t2))
-    {
-      uid1 = TYPE_UID (t1);
-      uid2 = TYPE_UID (t2);
-    }
-  else
-    {
-      uid1 = TYPE_UID (t2);
-      uid2 = TYPE_UID (t1);
-    }
-  gcc_checking_assert (uid1 != uid2);
-
-  /* iterative_hash_hashval_t imply an function calls.
-     We know that UIDS are in limited range.  */
-  index = ((((unsigned HOST_WIDE_INT)uid1 << HOST_BITS_PER_WIDE_INT / 2) + uid2)
-          % GIMPLE_TYPE_PAIR_SIZE);
-  if (type_pair_cache [index].uid1 == uid1
-      && type_pair_cache [index].uid2 == uid2)
-    return &type_pair_cache[index];
-
-  type_pair_cache [index].uid1 = uid1;
-  type_pair_cache [index].uid2 = uid2;
-  type_pair_cache [index].same_p[0] = -2;
-  type_pair_cache [index].same_p[1] = -2;
-
-  return &type_pair_cache[index];
-}
-
-/* Per pointer state for the SCC finding.  The on_sccstack flag
-   is not strictly required, it is true when there is no hash value
-   recorded for the type and false otherwise.  But querying that
-   is slower.  */
-
-struct sccs
-{
-  unsigned int dfsnum;
-  unsigned int low;
-  bool on_sccstack;
-  union {
-    hashval_t hash;
-    signed char same_p;
-  } u;
-};
-
-static unsigned int next_dfs_num;
-static unsigned int gtc_next_dfs_num;
-
-
-/* GIMPLE type merging cache.  A direct-mapped cache based on TYPE_UID.  */
-
-typedef struct GTY(()) gimple_type_leader_entry_s {
-  tree type;
-  tree leader;
-} gimple_type_leader_entry;
-
-#define GIMPLE_TYPE_LEADER_SIZE 16381
-static GTY((deletable, length("GIMPLE_TYPE_LEADER_SIZE")))
-  gimple_type_leader_entry *gimple_type_leader;
-
-/* Lookup an existing leader for T and return it or NULL_TREE, if
-   there is none in the cache.  */
-
-static inline tree
-gimple_lookup_type_leader (tree t)
-{
-  gimple_type_leader_entry *leader;
-
-  if (!gimple_type_leader)
-    return NULL_TREE;
-
-  leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE];
-  if (leader->type != t)
-    return NULL_TREE;
-
-  return leader->leader;
-}
-
-/* Return true if T1 and T2 have the same name.  If FOR_COMPLETION_P is
-   true then if any type has no name return false, otherwise return
-   true if both types have no names.  */
-
-static bool
-compare_type_names_p (tree t1, tree t2)
-{
-  tree name1 = TYPE_NAME (t1);
-  tree name2 = TYPE_NAME (t2);
-
-  if (name1 && TREE_CODE (name1) == TYPE_DECL)
-    name1 = DECL_NAME (name1);
-  gcc_checking_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE);
-
-  if (name2 && TREE_CODE (name2) == TYPE_DECL)
-    name2 = DECL_NAME (name2);
-  gcc_checking_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE);
-
-  /* Identifiers can be compared with pointer equality rather
-     than a string comparison.  */
-  if (name1 == name2)
-    return true;
-
-  return false;
-}
-
-/* Return true if the field decls F1 and F2 are at the same offset.
-
-   This is intended to be used on GIMPLE types only.  */
-
-bool
-gimple_compare_field_offset (tree f1, tree f2)
-{
-  if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2))
+  if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2))
     {
       tree offset1 = DECL_FIELD_OFFSET (f1);
       tree offset2 = DECL_FIELD_OFFSET (f2);
@@ -3418,1492 +2153,35 @@ gimple_compare_field_offset (tree f1, tree f2)
               || (TREE_CODE (offset1) == PLACEHOLDER_EXPR
                   && TREE_CODE (offset2) == PLACEHOLDER_EXPR
                   && (DECL_SIZE (f1) == DECL_SIZE (f2)
-                      || (TREE_CODE (DECL_SIZE (f1)) == PLACEHOLDER_EXPR
-                          && TREE_CODE (DECL_SIZE (f2)) == PLACEHOLDER_EXPR)
-                      || operand_equal_p (DECL_SIZE (f1), DECL_SIZE (f2), 0))
-                  && DECL_ALIGN (f1) == DECL_ALIGN (f2))
-              || operand_equal_p (offset1, offset2, 0))
-             && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1),
-                                    DECL_FIELD_BIT_OFFSET (f2)));
-    }
-
-  /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN
-     should be, so handle differing ones specially by decomposing
-     the offset into a byte and bit offset manually.  */
-  if (host_integerp (DECL_FIELD_OFFSET (f1), 0)
-      && host_integerp (DECL_FIELD_OFFSET (f2), 0))
-    {
-      unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
-      unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
-      bit_offset1 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f1));
-      byte_offset1 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f1))
-                     + bit_offset1 / BITS_PER_UNIT);
-      bit_offset2 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f2));
-      byte_offset2 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f2))
-                     + bit_offset2 / BITS_PER_UNIT);
-      if (byte_offset1 != byte_offset2)
-       return false;
-      return bit_offset1 % BITS_PER_UNIT == bit_offset2 % BITS_PER_UNIT;
-    }
-
-  return false;
-}
-
-static bool
-gimple_types_compatible_p_1 (tree, tree, type_pair_t,
-                            VEC(type_pair_t, heap) **,
-                            struct pointer_map_t *, struct obstack *);
-
-/* DFS visit the edge from the callers type pair with state *STATE to
-   the pair T1, T2 while operating in FOR_MERGING_P mode.
-   Update the merging status if it is not part of the SCC containing the
-   callers pair and return it.
-   SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.  */
-
-static bool
-gtc_visit (tree t1, tree t2,
-          struct sccs *state,
-          VEC(type_pair_t, heap) **sccstack,
-          struct pointer_map_t *sccstate,
-          struct obstack *sccstate_obstack)
-{
-  struct sccs *cstate = NULL;
-  type_pair_t p;
-  void **slot;
-  tree leader1, leader2;
-
-  /* Check first for the obvious case of pointer identity.  */
-  if (t1 == t2)
-    return true;
-
-  /* Check that we have two types to compare.  */
-  if (t1 == NULL_TREE || t2 == NULL_TREE)
-    return false;
-
-  /* Can't be the same type if the types don't have the same code.  */
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return false;
-
-  /* Can't be the same type if they have different CV qualifiers.  */
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
-    return false;
-
-  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
-    return false;
-
-  /* Void types and nullptr types are always the same.  */
-  if (TREE_CODE (t1) == VOID_TYPE
-      || TREE_CODE (t1) == NULLPTR_TYPE)
-    return true;
-
-  /* Can't be the same type if they have different alignment or mode.  */
-  if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-      || TYPE_MODE (t1) != TYPE_MODE (t2))
-    return false;
-
-  /* Do some simple checks before doing three hashtable queries.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1)
-      || TREE_CODE (t1) == VECTOR_TYPE
-      || TREE_CODE (t1) == COMPLEX_TYPE
-      || TREE_CODE (t1) == OFFSET_TYPE
-      || POINTER_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different sign or precision.  */
-      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-       return false;
-
-      if (TREE_CODE (t1) == INTEGER_TYPE
-         && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
-             || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
-       return false;
-
-      /* That's all we need to check for float and fixed-point types.  */
-      if (SCALAR_FLOAT_TYPE_P (t1)
-         || FIXED_POINT_TYPE_P (t1))
-       return true;
-
-      /* For other types fall thru to more complex checks.  */
-    }
-
-  /* If the types have been previously registered and found equal
-     they still are.  */
-  leader1 = gimple_lookup_type_leader (t1);
-  leader2 = gimple_lookup_type_leader (t2);
-  if (leader1 == t2
-      || t1 == leader2
-      || (leader1 && leader1 == leader2))
-    return true;
-
-  /* If the hash values of t1 and t2 are different the types can't
-     possibly be the same.  This helps keeping the type-pair hashtable
-     small, only tracking comparisons for hash collisions.  */
-  if (gimple_type_hash (t1) != gimple_type_hash (t2))
-    return false;
-
-  /* Allocate a new cache entry for this comparison.  */
-  p = lookup_type_pair (t1, t2);
-  if (p->same_p[GTC_MERGE] == 0 || p->same_p[GTC_MERGE] == 1)
-    {
-      /* We have already decided whether T1 and T2 are the
-        same, return the cached result.  */
-      return p->same_p[GTC_MERGE] == 1;
-    }
-
-  if ((slot = pointer_map_contains (sccstate, p)) != NULL)
-    cstate = (struct sccs *)*slot;
-  /* Not yet visited.  DFS recurse.  */
-  if (!cstate)
-    {
-      gimple_types_compatible_p_1 (t1, t2, p,
-                                  sccstack, sccstate, sccstate_obstack);
-      cstate = (struct sccs *)* pointer_map_contains (sccstate, p);
-      state->low = MIN (state->low, cstate->low);
-    }
-  /* If the type is still on the SCC stack adjust the parents low.  */
-  if (cstate->dfsnum < state->dfsnum
-      && cstate->on_sccstack)
-    state->low = MIN (cstate->dfsnum, state->low);
-
-  /* Return the current lattice value.  We start with an equality
-     assumption so types part of a SCC will be optimistically
-     treated equal unless proven otherwise.  */
-  return cstate->u.same_p;
-}
-
-/* Worker for gimple_types_compatible.
-   SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.  */
-
-static bool
-gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
-                            VEC(type_pair_t, heap) **sccstack,
-                            struct pointer_map_t *sccstate,
-                            struct obstack *sccstate_obstack)
-{
-  struct sccs *state;
-
-  gcc_assert (p->same_p[GTC_MERGE] == -2);
-
-  state = XOBNEW (sccstate_obstack, struct sccs);
-  *pointer_map_insert (sccstate, p) = state;
-
-  VEC_safe_push (type_pair_t, heap, *sccstack, p);
-  state->dfsnum = gtc_next_dfs_num++;
-  state->low = state->dfsnum;
-  state->on_sccstack = true;
-  /* Start with an equality assumption.  As we DFS recurse into child
-     SCCs this assumption may get revisited.  */
-  state->u.same_p = 1;
-
-  /* The struct tags shall compare equal.  */
-  if (!compare_type_names_p (t1, t2))
-    goto different_types;
-
-  /* If their attributes are not the same they can't be the same type.  */
-  if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
-    goto different_types;
-
-  /* Do type-specific comparisons.  */
-  switch (TREE_CODE (t1))
-    {
-    case VECTOR_TYPE:
-    case COMPLEX_TYPE:
-      if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
-                     state, sccstack, sccstate, sccstate_obstack))
-       goto different_types;
-      goto same_types;
-
-    case ARRAY_TYPE:
-      /* Array types are the same if the element types are the same and
-        the number of elements are the same.  */
-      if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
-                     state, sccstack, sccstate, sccstate_obstack)
-         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
-         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
-       goto different_types;
-      else
-       {
-         tree i1 = TYPE_DOMAIN (t1);
-         tree i2 = TYPE_DOMAIN (t2);
-
-         /* For an incomplete external array, the type domain can be
-            NULL_TREE.  Check this condition also.  */
-         if (i1 == NULL_TREE && i2 == NULL_TREE)
-           goto same_types;
-         else if (i1 == NULL_TREE || i2 == NULL_TREE)
-           goto different_types;
-         /* If for a complete array type the possibly gimplified sizes
-            are different the types are different.  */
-         else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
-                  || (TYPE_SIZE (i1)
-                      && TYPE_SIZE (i2)
-                      && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
-           goto different_types;
-         else
-           {
-             tree min1 = TYPE_MIN_VALUE (i1);
-             tree min2 = TYPE_MIN_VALUE (i2);
-             tree max1 = TYPE_MAX_VALUE (i1);
-             tree max2 = TYPE_MAX_VALUE (i2);
-
-             /* The minimum/maximum values have to be the same.  */
-             if ((min1 == min2
-                  || (min1 && min2
-                      && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
-                           && TREE_CODE (min2) == PLACEHOLDER_EXPR)
-                          || operand_equal_p (min1, min2, 0))))
-                 && (max1 == max2
-                     || (max1 && max2
-                         && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
-                              && TREE_CODE (max2) == PLACEHOLDER_EXPR)
-                             || operand_equal_p (max1, max2, 0)))))
-               goto same_types;
-             else
-               goto different_types;
-           }
-       }
-
-    case METHOD_TYPE:
-      /* Method types should belong to the same class.  */
-      if (!gtc_visit (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2),
-                     state, sccstack, sccstate, sccstate_obstack))
-       goto different_types;
-
-      /* Fallthru  */
-
-    case FUNCTION_TYPE:
-      /* Function types are the same if the return type and arguments types
-        are the same.  */
-      if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
-                     state, sccstack, sccstate, sccstate_obstack))
-       goto different_types;
-
-      if (!comp_type_attributes (t1, t2))
-       goto different_types;
-
-      if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
-       goto same_types;
-      else
-       {
-         tree parms1, parms2;
-
-         for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
-              parms1 && parms2;
-              parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
-           {
-             if (!gtc_visit (TREE_VALUE (parms1), TREE_VALUE (parms2),
-                             state, sccstack, sccstate, sccstate_obstack))
-               goto different_types;
-           }
-
-         if (parms1 || parms2)
-           goto different_types;
-
-         goto same_types;
-       }
-
-    case OFFSET_TYPE:
-      {
-       if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
-                       state, sccstack, sccstate, sccstate_obstack)
-           || !gtc_visit (TYPE_OFFSET_BASETYPE (t1),
-                          TYPE_OFFSET_BASETYPE (t2),
-                          state, sccstack, sccstate, sccstate_obstack))
-         goto different_types;
-
-       goto same_types;
-      }
-
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-      {
-       /* If the two pointers have different ref-all attributes,
-          they can't be the same type.  */
-       if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
-         goto different_types;
-
-       /* Otherwise, pointer and reference types are the same if the
-          pointed-to types are the same.  */
-       if (gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
-                      state, sccstack, sccstate, sccstate_obstack))
-         goto same_types;
-
-       goto different_types;
-      }
-
-    case INTEGER_TYPE:
-    case BOOLEAN_TYPE:
-      {
-       tree min1 = TYPE_MIN_VALUE (t1);
-       tree max1 = TYPE_MAX_VALUE (t1);
-       tree min2 = TYPE_MIN_VALUE (t2);
-       tree max2 = TYPE_MAX_VALUE (t2);
-       bool min_equal_p = false;
-       bool max_equal_p = false;
-
-       /* If either type has a minimum value, the other type must
-          have the same.  */
-       if (min1 == NULL_TREE && min2 == NULL_TREE)
-         min_equal_p = true;
-       else if (min1 && min2 && operand_equal_p (min1, min2, 0))
-         min_equal_p = true;
-
-       /* Likewise, if either type has a maximum value, the other
-          type must have the same.  */
-       if (max1 == NULL_TREE && max2 == NULL_TREE)
-         max_equal_p = true;
-       else if (max1 && max2 && operand_equal_p (max1, max2, 0))
-         max_equal_p = true;
-
-       if (!min_equal_p || !max_equal_p)
-         goto different_types;
-
-       goto same_types;
-      }
-
-    case ENUMERAL_TYPE:
-      {
-       /* FIXME lto, we cannot check bounds on enumeral types because
-          different front ends will produce different values.
-          In C, enumeral types are integers, while in C++ each element
-          will have its own symbolic value.  We should decide how enums
-          are to be represented in GIMPLE and have each front end lower
-          to that.  */
-       tree v1, v2;
-
-       /* For enumeral types, all the values must be the same.  */
-       if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
-         goto same_types;
-
-       for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
-            v1 && v2;
-            v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
-         {
-           tree c1 = TREE_VALUE (v1);
-           tree c2 = TREE_VALUE (v2);
-
-           if (TREE_CODE (c1) == CONST_DECL)
-             c1 = DECL_INITIAL (c1);
-
-           if (TREE_CODE (c2) == CONST_DECL)
-             c2 = DECL_INITIAL (c2);
-
-           if (tree_int_cst_equal (c1, c2) != 1)
-             goto different_types;
-
-           if (TREE_PURPOSE (v1) != TREE_PURPOSE (v2))
-             goto different_types;
-         }
-
-       /* If one enumeration has more values than the other, they
-          are not the same.  */
-       if (v1 || v2)
-         goto different_types;
-
-       goto same_types;
-      }
-
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      {
-       tree f1, f2;
-
-       /* For aggregate types, all the fields must be the same.  */
-       for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
-            f1 && f2;
-            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-         {
-           /* Different field kinds are not compatible.  */
-           if (TREE_CODE (f1) != TREE_CODE (f2))
-             goto different_types;
-           /* Field decls must have the same name and offset.  */
-           if (TREE_CODE (f1) == FIELD_DECL
-               && (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
-                   || !gimple_compare_field_offset (f1, f2)))
-             goto different_types;
-           /* All entities should have the same name and type.  */
-           if (DECL_NAME (f1) != DECL_NAME (f2)
-               || !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2),
-                              state, sccstack, sccstate, sccstate_obstack))
-             goto different_types;
-         }
-
-       /* If one aggregate has more fields than the other, they
-          are not the same.  */
-       if (f1 || f2)
-         goto different_types;
-
-       goto same_types;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-
-  /* Common exit path for types that are not compatible.  */
-different_types:
-  state->u.same_p = 0;
-  goto pop;
-
-  /* Common exit path for types that are compatible.  */
-same_types:
-  gcc_assert (state->u.same_p == 1);
-
-pop:
-  if (state->low == state->dfsnum)
-    {
-      type_pair_t x;
-
-      /* Pop off the SCC and set its cache values to the final
-         comparison result.  */
-      do
-       {
-         struct sccs *cstate;
-         x = VEC_pop (type_pair_t, *sccstack);
-         cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
-         cstate->on_sccstack = false;
-         x->same_p[GTC_MERGE] = state->u.same_p;
-       }
-      while (x != p);
-    }
-
-  return state->u.same_p;
-}
-
-/* Return true iff T1 and T2 are structurally identical.  When
-   FOR_MERGING_P is true the an incomplete type and a complete type
-   are considered different, otherwise they are considered compatible.  */
-
-static bool
-gimple_types_compatible_p (tree t1, tree t2)
-{
-  VEC(type_pair_t, heap) *sccstack = NULL;
-  struct pointer_map_t *sccstate;
-  struct obstack sccstate_obstack;
-  type_pair_t p = NULL;
-  bool res;
-  tree leader1, leader2;
-
-  /* Before starting to set up the SCC machinery handle simple cases.  */
-
-  /* Check first for the obvious case of pointer identity.  */
-  if (t1 == t2)
-    return true;
-
-  /* Check that we have two types to compare.  */
-  if (t1 == NULL_TREE || t2 == NULL_TREE)
-    return false;
-
-  /* Can't be the same type if the types don't have the same code.  */
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return false;
-
-  /* Can't be the same type if they have different CV qualifiers.  */
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
-    return false;
-
-  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
-    return false;
-
-  /* Void types and nullptr types are always the same.  */
-  if (TREE_CODE (t1) == VOID_TYPE
-      || TREE_CODE (t1) == NULLPTR_TYPE)
-    return true;
-
-  /* Can't be the same type if they have different alignment or mode.  */
-  if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-      || TYPE_MODE (t1) != TYPE_MODE (t2))
-    return false;
-
-  /* Do some simple checks before doing three hashtable queries.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1)
-      || TREE_CODE (t1) == VECTOR_TYPE
-      || TREE_CODE (t1) == COMPLEX_TYPE
-      || TREE_CODE (t1) == OFFSET_TYPE
-      || POINTER_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different sign or precision.  */
-      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-       return false;
-
-      if (TREE_CODE (t1) == INTEGER_TYPE
-         && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
-             || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
-       return false;
-
-      /* That's all we need to check for float and fixed-point types.  */
-      if (SCALAR_FLOAT_TYPE_P (t1)
-         || FIXED_POINT_TYPE_P (t1))
-       return true;
-
-      /* For other types fall thru to more complex checks.  */
-    }
-
-  /* If the types have been previously registered and found equal
-     they still are.  */
-  leader1 = gimple_lookup_type_leader (t1);
-  leader2 = gimple_lookup_type_leader (t2);
-  if (leader1 == t2
-      || t1 == leader2
-      || (leader1 && leader1 == leader2))
-    return true;
-
-  /* If the hash values of t1 and t2 are different the types can't
-     possibly be the same.  This helps keeping the type-pair hashtable
-     small, only tracking comparisons for hash collisions.  */
-  if (gimple_type_hash (t1) != gimple_type_hash (t2))
-    return false;
-
-  /* If we've visited this type pair before (in the case of aggregates
-     with self-referential types), and we made a decision, return it.  */
-  p = lookup_type_pair (t1, t2);
-  if (p->same_p[GTC_MERGE] == 0 || p->same_p[GTC_MERGE] == 1)
-    {
-      /* We have already decided whether T1 and T2 are the
-        same, return the cached result.  */
-      return p->same_p[GTC_MERGE] == 1;
-    }
-
-  /* Now set up the SCC machinery for the comparison.  */
-  gtc_next_dfs_num = 1;
-  sccstate = pointer_map_create ();
-  gcc_obstack_init (&sccstate_obstack);
-  res = gimple_types_compatible_p_1 (t1, t2, p,
-                                    &sccstack, sccstate, &sccstate_obstack);
-  VEC_free (type_pair_t, heap, sccstack);
-  pointer_map_destroy (sccstate);
-  obstack_free (&sccstate_obstack, NULL);
-
-  return res;
-}
-
-
-static hashval_t
-iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **,
-                           struct pointer_map_t *, struct obstack *);
-
-/* DFS visit the edge from the callers type with state *STATE to T.
-   Update the callers type hash V with the hash for T if it is not part
-   of the SCC containing the callers type and return it.
-   SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.  */
-
-static hashval_t
-visit (tree t, struct sccs *state, hashval_t v,
-       VEC (tree, heap) **sccstack,
-       struct pointer_map_t *sccstate,
-       struct obstack *sccstate_obstack)
-{
-  struct sccs *cstate = NULL;
-  struct tree_int_map m;
-  void **slot;
-
-  /* If there is a hash value recorded for this type then it can't
-     possibly be part of our parent SCC.  Simply mix in its hash.  */
-  m.base.from = t;
-  if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
-      && *slot)
-    return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v);
-
-  if ((slot = pointer_map_contains (sccstate, t)) != NULL)
-    cstate = (struct sccs *)*slot;
-  if (!cstate)
-    {
-      hashval_t tem;
-      /* Not yet visited.  DFS recurse.  */
-      tem = iterative_hash_gimple_type (t, v,
-                                       sccstack, sccstate, sccstate_obstack);
-      if (!cstate)
-       cstate = (struct sccs *)* pointer_map_contains (sccstate, t);
-      state->low = MIN (state->low, cstate->low);
-      /* If the type is no longer on the SCC stack and thus is not part
-         of the parents SCC mix in its hash value.  Otherwise we will
-        ignore the type for hashing purposes and return the unaltered
-        hash value.  */
-      if (!cstate->on_sccstack)
-       return tem;
-    }
-  if (cstate->dfsnum < state->dfsnum
-      && cstate->on_sccstack)
-    state->low = MIN (cstate->dfsnum, state->low);
-
-  /* We are part of our parents SCC, skip this type during hashing
-     and return the unaltered hash value.  */
-  return v;
-}
-
-/* Hash NAME with the previous hash value V and return it.  */
-
-static hashval_t
-iterative_hash_name (tree name, hashval_t v)
-{
-  if (!name)
-    return v;
-  if (TREE_CODE (name) == TYPE_DECL)
-    name = DECL_NAME (name);
-  if (!name)
-    return v;
-  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-  return iterative_hash_object (IDENTIFIER_HASH_VALUE (name), v);
-}
-
-/* A type, hashvalue pair for sorting SCC members.  */
-
-struct type_hash_pair {
-  tree type;
-  hashval_t hash;
-};
-
-/* Compare two type, hashvalue pairs.  */
-
-static int
-type_hash_pair_compare (const void *p1_, const void *p2_)
-{
-  const struct type_hash_pair *p1 = (const struct type_hash_pair *) p1_;
-  const struct type_hash_pair *p2 = (const struct type_hash_pair *) p2_;
-  if (p1->hash < p2->hash)
-    return -1;
-  else if (p1->hash > p2->hash)
-    return 1;
-  return 0;
-}
-
-/* Returning a hash value for gimple type TYPE combined with VAL.
-   SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.
-
-   To hash a type we end up hashing in types that are reachable.
-   Through pointers we can end up with cycles which messes up the
-   required property that we need to compute the same hash value
-   for structurally equivalent types.  To avoid this we have to
-   hash all types in a cycle (the SCC) in a commutative way.  The
-   easiest way is to not mix in the hashes of the SCC members at
-   all.  To make this work we have to delay setting the hash
-   values of the SCC until it is complete.  */
-
-static hashval_t
-iterative_hash_gimple_type (tree type, hashval_t val,
-                           VEC(tree, heap) **sccstack,
-                           struct pointer_map_t *sccstate,
-                           struct obstack *sccstate_obstack)
-{
-  hashval_t v;
-  void **slot;
-  struct sccs *state;
-
-  /* Not visited during this DFS walk.  */
-  gcc_checking_assert (!pointer_map_contains (sccstate, type));
-  state = XOBNEW (sccstate_obstack, struct sccs);
-  *pointer_map_insert (sccstate, type) = state;
-
-  VEC_safe_push (tree, heap, *sccstack, type);
-  state->dfsnum = next_dfs_num++;
-  state->low = state->dfsnum;
-  state->on_sccstack = true;
-
-  /* Combine a few common features of types so that types are grouped into
-     smaller sets; when searching for existing matching types to merge,
-     only existing types having the same features as the new type will be
-     checked.  */
-  v = iterative_hash_name (TYPE_NAME (type), 0);
-  v = iterative_hash_hashval_t (TREE_CODE (type), v);
-  v = iterative_hash_hashval_t (TYPE_QUALS (type), v);
-  v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
-
-  /* Do not hash the types size as this will cause differences in
-     hash values for the complete vs. the incomplete type variant.  */
-
-  /* Incorporate common features of numerical types.  */
-  if (INTEGRAL_TYPE_P (type)
-      || SCALAR_FLOAT_TYPE_P (type)
-      || FIXED_POINT_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
-      v = iterative_hash_hashval_t (TYPE_MODE (type), v);
-      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-    }
-
-  /* For pointer and reference types, fold in information about the type
-     pointed to.  */
-  if (POINTER_TYPE_P (type))
-    v = visit (TREE_TYPE (type), state, v,
-              sccstack, sccstate, sccstate_obstack);
-
-  /* For integer types hash the types min/max values and the string flag.  */
-  if (TREE_CODE (type) == INTEGER_TYPE)
-    {
-      /* OMP lowering can introduce error_mark_node in place of
-        random local decls in types.  */
-      if (TYPE_MIN_VALUE (type) != error_mark_node)
-       v = iterative_hash_expr (TYPE_MIN_VALUE (type), v);
-      if (TYPE_MAX_VALUE (type) != error_mark_node)
-       v = iterative_hash_expr (TYPE_MAX_VALUE (type), v);
-      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-    }
-
-  /* For array types hash their domain and the string flag.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-      v = visit (TYPE_DOMAIN (type), state, v,
-                sccstack, sccstate, sccstate_obstack);
-    }
-
-  /* Recurse for aggregates with a single element type.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      || TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    v = visit (TREE_TYPE (type), state, v,
-              sccstack, sccstate, sccstate_obstack);
-
-  /* Incorporate function return and argument types.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
-    {
-      unsigned na;
-      tree p;
-
-      /* For method types also incorporate their parent class.  */
-      if (TREE_CODE (type) == METHOD_TYPE)
-       v = visit (TYPE_METHOD_BASETYPE (type), state, v,
-                  sccstack, sccstate, sccstate_obstack);
-
-      /* Check result and argument types.  */
-      v = visit (TREE_TYPE (type), state, v,
-                sccstack, sccstate, sccstate_obstack);
-      for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
-       {
-         v = visit (TREE_VALUE (p), state, v,
-                    sccstack, sccstate, sccstate_obstack);
-         na++;
-       }
-
-      v = iterative_hash_hashval_t (na, v);
-    }
-
-  if (TREE_CODE (type) == RECORD_TYPE
-      || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE)
-    {
-      unsigned nf;
-      tree f;
-
-      for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
-       {
-         v = iterative_hash_name (DECL_NAME (f), v);
-         v = visit (TREE_TYPE (f), state, v,
-                    sccstack, sccstate, sccstate_obstack);
-         nf++;
-       }
-
-      v = iterative_hash_hashval_t (nf, v);
-    }
-
-  /* Record hash for us.  */
-  state->u.hash = v;
-
-  /* See if we found an SCC.  */
-  if (state->low == state->dfsnum)
-    {
-      tree x;
-      struct tree_int_map *m;
-
-      /* Pop off the SCC and set its hash values.  */
-      x = VEC_pop (tree, *sccstack);
-      /* Optimize SCC size one.  */
-      if (x == type)
-       {
-         state->on_sccstack = false;
-         m = ggc_alloc_cleared_tree_int_map ();
-         m->base.from = x;
-         m->to = v;
-         slot = htab_find_slot (type_hash_cache, m, INSERT);
-         gcc_assert (!*slot);
-         *slot = (void *) m;
-       }
-      else
-       {
-         struct sccs *cstate;
-         unsigned first, i, size, j;
-         struct type_hash_pair *pairs;
-         /* Pop off the SCC and build an array of type, hash pairs.  */
-         first = VEC_length (tree, *sccstack) - 1;
-         while (VEC_index (tree, *sccstack, first) != type)
-           --first;
-         size = VEC_length (tree, *sccstack) - first + 1;
-         pairs = XALLOCAVEC (struct type_hash_pair, size);
-         i = 0;
-         cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
-         cstate->on_sccstack = false;
-         pairs[i].type = x;
-         pairs[i].hash = cstate->u.hash;
-         do
-           {
-             x = VEC_pop (tree, *sccstack);
-             cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
-             cstate->on_sccstack = false;
-             ++i;
-             pairs[i].type = x;
-             pairs[i].hash = cstate->u.hash;
-           }
-         while (x != type);
-         gcc_assert (i + 1 == size);
-         /* Sort the arrays of type, hash pairs so that when we mix in
-            all members of the SCC the hash value becomes independent on
-            the order we visited the SCC.  Disregard hashes equal to
-            the hash of the type we mix into because we cannot guarantee
-            a stable sort for those across different TUs.  */
-         qsort (pairs, size, sizeof (struct type_hash_pair),
-                type_hash_pair_compare);
-         for (i = 0; i < size; ++i)
-           {
-             hashval_t hash;
-             m = ggc_alloc_cleared_tree_int_map ();
-             m->base.from = pairs[i].type;
-             hash = pairs[i].hash;
-             /* Skip same hashes.  */
-             for (j = i + 1; j < size && pairs[j].hash == pairs[i].hash; ++j)
-               ;
-             for (; j < size; ++j)
-               hash = iterative_hash_hashval_t (pairs[j].hash, hash);
-             for (j = 0; pairs[j].hash != pairs[i].hash; ++j)
-               hash = iterative_hash_hashval_t (pairs[j].hash, hash);
-             m->to = hash;
-             if (pairs[i].type == type)
-               v = hash;
-             slot = htab_find_slot (type_hash_cache, m, INSERT);
-             gcc_assert (!*slot);
-             *slot = (void *) m;
-           }
-       }
-    }
-
-  return iterative_hash_hashval_t (v, val);
-}
-
-
-/* Returns a hash value for P (assumed to be a type).  The hash value
-   is computed using some distinguishing features of the type.  Note
-   that we cannot use pointer hashing here as we may be dealing with
-   two distinct instances of the same type.
-
-   This function should produce the same hash value for two compatible
-   types according to gimple_types_compatible_p.  */
-
-static hashval_t
-gimple_type_hash (const void *p)
-{
-  const_tree t = (const_tree) p;
-  VEC(tree, heap) *sccstack = NULL;
-  struct pointer_map_t *sccstate;
-  struct obstack sccstate_obstack;
-  hashval_t val;
-  void **slot;
-  struct tree_int_map m;
-
-  if (type_hash_cache == NULL)
-    type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
-                                      tree_int_map_eq, NULL);
-
-  m.base.from = CONST_CAST_TREE (t);
-  if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
-      && *slot)
-    return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0);
-
-  /* Perform a DFS walk and pre-hash all reachable types.  */
-  next_dfs_num = 1;
-  sccstate = pointer_map_create ();
-  gcc_obstack_init (&sccstate_obstack);
-  val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0,
-                                   &sccstack, sccstate, &sccstate_obstack);
-  VEC_free (tree, heap, sccstack);
-  pointer_map_destroy (sccstate);
-  obstack_free (&sccstate_obstack, NULL);
-
-  return val;
-}
-
-/* Returning a hash value for gimple type TYPE combined with VAL.
-
-   The hash value returned is equal for types considered compatible
-   by gimple_canonical_types_compatible_p.  */
-
-static hashval_t
-iterative_hash_canonical_type (tree type, hashval_t val)
-{
-  hashval_t v;
-  void **slot;
-  struct tree_int_map *mp, m;
-
-  m.base.from = type;
-  if ((slot = htab_find_slot (canonical_type_hash_cache, &m, INSERT))
-      && *slot)
-    return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, val);
-
-  /* Combine a few common features of types so that types are grouped into
-     smaller sets; when searching for existing matching types to merge,
-     only existing types having the same features as the new type will be
-     checked.  */
-  v = iterative_hash_hashval_t (TREE_CODE (type), 0);
-  v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
-  v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
-  v = iterative_hash_hashval_t (TYPE_MODE (type), v);
-
-  /* Incorporate common features of numerical types.  */
-  if (INTEGRAL_TYPE_P (type)
-      || SCALAR_FLOAT_TYPE_P (type)
-      || FIXED_POINT_TYPE_P (type)
-      || TREE_CODE (type) == VECTOR_TYPE
-      || TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == OFFSET_TYPE
-      || POINTER_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
-      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-    }
-
-  /* For pointer and reference types, fold in information about the type
-     pointed to but do not recurse to the pointed-to type.  */
-  if (POINTER_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
-      v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
-      v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
-      v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
-    }
-
-  /* For integer types hash the types min/max values and the string flag.  */
-  if (TREE_CODE (type) == INTEGER_TYPE)
-    {
-      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-      v = iterative_hash_hashval_t (TYPE_IS_SIZETYPE (type), v);
-    }
-
-  /* For array types hash their domain and the string flag.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-      v = iterative_hash_canonical_type (TYPE_DOMAIN (type), v);
-    }
-
-  /* Recurse for aggregates with a single element type.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      || TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
-  /* Incorporate function return and argument types.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
-    {
-      unsigned na;
-      tree p;
-
-      /* For method types also incorporate their parent class.  */
-      if (TREE_CODE (type) == METHOD_TYPE)
-       v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
-
-      v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
-      for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
-       {
-         v = iterative_hash_canonical_type (TREE_VALUE (p), v);
-         na++;
-       }
-
-      v = iterative_hash_hashval_t (na, v);
-    }
-
-  if (TREE_CODE (type) == RECORD_TYPE
-      || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE)
-    {
-      unsigned nf;
-      tree f;
-
-      for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
-       if (TREE_CODE (f) == FIELD_DECL)
-         {
-           v = iterative_hash_canonical_type (TREE_TYPE (f), v);
-           nf++;
-         }
-
-      v = iterative_hash_hashval_t (nf, v);
-    }
-
-  /* Cache the just computed hash value.  */
-  mp = ggc_alloc_cleared_tree_int_map ();
-  mp->base.from = type;
-  mp->to = v;
-  *slot = (void *) mp;
-
-  return iterative_hash_hashval_t (v, val);
-}
-
-static hashval_t
-gimple_canonical_type_hash (const void *p)
-{
-  if (canonical_type_hash_cache == NULL)
-    canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
-                                                tree_int_map_eq, NULL);
-
-  return iterative_hash_canonical_type (CONST_CAST_TREE ((const_tree) p), 0);
-}
-
-
-/* Returns nonzero if P1 and P2 are equal.  */
-
-static int
-gimple_type_eq (const void *p1, const void *p2)
-{
-  const_tree t1 = (const_tree) p1;
-  const_tree t2 = (const_tree) p2;
-  return gimple_types_compatible_p (CONST_CAST_TREE (t1),
-                                   CONST_CAST_TREE (t2));
-}
-
-
-/* Worker for gimple_register_type.
-   Register type T in the global type table gimple_types.
-   When REGISTERING_MV is false first recurse for the main variant of T.  */
-
-static tree
-gimple_register_type_1 (tree t, bool registering_mv)
-{
-  void **slot;
-  gimple_type_leader_entry *leader;
-
-  /* If we registered this type before return the cached result.  */
-  leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE];
-  if (leader->type == t)
-    return leader->leader;
-
-  /* Always register the main variant first.  This is important so we
-     pick up the non-typedef variants as canonical, otherwise we'll end
-     up taking typedef ids for structure tags during comparison.
-     It also makes sure that main variants will be merged to main variants.
-     As we are operating on a possibly partially fixed up type graph
-     do not bother to recurse more than once, otherwise we may end up
-     walking in circles.
-     If we are registering a main variant it will either remain its
-     own main variant or it will be merged to something else in which
-     case we do not care for the main variant leader.  */
-  if (!registering_mv
-      && TYPE_MAIN_VARIANT (t) != t)
-    gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
-
-  /* See if we already have an equivalent type registered.  */
-  slot = htab_find_slot (gimple_types, t, INSERT);
-  if (*slot
-      && *(tree *)slot != t)
-    {
-      tree new_type = (tree) *((tree *) slot);
-      leader->type = t;
-      leader->leader = new_type;
-      return new_type;
-    }
-
-  /* If not, insert it to the cache and the hash.  */
-  leader->type = t;
-  leader->leader = t;
-  *slot = (void *) t;
-  return t;
-}
-
-/* Register type T in the global type table gimple_types.
-   If another type T', compatible with T, already existed in
-   gimple_types then return T', otherwise return T.  This is used by
-   LTO to merge identical types read from different TUs.  */
-
-tree
-gimple_register_type (tree t)
-{
-  gcc_assert (TYPE_P (t));
-
-  if (!gimple_type_leader)
-    gimple_type_leader = ggc_alloc_cleared_vec_gimple_type_leader_entry_s
-                               (GIMPLE_TYPE_LEADER_SIZE);
-
-  if (gimple_types == NULL)
-    gimple_types = htab_create_ggc (16381, gimple_type_hash, gimple_type_eq, 0);
-
-  return gimple_register_type_1 (t, false);
-}
-
-/* The TYPE_CANONICAL merging machinery.  It should closely resemble
-   the middle-end types_compatible_p function.  It needs to avoid
-   claiming types are different for types that should be treated
-   the same with respect to TBAA.  Canonical types are also used
-   for IL consistency checks via the useless_type_conversion_p
-   predicate which does not handle all type kinds itself but falls
-   back to pointer-comparison of TYPE_CANONICAL for aggregates
-   for example.  */
-
-/* Return true iff T1 and T2 are structurally identical for what
-   TBAA is concerned.  */
-
-static bool
-gimple_canonical_types_compatible_p (tree t1, tree t2)
-{
-  /* Before starting to set up the SCC machinery handle simple cases.  */
-
-  /* Check first for the obvious case of pointer identity.  */
-  if (t1 == t2)
-    return true;
-
-  /* Check that we have two types to compare.  */
-  if (t1 == NULL_TREE || t2 == NULL_TREE)
-    return false;
-
-  /* If the types have been previously registered and found equal
-     they still are.  */
-  if (TYPE_CANONICAL (t1)
-      && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
-    return true;
-
-  /* Can't be the same type if the types don't have the same code.  */
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return false;
-
-  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
-    return false;
-
-  /* Qualifiers do not matter for canonical type comparison purposes.  */
-
-  /* Void types and nullptr types are always the same.  */
-  if (TREE_CODE (t1) == VOID_TYPE
-      || TREE_CODE (t1) == NULLPTR_TYPE)
-    return true;
-
-  /* Can't be the same type if they have different alignment, or mode.  */
-  if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-      || TYPE_MODE (t1) != TYPE_MODE (t2))
-    return false;
-
-  /* Non-aggregate types can be handled cheaply.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1)
-      || TREE_CODE (t1) == VECTOR_TYPE
-      || TREE_CODE (t1) == COMPLEX_TYPE
-      || TREE_CODE (t1) == OFFSET_TYPE
-      || POINTER_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different sign or precision.  */
-      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-       return false;
-
-      if (TREE_CODE (t1) == INTEGER_TYPE
-         && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
-             || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
-       return false;
-
-      /* For canonical type comparisons we do not want to build SCCs
-        so we cannot compare pointed-to types.  But we can, for now,
-        require the same pointed-to type kind and match what
-        useless_type_conversion_p would do.  */
-      if (POINTER_TYPE_P (t1))
-       {
-         /* If the two pointers have different ref-all attributes,
-            they can't be the same type.  */
-         if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
-           return false;
-
-         if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
-             != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
-           return false;
-
-         if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
-           return false;
-
-         if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
-           return false;
-       }
-
-      /* Tail-recurse to components.  */
-      if (TREE_CODE (t1) == VECTOR_TYPE
-         || TREE_CODE (t1) == COMPLEX_TYPE)
-       return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
-                                                   TREE_TYPE (t2));
-
-      return true;
-    }
-
-  /* If their attributes are not the same they can't be the same type.  */
-  if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
-    return false;
-
-  /* Do type-specific comparisons.  */
-  switch (TREE_CODE (t1))
-    {
-    case ARRAY_TYPE:
-      /* Array types are the same if the element types are the same and
-        the number of elements are the same.  */
-      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
-         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
-         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
-       return false;
-      else
-       {
-         tree i1 = TYPE_DOMAIN (t1);
-         tree i2 = TYPE_DOMAIN (t2);
-
-         /* For an incomplete external array, the type domain can be
-            NULL_TREE.  Check this condition also.  */
-         if (i1 == NULL_TREE && i2 == NULL_TREE)
-           return true;
-         else if (i1 == NULL_TREE || i2 == NULL_TREE)
-           return false;
-         /* If for a complete array type the possibly gimplified sizes
-            are different the types are different.  */
-         else if (((TYPE_SIZE (i1) != NULL) ^ (TYPE_SIZE (i2) != NULL))
-                  || (TYPE_SIZE (i1)
-                      && TYPE_SIZE (i2)
-                      && !operand_equal_p (TYPE_SIZE (i1), TYPE_SIZE (i2), 0)))
-           return false;
-         else
-           {
-             tree min1 = TYPE_MIN_VALUE (i1);
-             tree min2 = TYPE_MIN_VALUE (i2);
-             tree max1 = TYPE_MAX_VALUE (i1);
-             tree max2 = TYPE_MAX_VALUE (i2);
-
-             /* The minimum/maximum values have to be the same.  */
-             if ((min1 == min2
-                  || (min1 && min2
-                      && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
-                           && TREE_CODE (min2) == PLACEHOLDER_EXPR)
-                          || operand_equal_p (min1, min2, 0))))
-                 && (max1 == max2
-                     || (max1 && max2
-                         && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
-                              && TREE_CODE (max2) == PLACEHOLDER_EXPR)
-                             || operand_equal_p (max1, max2, 0)))))
-               return true;
-             else
-               return false;
-           }
-       }
-
-    case METHOD_TYPE:
-      /* Method types should belong to the same class.  */
-      if (!gimple_canonical_types_compatible_p
-            (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2)))
-       return false;
-
-      /* Fallthru  */
-
-    case FUNCTION_TYPE:
-      /* Function types are the same if the return type and arguments types
-        are the same.  */
-      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
-       return false;
-
-      if (!comp_type_attributes (t1, t2))
-       return false;
-
-      if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
-       return true;
-      else
-       {
-         tree parms1, parms2;
-
-         for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
-              parms1 && parms2;
-              parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
-           {
-             if (!gimple_canonical_types_compatible_p
-                    (TREE_VALUE (parms1), TREE_VALUE (parms2)))
-               return false;
-           }
-
-         if (parms1 || parms2)
-           return false;
-
-         return true;
-       }
-
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      {
-       tree f1, f2;
-
-       /* For aggregate types, all the fields must be the same.  */
-       for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
-            f1 && f2;
-            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-         {
-           /* Skip non-fields.  */
-           while (f1 && TREE_CODE (f1) != FIELD_DECL)
-             f1 = TREE_CHAIN (f1);
-           while (f2 && TREE_CODE (f2) != FIELD_DECL)
-             f2 = TREE_CHAIN (f2);
-           if (!f1 || !f2)
-             break;
-           /* The fields must have the same name, offset and type.  */
-           if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
-               || !gimple_compare_field_offset (f1, f2)
-               || !gimple_canonical_types_compatible_p
-                     (TREE_TYPE (f1), TREE_TYPE (f2)))
-             return false;
-         }
-
-       /* If one aggregate has more fields than the other, they
-          are not the same.  */
-       if (f1 || f2)
-         return false;
-
-       return true;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-
-/* Returns nonzero if P1 and P2 are equal.  */
-
-static int
-gimple_canonical_type_eq (const void *p1, const void *p2)
-{
-  const_tree t1 = (const_tree) p1;
-  const_tree t2 = (const_tree) p2;
-  return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
-                                             CONST_CAST_TREE (t2));
-}
-
-/* Register type T in the global type table gimple_types.
-   If another type T', compatible with T, already existed in
-   gimple_types then return T', otherwise return T.  This is used by
-   LTO to merge identical types read from different TUs.
-
-   ???  This merging does not exactly match how the tree.c middle-end
-   functions will assign TYPE_CANONICAL when new types are created
-   during optimization (which at least happens for pointer and array
-   types).  */
-
-tree
-gimple_register_canonical_type (tree t)
-{
-  void **slot;
-
-  gcc_assert (TYPE_P (t));
-
-  if (TYPE_CANONICAL (t))
-    return TYPE_CANONICAL (t);
-
-  if (gimple_canonical_types == NULL)
-    gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
-                                             gimple_canonical_type_eq, 0);
-
-  slot = htab_find_slot (gimple_canonical_types, t, INSERT);
-  if (*slot
-      && *(tree *)slot != t)
-    {
-      tree new_type = (tree) *((tree *) slot);
-
-      TYPE_CANONICAL (t) = new_type;
-      t = new_type;
-    }
-  else
-    {
-      TYPE_CANONICAL (t) = t;
-      *slot = (void *) t;
-    }
-
-  return t;
-}
-
-
-/* Show statistics on references to the global type table gimple_types.  */
-
-void
-print_gimple_types_stats (void)
-{
-  if (gimple_types)
-    fprintf (stderr, "GIMPLE type table: size %ld, %ld elements, "
-            "%ld searches, %ld collisions (ratio: %f)\n",
-            (long) htab_size (gimple_types),
-            (long) htab_elements (gimple_types),
-            (long) gimple_types->searches,
-            (long) gimple_types->collisions,
-            htab_collisions (gimple_types));
-  else
-    fprintf (stderr, "GIMPLE type table is empty\n");
-  if (type_hash_cache)
-    fprintf (stderr, "GIMPLE type hash table: size %ld, %ld elements, "
-            "%ld searches, %ld collisions (ratio: %f)\n",
-            (long) htab_size (type_hash_cache),
-            (long) htab_elements (type_hash_cache),
-            (long) type_hash_cache->searches,
-            (long) type_hash_cache->collisions,
-            htab_collisions (type_hash_cache));
-  else
-    fprintf (stderr, "GIMPLE type hash table is empty\n");
-  if (gimple_canonical_types)
-    fprintf (stderr, "GIMPLE canonical type table: size %ld, %ld elements, "
-            "%ld searches, %ld collisions (ratio: %f)\n",
-            (long) htab_size (gimple_canonical_types),
-            (long) htab_elements (gimple_canonical_types),
-            (long) gimple_canonical_types->searches,
-            (long) gimple_canonical_types->collisions,
-            htab_collisions (gimple_canonical_types));
-  else
-    fprintf (stderr, "GIMPLE canonical type table is empty\n");
-  if (canonical_type_hash_cache)
-    fprintf (stderr, "GIMPLE canonical type hash table: size %ld, %ld elements, "
-            "%ld searches, %ld collisions (ratio: %f)\n",
-            (long) htab_size (canonical_type_hash_cache),
-            (long) htab_elements (canonical_type_hash_cache),
-            (long) canonical_type_hash_cache->searches,
-            (long) canonical_type_hash_cache->collisions,
-            htab_collisions (canonical_type_hash_cache));
-  else
-    fprintf (stderr, "GIMPLE canonical type hash table is empty\n");
-}
-
-/* Free the gimple type hashtables used for LTO type merging.  */
-
-void
-free_gimple_type_tables (void)
-{
-  /* Last chance to print stats for the tables.  */
-  if (flag_lto_report)
-    print_gimple_types_stats ();
-
-  if (gimple_types)
-    {
-      htab_delete (gimple_types);
-      gimple_types = NULL;
-    }
-  if (gimple_canonical_types)
-    {
-      htab_delete (gimple_canonical_types);
-      gimple_canonical_types = NULL;
-    }
-  if (type_hash_cache)
-    {
-      htab_delete (type_hash_cache);
-      type_hash_cache = NULL;
-    }
-  if (canonical_type_hash_cache)
-    {
-      htab_delete (canonical_type_hash_cache);
-      canonical_type_hash_cache = NULL;
+                      || (TREE_CODE (DECL_SIZE (f1)) == PLACEHOLDER_EXPR
+                          && TREE_CODE (DECL_SIZE (f2)) == PLACEHOLDER_EXPR)
+                      || operand_equal_p (DECL_SIZE (f1), DECL_SIZE (f2), 0))
+                  && DECL_ALIGN (f1) == DECL_ALIGN (f2))
+              || operand_equal_p (offset1, offset2, 0))
+             && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1),
+                                    DECL_FIELD_BIT_OFFSET (f2)));
     }
-  if (type_pair_cache)
+
+  /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN
+     should be, so handle differing ones specially by decomposing
+     the offset into a byte and bit offset manually.  */
+  if (tree_fits_shwi_p (DECL_FIELD_OFFSET (f1))
+      && tree_fits_shwi_p (DECL_FIELD_OFFSET (f2)))
     {
-      free (type_pair_cache);
-      type_pair_cache = NULL;
+      unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
+      unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
+      bit_offset1 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f1));
+      byte_offset1 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f1))
+                     + bit_offset1 / BITS_PER_UNIT);
+      bit_offset2 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f2));
+      byte_offset2 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f2))
+                     + bit_offset2 / BITS_PER_UNIT);
+      if (byte_offset1 != byte_offset2)
+       return false;
+      return bit_offset1 % BITS_PER_UNIT == bit_offset2 % BITS_PER_UNIT;
     }
-  gimple_type_leader = NULL;
+
+  return false;
 }
 
 
@@ -4914,6 +2192,7 @@ static tree
 gimple_signed_or_unsigned_type (bool unsignedp, tree type)
 {
   tree type1;
+  int i;
 
   type1 = TYPE_MAIN_VARIANT (type);
   if (type1 == signed_char_type_node
@@ -4931,10 +2210,15 @@ gimple_signed_or_unsigned_type (bool unsignedp, tree type)
     return unsignedp
            ? long_long_unsigned_type_node
           : long_long_integer_type_node;
-  if (int128_integer_type_node && (type1 == int128_integer_type_node || type1 == int128_unsigned_type_node))
-    return unsignedp
-           ? int128_unsigned_type_node
-          : int128_integer_type_node;
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+       && (type1 == int_n_trees[i].unsigned_type
+           || type1 == int_n_trees[i].signed_type))
+       return unsignedp
+         ? int_n_trees[i].unsigned_type
+         : int_n_trees[i].signed_type;
+
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
@@ -5047,10 +2331,14 @@ gimple_signed_or_unsigned_type (bool unsignedp, tree type)
     return (unsignedp
            ? long_long_unsigned_type_node
            : long_long_integer_type_node);
-  if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
-    return (unsignedp
-           ? int128_unsigned_type_node
-           : int128_integer_type_node);
+
+  for (i = 0; i < NUM_INT_N_ENTS; i ++)
+    if (int_n_enabled_p[i]
+       && TYPE_MODE (type) == int_n_data[i].m
+       && TYPE_PRECISION (type) == int_n_data[i].bitsize)
+       return unsignedp
+         ? int_n_trees[i].unsigned_type
+         : int_n_trees[i].signed_type;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
   if (TYPE_OK (intTI_type_node))
@@ -5141,451 +2429,532 @@ gimple_get_alias_set (tree t)
 }
 
 
-/* Data structure used to count the number of dereferences to PTR
-   inside an expression.  */
-struct count_ptr_d
+/* Helper for gimple_ior_addresses_taken_1.  */
+
+static bool
+gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
 {
-  tree ptr;
-  unsigned num_stores;
-  unsigned num_loads;
-};
+  bitmap addresses_taken = (bitmap)data;
+  addr = get_base_address (addr);
+  if (addr
+      && DECL_P (addr))
+    {
+      bitmap_set_bit (addresses_taken, DECL_UID (addr));
+      return true;
+    }
+  return false;
+}
 
-/* Helper for count_uses_and_derefs.  Called by walk_tree to look for
-   (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
+/* Set the bit for the uid of all decls that have their address taken
+   in STMT in the ADDRESSES_TAKEN bitmap.  Returns true if there
+   were any in this stmt.  */
 
-static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
+bool
+gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
 {
-  struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
-  struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
+  return walk_stmt_load_store_addr_ops (stmt, addresses_taken, NULL, NULL,
+                                       gimple_ior_addresses_taken_1);
+}
 
-  /* Do not walk inside ADDR_EXPR nodes.  In the expression &ptr->fld,
-     pointer 'ptr' is *not* dereferenced, it is simply used to compute
-     the address of 'fld' as 'ptr + offsetof(fld)'.  */
-  if (TREE_CODE (*tp) == ADDR_EXPR)
-    {
-      *walk_subtrees = 0;
-      return NULL_TREE;
-    }
 
-  if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
-    {
-      if (wi_p->is_lhs)
-       count_p->num_stores++;
-      else
-       count_p->num_loads++;
-    }
+/* Return true if TYPE1 and TYPE2 are compatible enough for builtin
+   processing.  */
 
-  return NULL_TREE;
+static bool
+validate_type (tree type1, tree type2)
+{
+  if (INTEGRAL_TYPE_P (type1)
+      && INTEGRAL_TYPE_P (type2))
+    ;
+  else if (POINTER_TYPE_P (type1)
+          && POINTER_TYPE_P (type2))
+    ;
+  else if (TREE_CODE (type1)
+          != TREE_CODE (type2))
+    return false;
+  return true;
 }
 
-/* Count the number of direct and indirect uses for pointer PTR in
-   statement STMT.  The number of direct uses is stored in
-   *NUM_USES_P.  Indirect references are counted separately depending
-   on whether they are store or load operations.  The counts are
-   stored in *NUM_STORES_P and *NUM_LOADS_P.  */
+/* Return true when STMTs arguments and return value match those of FNDECL,
+   a decl of a builtin function.  */
 
-void
-count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
-                      unsigned *num_loads_p, unsigned *num_stores_p)
+bool
+gimple_builtin_call_types_compatible_p (const_gimple stmt, tree fndecl)
 {
-  ssa_op_iter i;
-  tree use;
-
-  *num_uses_p = 0;
-  *num_loads_p = 0;
-  *num_stores_p = 0;
-
-  /* Find out the total number of uses of PTR in STMT.  */
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
-    if (use == ptr)
-      (*num_uses_p)++;
-
-  /* Now count the number of indirect references to PTR.  This is
-     truly awful, but we don't have much choice.  There are no parent
-     pointers inside INDIRECT_REFs, so an expression like
-     '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
-     find all the indirect and direct uses of x_1 inside.  The only
-     shortcut we can take is the fact that GIMPLE only allows
-     INDIRECT_REFs inside the expressions below.  */
-  if (is_gimple_assign (stmt)
-      || gimple_code (stmt) == GIMPLE_RETURN
-      || gimple_code (stmt) == GIMPLE_ASM
-      || is_gimple_call (stmt))
+  gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
+
+  tree ret = gimple_call_lhs (stmt);
+  if (ret
+      && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl))))
+    return false;
+
+  tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+  unsigned nargs = gimple_call_num_args (stmt);
+  for (unsigned i = 0; i < nargs; ++i)
     {
-      struct walk_stmt_info wi;
-      struct count_ptr_d count;
+      /* Variadic args follow.  */
+      if (!targs)
+       return true;
+      tree arg = gimple_call_arg (stmt, i);
+      if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs)))
+       return false;
+      targs = TREE_CHAIN (targs);
+    }
+  if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
+    return false;
+  return true;
+}
 
-      count.ptr = ptr;
-      count.num_stores = 0;
-      count.num_loads = 0;
+/* Return true when STMT is builtins call.  */
 
-      memset (&wi, 0, sizeof (wi));
-      wi.info = &count;
-      walk_gimple_op (stmt, count_ptr_derefs, &wi);
+bool
+gimple_call_builtin_p (const_gimple stmt)
+{
+  tree fndecl;
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN)
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
+  return false;
+}
 
-      *num_stores_p = count.num_stores;
-      *num_loads_p = count.num_loads;
-    }
+/* Return true when STMT is builtins call to CLASS.  */
 
-  gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
+bool
+gimple_call_builtin_p (const_gimple stmt, enum built_in_class klass)
+{
+  tree fndecl;
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) == klass)
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
+  return false;
 }
 
-/* From a tree operand OP return the base of a load or store operation
-   or NULL_TREE if OP is not a load or a store.  */
+/* Return true when STMT is builtins call to CODE of CLASS.  */
 
-static tree
-get_base_loadstore (tree op)
+bool
+gimple_call_builtin_p (const_gimple stmt, enum built_in_function code)
 {
-  while (handled_component_p (op))
-    op = TREE_OPERAND (op, 0);
-  if (DECL_P (op)
-      || INDIRECT_REF_P (op)
-      || TREE_CODE (op) == MEM_REF
-      || TREE_CODE (op) == TARGET_MEM_REF)
-    return op;
-  return NULL_TREE;
+  tree fndecl;
+  if (is_gimple_call (stmt)
+      && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
+      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 
+      && DECL_FUNCTION_CODE (fndecl) == code)
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
+  return false;
 }
 
-/* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
-   VISIT_ADDR if non-NULL on loads, store and address-taken operands
-   passing the STMT, the base of the operand and DATA to it.  The base
-   will be either a decl, an indirect reference (including TARGET_MEM_REF)
-   or the argument of an address expression.
-   Returns the results of these callbacks or'ed.  */
+/* Return true if STMT clobbers memory.  STMT is required to be a
+   GIMPLE_ASM.  */
 
 bool
-walk_stmt_load_store_addr_ops (gimple stmt, void *data,
-                              bool (*visit_load)(gimple, tree, void *),
-                              bool (*visit_store)(gimple, tree, void *),
-                              bool (*visit_addr)(gimple, tree, void *))
+gimple_asm_clobbers_memory_p (const gasm *stmt)
 {
-  bool ret = false;
   unsigned i;
-  if (gimple_assign_single_p (stmt))
+
+  for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
     {
-      tree lhs, rhs;
-      if (visit_store)
-       {
-         lhs = get_base_loadstore (gimple_assign_lhs (stmt));
-         if (lhs)
-           ret |= visit_store (stmt, lhs, data);
-       }
-      rhs = gimple_assign_rhs1 (stmt);
-      while (handled_component_p (rhs))
-       rhs = TREE_OPERAND (rhs, 0);
-      if (visit_addr)
-       {
-         if (TREE_CODE (rhs) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
-         else if (TREE_CODE (rhs) == TARGET_MEM_REF
-                  && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
-         else if (TREE_CODE (rhs) == OBJ_TYPE_REF
-                  && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
-                                                  0), data);
-         else if (TREE_CODE (rhs) == CONSTRUCTOR)
-           {
-             unsigned int ix;
-             tree val;
-
-             FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
-               if (TREE_CODE (val) == ADDR_EXPR)
-                 ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
-               else if (TREE_CODE (val) == OBJ_TYPE_REF
-                        && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
-                 ret |= visit_addr (stmt,
-                                    TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
-                                                  0), data);
-           }
-          lhs = gimple_assign_lhs (stmt);
-         if (TREE_CODE (lhs) == TARGET_MEM_REF
-              && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
-            ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
-       }
-      if (visit_load)
-       {
-         rhs = get_base_loadstore (rhs);
-         if (rhs)
-           ret |= visit_load (stmt, rhs, data);
-       }
+      tree op = gimple_asm_clobber_op (stmt, i);
+      if (strcmp (TREE_STRING_POINTER (TREE_VALUE (op)), "memory") == 0)
+       return true;
     }
-  else if (visit_addr
-          && (is_gimple_assign (stmt)
-              || gimple_code (stmt) == GIMPLE_COND))
+
+  return false;
+}
+
+/* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE.  */
+
+void
+dump_decl_set (FILE *file, bitmap set)
+{
+  if (set)
     {
-      for (i = 0; i < gimple_num_ops (stmt); ++i)
+      bitmap_iterator bi;
+      unsigned i;
+
+      fprintf (file, "{ ");
+
+      EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
        {
-         tree op = gimple_op (stmt, i);
-         if (op == NULL_TREE)
-           ;
-         else if (TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-         /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
-            tree with two operands.  */
-         else if (i == 1 && COMPARISON_CLASS_P (op))
-           {
-             if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
-               ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
-                                                      0), data);
-             if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
-               ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
-                                                      0), data);
-           }
+         fprintf (file, "D.%u", i);
+         fprintf (file, " ");
        }
+
+      fprintf (file, "}");
     }
-  else if (is_gimple_call (stmt))
+  else
+    fprintf (file, "NIL");
+}
+
+/* Return true when CALL is a call stmt that definitely doesn't
+   free any memory or makes it unavailable otherwise.  */
+bool
+nonfreeing_call_p (gimple call)
+{
+  if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
+      && gimple_call_flags (call) & ECF_LEAF)
+    switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
+      {
+       /* Just in case these become ECF_LEAF in the future.  */
+       case BUILT_IN_FREE:
+       case BUILT_IN_TM_FREE:
+       case BUILT_IN_REALLOC:
+       case BUILT_IN_STACK_RESTORE:
+         return false;
+       default:
+         return true;
+      }
+  else if (gimple_call_internal_p (call))
+    switch (gimple_call_internal_fn (call))
+      {
+      case IFN_ABNORMAL_DISPATCHER:
+        return true;
+      default:
+       if (gimple_call_flags (call) & ECF_LEAF)
+         return true;
+       return false;
+      }
+
+  tree fndecl = gimple_call_fndecl (call);
+  if (!fndecl)
+    return false;
+  struct cgraph_node *n = cgraph_node::get (fndecl);
+  if (!n)
+    return false;
+  enum availability availability;
+  n = n->function_symbol (&availability);
+  if (!n || availability <= AVAIL_INTERPOSABLE)
+    return false;
+  return n->nonfreeing_fn;
+}
+
+/* Callback for walk_stmt_load_store_ops.
+   Return TRUE if OP will dereference the tree stored in DATA, FALSE
+   otherwise.
+
+   This routine only makes a superficial check for a dereference.  Thus
+   it must only be used if it is safe to return a false negative.  */
+static bool
+check_loadstore (gimple, tree op, tree, void *data)
+{
+  if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+      && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
+    return true;
+  return false;
+}
+
+/* If OP can be inferred to be non-NULL after STMT executes, return true.
+
+   DEREFERENCE is TRUE if we can use a pointer dereference to infer a
+   non-NULL range, FALSE otherwise.
+
+   ATTRIBUTE is TRUE if we can use attributes to infer a non-NULL range
+   for function arguments and return values.  FALSE otherwise.  */
+
+bool
+infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
+{
+  /* We can only assume that a pointer dereference will yield
+     non-NULL if -fdelete-null-pointer-checks is enabled.  */
+  if (!flag_delete_null_pointer_checks
+      || !POINTER_TYPE_P (TREE_TYPE (op))
+      || gimple_code (stmt) == GIMPLE_ASM)
+    return false;
+
+  if (dereference
+      && walk_stmt_load_store_ops (stmt, (void *)op,
+                                  check_loadstore, check_loadstore))
+    return true;
+
+  if (attribute
+      && is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
     {
-      if (visit_store)
+      tree fntype = gimple_call_fntype (stmt);
+      tree attrs = TYPE_ATTRIBUTES (fntype);
+      for (; attrs; attrs = TREE_CHAIN (attrs))
        {
-         tree lhs = gimple_call_lhs (stmt);
-         if (lhs)
+         attrs = lookup_attribute ("nonnull", attrs);
+
+         /* If "nonnull" wasn't specified, we know nothing about
+            the argument.  */
+         if (attrs == NULL_TREE)
+           return false;
+
+         /* If "nonnull" applies to all the arguments, then ARG
+            is non-null if it's in the argument list.  */
+         if (TREE_VALUE (attrs) == NULL_TREE)
            {
-             lhs = get_base_loadstore (lhs);
-             if (lhs)
-               ret |= visit_store (stmt, lhs, data);
+             for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
+               {
+                 if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i)))
+                     && operand_equal_p (op, gimple_call_arg (stmt, i), 0))
+                   return true;
+               }
+             return false;
            }
-       }
-      if (visit_load || visit_addr)
-       for (i = 0; i < gimple_call_num_args (stmt); ++i)
-         {
-           tree rhs = gimple_call_arg (stmt, i);
-           if (visit_addr
-               && TREE_CODE (rhs) == ADDR_EXPR)
-             ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
-           else if (visit_load)
-             {
-               rhs = get_base_loadstore (rhs);
-               if (rhs)
-                 ret |= visit_load (stmt, rhs, data);
-             }
-         }
-      if (visit_addr
-         && gimple_call_chain (stmt)
-         && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
-       ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
-                          data);
-      if (visit_addr
-         && gimple_call_return_slot_opt_p (stmt)
-         && gimple_call_lhs (stmt) != NULL_TREE
-         && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
-       ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
-    }
-  else if (gimple_code (stmt) == GIMPLE_ASM)
-    {
-      unsigned noutputs;
-      const char *constraint;
-      const char **oconstraints;
-      bool allows_mem, allows_reg, is_inout;
-      noutputs = gimple_asm_noutputs (stmt);
-      oconstraints = XALLOCAVEC (const char *, noutputs);
-      if (visit_store || visit_addr)
-       for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
-         {
-           tree link = gimple_asm_output_op (stmt, i);
-           tree op = get_base_loadstore (TREE_VALUE (link));
-           if (op && visit_store)
-             ret |= visit_store (stmt, op, data);
-           if (visit_addr)
-             {
-               constraint = TREE_STRING_POINTER
-                   (TREE_VALUE (TREE_PURPOSE (link)));
-               oconstraints[i] = constraint;
-               parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
-                                        &allows_reg, &is_inout);
-               if (op && !allows_reg && allows_mem)
-                 ret |= visit_addr (stmt, op, data);
-             }
-         }
-      if (visit_load || visit_addr)
-       for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
-         {
-           tree link = gimple_asm_input_op (stmt, i);
-           tree op = TREE_VALUE (link);
-           if (visit_addr
-               && TREE_CODE (op) == ADDR_EXPR)
-             ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-           else if (visit_load || visit_addr)
-             {
-               op = get_base_loadstore (op);
-               if (op)
-                 {
-                   if (visit_load)
-                     ret |= visit_load (stmt, op, data);
-                   if (visit_addr)
-                     {
-                       constraint = TREE_STRING_POINTER
-                           (TREE_VALUE (TREE_PURPOSE (link)));
-                       parse_input_constraint (&constraint, 0, 0, noutputs,
-                                               0, oconstraints,
-                                               &allows_mem, &allows_reg);
-                       if (!allows_reg && allows_mem)
-                         ret |= visit_addr (stmt, op, data);
-                     }
-                 }
-             }
-         }
-    }
-  else if (gimple_code (stmt) == GIMPLE_RETURN)
-    {
-      tree op = gimple_return_retval (stmt);
-      if (op)
-       {
-         if (visit_addr
-             && TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-         else if (visit_load)
+
+         /* Now see if op appears in the nonnull list.  */
+         for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
            {
-             op = get_base_loadstore (op);
-             if (op)
-               ret |= visit_load (stmt, op, data);
+             int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
+             tree arg = gimple_call_arg (stmt, idx);
+             if (operand_equal_p (op, arg, 0))
+               return true;
            }
        }
     }
-  else if (visit_addr
-          && gimple_code (stmt) == GIMPLE_PHI)
-    {
-      for (i = 0; i < gimple_phi_num_args (stmt); ++i)
-       {
-         tree op = PHI_ARG_DEF (stmt, i);
-         if (TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-       }
-    }
 
-  return ret;
+  /* If this function is marked as returning non-null, then we can
+     infer OP is non-null if it is used in the return statement.  */
+  if (attribute)
+    if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
+      if (gimple_return_retval (return_stmt)
+         && operand_equal_p (gimple_return_retval (return_stmt), op, 0)
+         && lookup_attribute ("returns_nonnull",
+                              TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+       return true;
+
+  return false;
 }
 
-/* Like walk_stmt_load_store_addr_ops but with NULL visit_addr.  IPA-CP
-   should make a faster clone for this case.  */
+/* Compare two case labels.  Because the front end should already have
+   made sure that case ranges do not overlap, it is enough to only compare
+   the CASE_LOW values of each case label.  */
 
-bool
-walk_stmt_load_store_ops (gimple stmt, void *data,
-                         bool (*visit_load)(gimple, tree, void *),
-                         bool (*visit_store)(gimple, tree, void *))
+static int
+compare_case_labels (const void *p1, const void *p2)
 {
-  return walk_stmt_load_store_addr_ops (stmt, data,
-                                       visit_load, visit_store, NULL);
+  const_tree const case1 = *(const_tree const*)p1;
+  const_tree const case2 = *(const_tree const*)p2;
+
+  /* The 'default' case label always goes first.  */
+  if (!CASE_LOW (case1))
+    return -1;
+  else if (!CASE_LOW (case2))
+    return 1;
+  else
+    return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
 }
 
-/* Helper for gimple_ior_addresses_taken_1.  */
+/* Sort the case labels in LABEL_VEC in place in ascending order.  */
 
-static bool
-gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
-                             tree addr, void *data)
+void
+sort_case_labels (vec<tree> label_vec)
 {
-  bitmap addresses_taken = (bitmap)data;
-  addr = get_base_address (addr);
-  if (addr
-      && DECL_P (addr))
-    {
-      bitmap_set_bit (addresses_taken, DECL_UID (addr));
-      return true;
-    }
-  return false;
+  label_vec.qsort (compare_case_labels);
 }
+\f
+/* Prepare a vector of case labels to be used in a GIMPLE_SWITCH statement.
 
-/* Set the bit for the uid of all decls that have their address taken
-   in STMT in the ADDRESSES_TAKEN bitmap.  Returns true if there
-   were any in this stmt.  */
+   LABELS is a vector that contains all case labels to look at.
 
-bool
-gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
-{
-  return walk_stmt_load_store_addr_ops (stmt, addresses_taken, NULL, NULL,
-                                       gimple_ior_addresses_taken_1);
-}
+   INDEX_TYPE is the type of the switch index expression.  Case labels
+   in LABELS are discarded if their values are not in the value range
+   covered by INDEX_TYPE.  The remaining case label values are folded
+   to INDEX_TYPE.
 
+   If a default case exists in LABELS, it is removed from LABELS and
+   returned in DEFAULT_CASEP.  If no default case exists, but the
+   case labels already cover the whole range of INDEX_TYPE, a default
+   case is returned pointing to one of the existing case labels.
+   Otherwise DEFAULT_CASEP is set to NULL_TREE.
 
-/* Return a printable name for symbol DECL.  */
+   DEFAULT_CASEP may be NULL, in which case the above comment doesn't
+   apply and no action is taken regardless of whether a default case is
+   found or not.  */
 
-const char *
-gimple_decl_printable_name (tree decl, int verbosity)
+void
+preprocess_case_label_vec_for_gimple (vec<tree> labels,
+                                     tree index_type,
+                                     tree *default_casep)
 {
-  if (!DECL_NAME (decl))
-    return NULL;
+  tree min_value, max_value;
+  tree default_case = NULL_TREE;
+  size_t i, len;
 
-  if (DECL_ASSEMBLER_NAME_SET_P (decl))
+  i = 0;
+  min_value = TYPE_MIN_VALUE (index_type);
+  max_value = TYPE_MAX_VALUE (index_type);
+  while (i < labels.length ())
     {
-      const char *str, *mangled_str;
-      int dmgl_opts = DMGL_NO_OPTS;
+      tree elt = labels[i];
+      tree low = CASE_LOW (elt);
+      tree high = CASE_HIGH (elt);
+      bool remove_element = FALSE;
+
+      if (low)
+       {
+         gcc_checking_assert (TREE_CODE (low) == INTEGER_CST);
+         gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST);
+
+         /* This is a non-default case label, i.e. it has a value.
 
-      if (verbosity >= 2)
+            See if the case label is reachable within the range of
+            the index type.  Remove out-of-range case values.  Turn
+            case ranges into a canonical form (high > low strictly)
+            and convert the case label values to the index type.
+
+            NB: The type of gimple_switch_index() may be the promoted
+            type, but the case labels retain the original type.  */
+
+         if (high)
+           {
+             /* This is a case range.  Discard empty ranges.
+                If the bounds or the range are equal, turn this
+                into a simple (one-value) case.  */
+             int cmp = tree_int_cst_compare (high, low);
+             if (cmp < 0)
+               remove_element = TRUE;
+             else if (cmp == 0)
+               high = NULL_TREE;
+           }
+
+         if (! high)
+           {
+             /* If the simple case value is unreachable, ignore it.  */
+             if ((TREE_CODE (min_value) == INTEGER_CST
+                  && tree_int_cst_compare (low, min_value) < 0)
+                 || (TREE_CODE (max_value) == INTEGER_CST
+                     && tree_int_cst_compare (low, max_value) > 0))
+               remove_element = TRUE;
+             else
+               low = fold_convert (index_type, low);
+           }
+         else
+           {
+             /* If the entire case range is unreachable, ignore it.  */
+             if ((TREE_CODE (min_value) == INTEGER_CST
+                  && tree_int_cst_compare (high, min_value) < 0)
+                 || (TREE_CODE (max_value) == INTEGER_CST
+                     && tree_int_cst_compare (low, max_value) > 0))
+               remove_element = TRUE;
+             else
+               {
+                 /* If the lower bound is less than the index type's
+                    minimum value, truncate the range bounds.  */
+                 if (TREE_CODE (min_value) == INTEGER_CST
+                     && tree_int_cst_compare (low, min_value) < 0)
+                   low = min_value;
+                 low = fold_convert (index_type, low);
+
+                 /* If the upper bound is greater than the index type's
+                    maximum value, truncate the range bounds.  */
+                 if (TREE_CODE (max_value) == INTEGER_CST
+                     && tree_int_cst_compare (high, max_value) > 0)
+                   high = max_value;
+                 high = fold_convert (index_type, high);
+
+                 /* We may have folded a case range to a one-value case.  */
+                 if (tree_int_cst_equal (low, high))
+                   high = NULL_TREE;
+               }
+           }
+
+         CASE_LOW (elt) = low;
+         CASE_HIGH (elt) = high;
+       }
+      else
        {
-         dmgl_opts = DMGL_VERBOSE
-                     | DMGL_ANSI
-                     | DMGL_GNU_V3
-                     | DMGL_RET_POSTFIX;
-         if (TREE_CODE (decl) == FUNCTION_DECL)
-           dmgl_opts |= DMGL_PARAMS;
+         gcc_assert (!default_case);
+         default_case = elt;
+         /* The default case must be passed separately to the
+            gimple_build_switch routine.  But if DEFAULT_CASEP
+            is NULL, we do not remove the default case (it would
+            be completely lost).  */
+         if (default_casep)
+           remove_element = TRUE;
        }
 
-      mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      str = cplus_demangle_v3 (mangled_str, dmgl_opts);
-      return (str) ? str : mangled_str;
+      if (remove_element)
+       labels.ordered_remove (i);
+      else
+       i++;
+    }
+  len = i;
+
+  if (!labels.is_empty ())
+    sort_case_labels (labels);
+
+  if (default_casep && !default_case)
+    {
+      /* If the switch has no default label, add one, so that we jump
+        around the switch body.  If the labels already cover the whole
+        range of the switch index_type, add the default label pointing
+        to one of the existing labels.  */
+      if (len
+         && TYPE_MIN_VALUE (index_type)
+         && TYPE_MAX_VALUE (index_type)
+         && tree_int_cst_equal (CASE_LOW (labels[0]),
+                                TYPE_MIN_VALUE (index_type)))
+       {
+         tree low, high = CASE_HIGH (labels[len - 1]);
+         if (!high)
+           high = CASE_LOW (labels[len - 1]);
+         if (tree_int_cst_equal (high, TYPE_MAX_VALUE (index_type)))
+           {
+             for (i = 1; i < len; i++)
+               {
+                 high = CASE_LOW (labels[i]);
+                 low = CASE_HIGH (labels[i - 1]);
+                 if (!low)
+                   low = CASE_LOW (labels[i - 1]);
+                 if (wi::add (low, 1) != high)
+                   break;
+               }
+             if (i == len)
+               {
+                 tree label = CASE_LABEL (labels[0]);
+                 default_case = build_case_label (NULL_TREE, NULL_TREE,
+                                                  label);
+               }
+           }
+       }
     }
 
-  return IDENTIFIER_POINTER (DECL_NAME (decl));
+  if (default_casep)
+    *default_casep = default_case;
 }
 
-/* Return true when STMT is builtins call to CODE.  */
+/* Set the location of all statements in SEQ to LOC.  */
 
-bool
-gimple_call_builtin_p (gimple stmt, enum built_in_function code)
+void
+gimple_seq_set_location (gimple_seq seq, location_t loc)
 {
-  tree fndecl;
-  return (is_gimple_call (stmt)
-         && (fndecl = gimple_call_fndecl (stmt)) != NULL
-         && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-         && DECL_FUNCTION_CODE (fndecl) == code);
+  for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+    gimple_set_location (gsi_stmt (i), loc);
 }
 
-/* Return true if STMT clobbers memory.  STMT is required to be a
-   GIMPLE_ASM.  */
+/* Release SSA_NAMEs in SEQ as well as the GIMPLE statements.  */
 
-bool
-gimple_asm_clobbers_memory_p (const_gimple stmt)
+void
+gimple_seq_discard (gimple_seq seq)
 {
-  unsigned i;
+  gimple_stmt_iterator gsi;
 
-  for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
+  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
     {
-      tree op = gimple_asm_clobber_op (stmt, i);
-      if (strcmp (TREE_STRING_POINTER (TREE_VALUE (op)), "memory") == 0)
-       return true;
+      gimple stmt = gsi_stmt (gsi);
+      gsi_remove (&gsi, true);
+      release_defs (stmt);
+      ggc_free (stmt);
     }
-
-  return false;
 }
 
-
-/* Set the inlinable status of GIMPLE_CALL S to INLINABLE_P.  */
+/* See if STMT now calls function that takes no parameters and if so, drop
+   call arguments.  This is used when devirtualization machinery redirects
+   to __builtiln_unreacahble or __cxa_pure_virutal.  */
 
 void
-gimple_call_set_cannot_inline (gimple s, bool inlinable_p)
+maybe_remove_unused_call_args (struct function *fn, gimple stmt)
 {
-  bool prev_inlinable_p;
-
-  GIMPLE_CHECK (s, GIMPLE_CALL);
-
-  prev_inlinable_p = gimple_call_cannot_inline_p (s);
-
-  if (inlinable_p)
-    s->gsbase.subcode |= GF_CALL_CANNOT_INLINE;
-  else
-    s->gsbase.subcode &= ~GF_CALL_CANNOT_INLINE;
-
-  /* If we have changed the inlinable attribute, and there is a call
-     graph edge going out of this statement, update its inlinable
-     attribute as well.  */
-  if (current_function_decl && prev_inlinable_p != inlinable_p)
+  tree decl = gimple_call_fndecl (stmt);
+  if (TYPE_ARG_TYPES (TREE_TYPE (decl))
+      && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))) == void_type_node
+      && gimple_call_num_args (stmt))
     {
-      struct cgraph_node *n = cgraph_get_node (current_function_decl);
-      struct cgraph_edge *e = cgraph_edge (n, s);
-      if (e)
-       e->call_stmt_cannot_inline_p = inlinable_p;
+      gimple_set_num_ops (stmt, 3);
+      update_stmt_fn (fn, stmt);
     }
 }
-
-#include "gt-gimple.h"