IA MCU psABI support: changes to libraries
[gcc.git] / gcc / gimple.c
index cba3bcedf54de8bbb923298d7c6afe1c7779d146..b32c6b5ada48b122ed35e9dd8fce6045c601c737 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR support functions.
 
-   Copyright (C) 2007-2013 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,10 +24,26 @@ 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"
@@ -37,6 +53,11 @@ along with GCC; see the file COPYING3.  If not see
 #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"
 
 
 /* All the tuples have their operand vector (if present) at the very bottom
@@ -81,11 +102,6 @@ static const char * const gimple_alloc_kind_names[] = {
     "everything else"
 };
 
-/* 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.  */
@@ -95,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
@@ -127,13 +143,13 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
       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;
@@ -147,7 +163,7 @@ 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;
 }
 
 
@@ -172,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, 2);
+  greturn *s
+    = as_a <greturn *> (gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK,
+                                              2));
   if (retval)
     gimple_return_set_retval (s, retval);
   return s;
@@ -184,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));
@@ -201,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);
@@ -217,12 +237,12 @@ gimple_build_call_1 (tree fn, unsigned nargs)
 /* Build a GIMPLE_CALL statement to function FN with the arguments
    specified in vector ARGS.  */
 
-gimple
+gcall *
 gimple_build_call_vec (tree fn, vec<tree> args)
 {
   unsigned i;
   unsigned nargs = args.length ();
-  gimple call = gimple_build_call_1 (fn, nargs);
+  gcall *call = gimple_build_call_1 (fn, nargs);
 
   for (i = 0; i < nargs; i++)
     gimple_call_set_arg (call, i, args[i]);
@@ -234,11 +254,11 @@ gimple_build_call_vec (tree fn, vec<tree> 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));
@@ -257,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));
@@ -278,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;
@@ -292,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);
@@ -312,11 +334,11 @@ 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
+gcall *
 gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
 {
   unsigned i, nargs;
-  gimple call;
+  gcall *call;
 
   nargs = args.length ();
   call = gimple_build_call_internal_1 (fn, nargs);
@@ -331,11 +353,11 @@ gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> 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);
@@ -362,65 +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;
 }
 
 
-/* Return index of INDEX's non bound argument of the call.  */
-
-unsigned
-gimple_call_get_nobnd_arg_index (const_gimple gs, unsigned index)
-{
-  unsigned num_args = gimple_call_num_args (gs);
-  for (unsigned n = 0; n < num_args; n++)
-    {
-      if (POINTER_BOUNDS_P (gimple_call_arg (gs, n)))
-       continue;
-      else if (index)
-       index--;
-      else
-       return n;
-    }
-
-  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 (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 subcode SUBCODE and operands
-   OP1 and OP2.  If OP2 is NULL then SUBCODE must be of class
-   GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS.  */
+   OP1, OP2 and OP3.  */
 
-gimple
-gimple_build_assign_with_ops (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)
@@ -438,12 +440,34 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
   return p;
 }
 
-gimple
-gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
-                             tree op2 MEM_STAT_DECL)
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+   OP1, OP2 and OP3.  */
+
+gassign *
+gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
+                    tree op2, tree op3 MEM_STAT_DECL)
 {
-  return gimple_build_assign_with_ops (subcode, lhs, op1, op2, NULL_TREE
-                                      PASS_MEM_STAT);
+  return gimple_build_assign_1 (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
+}
+
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
+   OP1 and OP2.  */
+
+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);
+}
+
+/* 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)
+{
+  return gimple_build_assign_1 (lhs, subcode, op1, NULL_TREE, NULL_TREE
+                               PASS_MEM_STAT);
 }
 
 
@@ -453,14 +477,14 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
    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);
@@ -471,7 +495,7 @@ gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
 /* 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;
@@ -485,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;
@@ -496,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;
 }
@@ -528,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);
@@ -548,25 +574,26 @@ 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);
 
   if (GATHER_STATISTICS)
     gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
@@ -585,12 +612,12 @@ 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
+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,
@@ -619,10 +646,10 @@ gimple_build_asm_vec (const char *string, vec<tree, va_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);
@@ -635,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);
@@ -648,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);
@@ -662,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;
@@ -678,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);
@@ -712,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;
 }
 
@@ -726,13 +754,14 @@ 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.  */
   gcc_checking_assert (default_label);
-  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
-                                   1 + 1 + nlabels);
+  gswitch *p = as_a <gswitch *> (gimple_build_with_ops (GIMPLE_SWITCH,
+                                                       ERROR_MARK,
+                                                       1 + 1 + nlabels));
   gimple_switch_set_index (p, index);
   gimple_switch_set_default_label (p, default_label);
   return p;
@@ -744,12 +773,12 @@ gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
    DEFAULT_LABEL is the default label
    ARGS is a vector of labels excluding the default.  */
 
-gimple
+gswitch *
 gimple_build_switch (tree index, tree default_label, vec<tree> args)
 {
   unsigned i, nlabels = args.length ();
 
-  gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
+  gswitch *p = gimple_build_switch_nlabels (nlabels, index, default_label);
 
   /* Copy the labels from the vector to the switch statement.  */
   for (i = 0; i < nlabels; i++)
@@ -760,11 +789,13 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args)
 
 /* 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;
 }
 
@@ -772,13 +803,13 @@ 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)
@@ -792,13 +823,15 @@ 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);
@@ -814,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);
@@ -829,23 +863,22 @@ gimple_build_omp_critical (gimple_seq body, tree name)
 
    BODY is sequence of statements inside the for loop.
    KIND is the `for' variant.
-   CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate,
-   lastprivate, reductions, ordered, schedule, and nowait.
+   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
+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);
   gimple_omp_for_set_kind (p, kind);
-  p->gimple_omp_for.collapse = collapse;
-  p->gimple_omp_for.iter
-      = ggc_alloc_cleared_vec_gimple_omp_for_iter (collapse);
+  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);
 
@@ -860,11 +893,12 @@ gimple_build_omp_for (gimple_seq body, int kind, 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);
@@ -884,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);
@@ -954,10 +988,11 @@ gimple_build_omp_taskgroup (gimple_seq body)
    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;
@@ -999,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);
@@ -1026,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);
@@ -1041,12 +1078,14 @@ 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.
-   CLAUSES are any of the OMP target construct's clauses.  */
+   KIND is the kind of the region.
+   CLAUSES are any of the construct's clauses.  */
 
-gimple
+gomp_target *
 gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_TARGET, 0);
+  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);
@@ -1061,10 +1100,10 @@ gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
    BODY is the sequence of statements that will be executed.
    CLAUSES are any of the OMP teams construct's clauses.  */
 
-gimple
+gomp_teams *
 gimple_build_omp_teams (gimple_seq body, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_TEAMS, 0);
+  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);
@@ -1075,10 +1114,11 @@ gimple_build_omp_teams (gimple_seq body, tree clauses)
 
 /* 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;
@@ -1088,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;
@@ -1133,8 +1175,8 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
                  gimple_code_name[code],
                  get_tree_code_name (subcode),
                  gimple_code_name[gimple_code (gs)],
-                 gs->gsbase.subcode > 0
-                   ? get_tree_code_name ((enum tree_code) gs->gsbase.subcode)
+                 gs->subcode > 0
+                   ? get_tree_code_name ((enum tree_code) gs->subcode)
                    : "",
                  function, trim_filename (file), line);
 }
@@ -1187,6 +1229,21 @@ gimple_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
   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
@@ -1254,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;
 }
 
@@ -1297,600 +1354,6 @@ gimple_seq_copy (gimple_seq src)
 }
 
 
-/* Walk all the statements in the sequence *PSEQ 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.  */
-
-gimple
-walk_gimple_seq_mod (gimple_seq *pseq, walk_stmt_fn callback_stmt,
-                    walk_tree_fn callback_op, struct walk_stmt_info *wi)
-{
-  gimple_stmt_iterator gsi;
-
-  for (gsi = gsi_start (*pseq); !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;
-
-         return wi->removed_stmt ? NULL : gsi_stmt (gsi);
-       }
-
-      if (!wi->removed_stmt)
-       gsi_next (&gsi);
-    }
-
-  if (wi)
-    wi->callback_result = NULL_TREE;
-
-  return NULL;
-}
-
-
-/* Like walk_gimple_seq_mod, but ensure that the head of SEQ isn't
-   changed by the callbacks.  */
-
-gimple
-walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
-                walk_tree_fn callback_op, struct walk_stmt_info *wi)
-{
-  gimple_seq seq2 = seq;
-  gimple ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
-  gcc_assert (seq2 == seq);
-  return ret;
-}
-
-
-/* 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)
-{
-  tree ret, op;
-  unsigned noutputs;
-  const char **oconstraints;
-  unsigned i, n;
-  const char *constraint;
-  bool allows_mem, allows_reg, is_inout;
-
-  noutputs = gimple_asm_noutputs (stmt);
-  oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
-
-  if (wi)
-    wi->is_lhs = true;
-
-  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;
-    }
-
-  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_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
-       }
-
-      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 is of a non-renamable type or is a register variable,
-            we may use a COMPONENT_REF on the LHS.  */
-         tree rhs1 = gimple_assign_rhs1 (stmt);
-         wi->val_only
-           = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
-             || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
-         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_TARGET:
-      ret = walk_tree (gimple_omp_target_clauses_ptr (stmt), callback_op, wi,
-                      pset);
-      if (ret)
-       return ret;
-      break;
-
-    case GIMPLE_OMP_TEAMS:
-      ret = walk_tree (gimple_omp_teams_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;
-
-    case GIMPLE_OMP_RETURN:
-      ret = walk_tree (gimple_omp_return_lhs_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_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_mod (gimple_bind_body_ptr (stmt), callback_stmt,
-                                callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_CATCH:
-      ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (stmt), callback_stmt,
-                                callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_EH_FILTER:
-      ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_EH_ELSE:
-      ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_TRY:
-      ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
-                            wi);
-      if (ret)
-       return wi->callback_result;
-
-      ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_OMP_FOR:
-      ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (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_TASKGROUP:
-    case GIMPLE_OMP_ORDERED:
-    case GIMPLE_OMP_SECTION:
-    case GIMPLE_OMP_PARALLEL:
-    case GIMPLE_OMP_TASK:
-    case GIMPLE_OMP_SECTIONS:
-    case GIMPLE_OMP_SINGLE:
-    case GIMPLE_OMP_TARGET:
-    case GIMPLE_OMP_TEAMS:
-      ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_WITH_CLEANUP_EXPR:
-      ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
-                            callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    case GIMPLE_TRANSACTION:
-      ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
-                            callback_stmt, callback_op, wi);
-      if (ret)
-       return wi->callback_result;
-      break;
-
-    default:
-      gcc_assert (!gimple_has_substatements (stmt));
-      break;
-    }
-
-  return NULL;
-}
-
 
 /* Return true if calls C1 and C2 are known to go to the same function.  */
 
@@ -1922,7 +1385,7 @@ gimple_call_flags (const_gimple stmt)
   else
     flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
 
-  if (stmt->gsbase.subcode & GF_CALL_NOTHROW)
+  if (stmt->subcode & GF_CALL_NOTHROW)
     flags |= ECF_NOTHROW;
 
   return flags;
@@ -1930,11 +1393,14 @@ gimple_call_flags (const_gimple stmt)
 
 /* Return the "fn spec" string for call STMT.  */
 
-static tree
-gimple_call_fnspec (const_gimple stmt)
+static const_tree
+gimple_call_fnspec (const gcall *stmt)
 {
   tree type, attr;
 
+  if (gimple_call_internal_p (stmt))
+    return internal_fn_fnspec (gimple_call_internal_fn (stmt));
+
   type = gimple_call_fntype (stmt);
   if (!type)
     return NULL_TREE;
@@ -1949,9 +1415,9 @@ gimple_call_fnspec (const_gimple stmt)
 /* 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;
@@ -1983,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;
@@ -2063,30 +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_safe_length (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 (label_to_block_map, new_len);
+             vec_safe_grow_cleared (label_to_block_map_for_fn (cfun),
+                                    new_len);
            }
        }
 
-      (*label_to_block_map)[uid] = bb;
+      (*label_to_block_map_for_fn (cfun))[uid] = bb;
     }
 }
 
@@ -2115,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);
 }
 
 
@@ -2126,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);
@@ -2219,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:
@@ -2258,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,
@@ -2277,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:
@@ -2301,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:
@@ -2325,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:
@@ -2381,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))
@@ -2422,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);
@@ -2529,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                                             \
@@ -2549,85 +2052,6 @@ const unsigned char gimple_rhs_class_table[] = {
 #undef DEFTREECODE
 #undef END_OF_BASE_TREE_CODES
 
-/* 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);
-
-  /* ???  Either the alias oracle or all callers need to properly deal
-     with WITH_SIZE_EXPRs before we can look through those.  */
-  if (TREE_CODE (t) == WITH_SIZE_EXPR)
-    return NULL_TREE;
-
-  return t;
-}
-
-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.  */
@@ -2673,14 +2097,13 @@ canonicalize_cond_expr_cond (tree t)
 /* 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)
+gcall *
+gimple_call_copy_skip_args (gcall *stmt, bitmap args_to_skip)
 {
   int i;
   int nargs = gimple_call_num_args (stmt);
-  vec<tree> vargs;
-  vargs.create (nargs);
-  gimple new_stmt;
+  auto_vec<tree> vargs (nargs);
+  gcall *new_stmt;
 
   for (i = 0; i < nargs; i++)
     if (!bitmap_bit_p (args_to_skip, i))
@@ -2691,7 +2114,7 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
                                               vargs);
   else
     new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
-  vargs.release ();
+
   if (gimple_call_lhs (stmt))
     gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
 
@@ -2742,8 +2165,8 @@ gimple_compare_field_offset (tree f1, tree 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))
+  if (tree_fits_shwi_p (DECL_FIELD_OFFSET (f1))
+      && tree_fits_shwi_p (DECL_FIELD_OFFSET (f2)))
     {
       unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
       unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
@@ -2769,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
@@ -2786,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;
@@ -2902,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))
@@ -2996,256 +2429,10 @@ gimple_get_alias_set (tree t)
 }
 
 
-/* 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.  */
-
-static tree
-get_base_loadstore (tree op)
-{
-  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;
-}
-
-/* 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.  */
-
-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 *))
-{
-  bool ret = false;
-  unsigned i;
-  if (gimple_assign_single_p (stmt))
-    {
-      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);
-       }
-    }
-  else if (visit_addr
-          && (is_gimple_assign (stmt)
-              || gimple_code (stmt) == GIMPLE_COND))
-    {
-      for (i = 0; i < gimple_num_ops (stmt); ++i)
-       {
-         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);
-           }
-       }
-    }
-  else if (is_gimple_call (stmt))
-    {
-      if (visit_store)
-       {
-         tree lhs = gimple_call_lhs (stmt);
-         if (lhs)
-           {
-             lhs = get_base_loadstore (lhs);
-             if (lhs)
-               ret |= visit_store (stmt, lhs, data);
-           }
-       }
-      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)
-           {
-             op = get_base_loadstore (op);
-             if (op)
-               ret |= visit_load (stmt, op, data);
-           }
-       }
-    }
-  else if (visit_addr
-          && gimple_code (stmt) == GIMPLE_PHI)
-    {
-      for (i = 0; i < gimple_phi_num_args (stmt); ++i)
-       {
-         tree op = gimple_phi_arg_def (stmt, i);
-         if (TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-       }
-    }
-  else if (visit_addr
-          && gimple_code (stmt) == GIMPLE_GOTO)
-    {
-      tree op = gimple_goto_dest (stmt);
-      if (TREE_CODE (op) == ADDR_EXPR)
-       ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-    }
-
-  return ret;
-}
-
-/* Like walk_stmt_load_store_addr_ops but with NULL visit_addr.  IPA-CP
-   should make a faster clone for this case.  */
-
-bool
-walk_stmt_load_store_ops (gimple stmt, void *data,
-                         bool (*visit_load)(gimple, tree, void *),
-                         bool (*visit_store)(gimple, tree, void *))
-{
-  return walk_stmt_load_store_addr_ops (stmt, data,
-                                       visit_load, visit_store, NULL);
-}
-
 /* Helper for gimple_ior_addresses_taken_1.  */
 
 static bool
-gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
-                             tree addr, void *data)
+gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
 {
   bitmap addresses_taken = (bitmap)data;
   addr = get_base_address (addr);
@@ -3270,27 +2457,37 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
 }
 
 
-/* Return TRUE iff stmt is a call to a built-in function.  */
-
-bool
-is_gimple_builtin_call (gimple stmt)
-{
-  tree callee;
+/* Return true if TYPE1 and TYPE2 are compatible enough for builtin
+   processing.  */
 
-  if (is_gimple_call (stmt)
-      && (callee = gimple_call_fndecl (stmt))
-      && is_builtin_fn (callee)
-      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
-    return true;
-
-  return false;
+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;
 }
 
-/* Return true when STMTs arguments match those of FNDECL.  */
+/* Return true when STMTs arguments and return value match those of FNDECL,
+   a decl of a builtin function.  */
 
-static bool
-validate_call (gimple stmt, tree fndecl)
+bool
+gimple_builtin_call_types_compatible_p (const_gimple stmt, tree fndecl)
 {
+  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)
@@ -3299,14 +2496,7 @@ validate_call (gimple stmt, tree fndecl)
       if (!targs)
        return true;
       tree arg = gimple_call_arg (stmt, i);
-      if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
-         && INTEGRAL_TYPE_P (TREE_VALUE (targs)))
-       ;
-      else if (POINTER_TYPE_P (TREE_TYPE (arg))
-              && POINTER_TYPE_P (TREE_VALUE (targs)))
-       ;
-      else if (TREE_CODE (TREE_TYPE (arg))
-              != TREE_CODE (TREE_VALUE (targs)))
+      if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs)))
        return false;
       targs = TREE_CHAIN (targs);
     }
@@ -3315,30 +2505,43 @@ validate_call (gimple stmt, tree fndecl)
   return true;
 }
 
+/* Return true when STMT is builtins call.  */
+
+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;
+}
+
 /* Return true when STMT is builtins call to CLASS.  */
 
 bool
-gimple_call_builtin_p (gimple stmt, enum built_in_class klass)
+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 validate_call (stmt, fndecl);
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
   return false;
 }
 
 /* Return true when STMT is builtins call to CODE of CLASS.  */
 
 bool
-gimple_call_builtin_p (gimple stmt, enum built_in_function code)
+gimple_call_builtin_p (const_gimple stmt, enum built_in_function code)
 {
   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 validate_call (stmt, fndecl);
+    return gimple_builtin_call_types_compatible_p (stmt, fndecl);
   return false;
 }
 
@@ -3346,7 +2549,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_function code)
    GIMPLE_ASM.  */
 
 bool
-gimple_asm_clobbers_memory_p (const_gimple stmt)
+gimple_asm_clobbers_memory_p (const gasm *stmt)
 {
   unsigned i;
 
@@ -3402,8 +2605,28 @@ nonfreeing_call_p (gimple call)
        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;
+      }
 
-  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.
@@ -3414,7 +2637,7 @@ nonfreeing_call_p (gimple call)
    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 stmt ATTRIBUTE_UNUSED, tree op, void *data)
+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))
@@ -3422,10 +2645,16 @@ check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
   return false;
 }
 
-/* If OP can be inferred to be non-zero after STMT executes, return true.  */
+/* 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)
+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.  */
@@ -3434,11 +2663,13 @@ infer_nonnull_range (gimple stmt, tree op)
       || gimple_code (stmt) == GIMPLE_ASM)
     return false;
 
-  if (walk_stmt_load_store_ops (stmt, (void *)op,
-                               check_loadstore, check_loadstore))
+  if (dereference
+      && walk_stmt_load_store_ops (stmt, (void *)op,
+                                  check_loadstore, check_loadstore))
     return true;
 
-  if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
+  if (attribute
+      && is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
     {
       tree fntype = gimple_call_fntype (stmt);
       tree attrs = TYPE_ATTRIBUTES (fntype);
@@ -3457,8 +2688,8 @@ infer_nonnull_range (gimple stmt, tree op)
            {
              for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
                {
-                 if (operand_equal_p (op, gimple_call_arg (stmt, i), 0)
-                     && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (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;
@@ -3477,12 +2708,13 @@ infer_nonnull_range (gimple stmt, tree op)
 
   /* 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 (gimple_code (stmt) == GIMPLE_RETURN
-      && gimple_return_retval (stmt)
-      && operand_equal_p (gimple_return_retval (stmt), op, 0)
-      && lookup_attribute ("returns_nonnull",
-                          TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
-    return true;
+  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;
 }
@@ -3668,11 +2900,7 @@ preprocess_case_label_vec_for_gimple (vec<tree> labels,
                  low = CASE_HIGH (labels[i - 1]);
                  if (!low)
                    low = CASE_LOW (labels[i - 1]);
-                 if ((TREE_INT_CST_LOW (low) + 1
-                      != TREE_INT_CST_LOW (high))
-                     || (TREE_INT_CST_HIGH (low)
-                         + (TREE_INT_CST_LOW (high) == 0)
-                         != TREE_INT_CST_HIGH (high)))
+                 if (wi::add (low, 1) != high)
                    break;
                }
              if (i == len)
@@ -3688,3 +2916,45 @@ preprocess_case_label_vec_for_gimple (vec<tree> labels,
   if (default_casep)
     *default_casep = default_case;
 }
+
+/* Set the location of all statements in SEQ to LOC.  */
+
+void
+gimple_seq_set_location (gimple_seq seq, location_t loc)
+{
+  for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+    gimple_set_location (gsi_stmt (i), loc);
+}
+
+/* Release SSA_NAMEs in SEQ as well as the GIMPLE statements.  */
+
+void
+gimple_seq_discard (gimple_seq seq)
+{
+  gimple_stmt_iterator gsi;
+
+  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
+    {
+      gimple stmt = gsi_stmt (gsi);
+      gsi_remove (&gsi, true);
+      release_defs (stmt);
+      ggc_free (stmt);
+    }
+}
+
+/* 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
+maybe_remove_unused_call_args (struct function *fn, gimple stmt)
+{
+  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))
+    {
+      gimple_set_num_ops (stmt, 3);
+      update_stmt_fn (fn, stmt);
+    }
+}