]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/var-tracking.c
[21/77] Replace SCALAR_INT_MODE_P checks with is_a <scalar_int_mode>
[gcc.git] / gcc / var-tracking.c
index ee16aed3564622c9d60b96d2a47d94bd66805776..83a9e5af524caf90997212c9ccbc0dba31670fa8 100644 (file)
@@ -1,5 +1,5 @@
 /* Variable tracking routines for the GNU compiler.
-   Copyright (C) 2002-2014 Free Software Foundation, Inc.
+   Copyright (C) 2002-2017 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
 #include "tree.h"
-#include "varasm.h"
-#include "stor-layout.h"
-#include "pointer-set.h"
-#include "hash-table.h"
-#include "basic-block.h"
+#include "cfghooks.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "memmodel.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
-#include "flags.h"
 #include "insn-config.h"
-#include "reload.h"
-#include "sbitmap.h"
-#include "alloc-pool.h"
-#include "fibheap.h"
 #include "regs.h"
-#include "expr.h"
-#include "tree-pass.h"
-#include "bitmap.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic.h"
+#include "varasm.h"
+#include "stor-layout.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "reload.h"
+#include "calls.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
 #include "cselib.h"
-#include "target.h"
 #include "params.h"
-#include "diagnostic.h"
 #include "tree-pretty-print.h"
-#include "recog.h"
-#include "tm_p.h"
-#include "alias.h"
+#include "rtl-iter.h"
+#include "fibonacci_heap.h"
+
+typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
+typedef fibonacci_node <long, basic_block_def> bb_heap_node_t;
 
 /* var-tracking.c assumes that tree code with the same value as VALUE rtx code
    has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
@@ -169,7 +169,7 @@ enum emit_note_where
 };
 
 /* Structure holding information about micro operation.  */
-typedef struct micro_operation_def
+struct micro_operation
 {
   /* Type of micro operation.  */
   enum micro_operation_type type;
@@ -179,7 +179,7 @@ typedef struct micro_operation_def
      instruction or note in the original flow (before any var-tracking
      notes are inserted, to simplify emission of notes), for MO_SET
      and MO_CLOBBER.  */
-  rtx insn;
+  rtx_insn *insn;
 
   union {
     /* Location.  For MO_SET and MO_COPY, this is the SET that
@@ -193,7 +193,7 @@ typedef struct micro_operation_def
     /* Stack adjustment.  */
     HOST_WIDE_INT adjust;
   } u;
-} micro_operation;
+};
 
 
 /* A declaration of a variable, or an RTL value being handled like a
@@ -242,10 +242,10 @@ dv_as_opaque (decl_or_value dv)
    register is described by a chain of these structures.
    The chains are pretty short (usually 1 or 2 elements) and thus
    chain is the best data structure.  */
-typedef struct attrs_def
+struct attrs
 {
   /* Pointer to next member of the list.  */
-  struct attrs_def *next;
+  attrs *next;
 
   /* The rtx of register.  */
   rtx loc;
@@ -255,13 +255,13 @@ typedef struct attrs_def
 
   /* Offset from start of DECL.  */
   HOST_WIDE_INT offset;
-} *attrs;
+};
 
 /* Structure for chaining the locations.  */
-typedef struct location_chain_def
+struct location_chain
 {
   /* Next element in the chain.  */
-  struct location_chain_def *next;
+  location_chain *next;
 
   /* The location (REG, MEM or VALUE).  */
   rtx loc;
@@ -271,29 +271,29 @@ typedef struct location_chain_def
 
   /* Initialized? */
   enum var_init_status init;
-} *location_chain;
+};
 
 /* A vector of loc_exp_dep holds the active dependencies of a one-part
    DV on VALUEs, i.e., the VALUEs expanded so as to form the current
    location of DV.  Each entry is also part of VALUE' s linked-list of
    backlinks back to DV.  */
-typedef struct loc_exp_dep_s
+struct loc_exp_dep
 {
   /* The dependent DV.  */
   decl_or_value dv;
   /* The dependency VALUE or DECL_DEBUG.  */
   rtx value;
   /* The next entry in VALUE's backlinks list.  */
-  struct loc_exp_dep_s *next;
+  struct loc_exp_dep *next;
   /* A pointer to the pointer to this entry (head or prev's next) in
      the doubly-linked list.  */
-  struct loc_exp_dep_s **pprev;
-} loc_exp_dep;
+  struct loc_exp_dep **pprev;
+};
 
 
 /* This data structure holds information about the depth of a variable
    expansion.  */
-typedef struct expand_depth_struct
+struct expand_depth
 {
   /* This measures the complexity of the expanded expression.  It
      grows by one for each level of expansion that adds more than one
@@ -302,7 +302,7 @@ typedef struct expand_depth_struct
   /* This counts the number of ENTRY_VALUE expressions in an
      expansion.  We want to minimize their use.  */
   int entryvals;
-} expand_depth;
+};
 
 /* This data structure is allocated for one-part variables at the time
    of emitting notes.  */
@@ -328,10 +328,10 @@ struct onepart_aux
 };
 
 /* Structure describing one part of variable.  */
-typedef struct variable_part_def
+struct variable_part
 {
   /* Chain of locations of the part.  */
-  location_chain loc_chain;
+  location_chain *loc_chain;
 
   /* Location which was last emitted to location list.  */
   rtx cur_loc;
@@ -344,14 +344,14 @@ typedef struct variable_part_def
     /* Pointer to auxiliary data, if var->onepart and emit_notes.  */
     struct onepart_aux *onepaux;
   } aux;
-} variable_part;
+};
 
 /* Maximum number of location parts.  */
 #define MAX_VAR_PARTS 16
 
 /* Enumeration type used to discriminate various types of one-part
    variables.  */
-typedef enum onepart_enum
+enum onepart_enum
 {
   /* Not a one-part variable.  */
   NOT_ONEPART = 0,
@@ -361,10 +361,10 @@ typedef enum onepart_enum
   ONEPART_DEXPR = 2,
   /* A VALUE.  */
   ONEPART_VALUE = 3
-} onepart_enum_t;
+};
 
 /* Structure describing where the variable is located.  */
-typedef struct variable_def
+struct variable
 {
   /* The declaration of the variable, or an RTL value being handled
      like a declaration.  */
@@ -385,28 +385,27 @@ typedef struct variable_def
 
   /* The variable parts.  */
   variable_part var_part[1];
-} *variable;
-typedef const struct variable_def *const_variable;
+};
 
 /* Pointer to the BB's information specific to variable tracking pass.  */
-#define VTI(BB) ((variable_tracking_info) (BB)->aux)
+#define VTI(BB) ((variable_tracking_info *) (BB)->aux)
 
 /* Macro to access MEM_OFFSET as an HOST_WIDE_INT.  Evaluates MEM twice.  */
 #define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
 
-#if ENABLE_CHECKING && (GCC_VERSION >= 2007)
+#if CHECKING_P && (GCC_VERSION >= 2007)
 
 /* Access VAR's Ith part's offset, checking that it's not a one-part
    variable.  */
 #define VAR_PART_OFFSET(var, i) __extension__                  \
-(*({  variable const __v = (var);                              \
+(*({  variable *const __v = (var);                             \
       gcc_checking_assert (!__v->onepart);                     \
       &__v->var_part[(i)].aux.offset; }))
 
 /* Access VAR's one-part auxiliary data, checking that it is a
    one-part variable.  */
 #define VAR_LOC_1PAUX(var) __extension__                       \
-(*({  variable const __v = (var);                              \
+(*({  variable *const __v = (var);                             \
       gcc_checking_assert (__v->onepart);                      \
       &__v->var_part[0].aux.onepaux; }))
 
@@ -465,20 +464,19 @@ static void variable_htab_free (void *);
 
 /* Variable hashtable helpers.  */
 
-struct variable_hasher
+struct variable_hasher : pointer_hash <variable>
 {
-  typedef variable_def value_type;
-  typedef void compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
-  static inline void remove (value_type *);
+  typedef void *compare_type;
+  static inline hashval_t hash (const variable *);
+  static inline bool equal (const variable *, const void *);
+  static inline void remove (variable *);
 };
 
 /* The hash function for variable_htab, computes the hash value
    from the declaration of variable X.  */
 
 inline hashval_t
-variable_hasher::hash (const value_type *v)
+variable_hasher::hash (const variable *v)
 {
   return dv_htab_hash (v->dv);
 }
@@ -486,7 +484,7 @@ variable_hasher::hash (const value_type *v)
 /* Compare the declaration of variable X with declaration Y.  */
 
 inline bool
-variable_hasher::equal (const value_type *v, const compare_type *y)
+variable_hasher::equal (const variable *v, const void *y)
 {
   decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
 
@@ -496,58 +494,58 @@ variable_hasher::equal (const value_type *v, const compare_type *y)
 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
 
 inline void
-variable_hasher::remove (value_type *var)
+variable_hasher::remove (variable *var)
 {
   variable_htab_free (var);
 }
 
-typedef hash_table <variable_hasher> variable_table_type;
+typedef hash_table<variable_hasher> variable_table_type;
 typedef variable_table_type::iterator variable_iterator_type;
 
 /* Structure for passing some other parameters to function
    emit_note_insn_var_location.  */
-typedef struct emit_note_data_def
+struct emit_note_data
 {
   /* The instruction which the note will be emitted before/after.  */
-  rtx insn;
+  rtx_insn *insn;
 
   /* Where the note will be emitted (before/after insn)?  */
   enum emit_note_where where;
 
   /* The variables and values active at this point.  */
-  variable_table_type vars;
-} emit_note_data;
+  variable_table_type *vars;
+};
 
 /* Structure holding a refcounted hash table.  If refcount > 1,
    it must be first unshared before modified.  */
-typedef struct shared_hash_def
+struct shared_hash
 {
   /* Reference count.  */
   int refcount;
 
   /* Actual hash table.  */
-  variable_table_type htab;
-} *shared_hash;
+  variable_table_type *htab;
+};
 
 /* Structure holding the IN or OUT set for a basic block.  */
-typedef struct dataflow_set_def
+struct dataflow_set
 {
   /* Adjustment of stack offset.  */
   HOST_WIDE_INT stack_adjust;
 
   /* Attributes for registers (lists of attrs).  */
-  attrs regs[FIRST_PSEUDO_REGISTER];
+  attrs *regs[FIRST_PSEUDO_REGISTER];
 
   /* Variable locations.  */
-  shared_hash vars;
+  shared_hash *vars;
 
   /* Vars that is being traversed.  */
-  shared_hash traversed_vars;
-} dataflow_set;
+  shared_hash *traversed_vars;
+};
 
 /* The structure (one for each basic block) containing the information
    needed for variable tracking.  */
-typedef struct variable_tracking_info_def
+struct variable_tracking_info
 {
   /* The vector of micro operations.  */
   vec<micro_operation> mos;
@@ -568,28 +566,33 @@ typedef struct variable_tracking_info_def
   /* Has the block been flooded in VTA?  */
   bool flooded;
 
-} *variable_tracking_info;
+};
 
 /* Alloc pool for struct attrs_def.  */
-static alloc_pool attrs_pool;
+object_allocator<attrs> attrs_pool ("attrs pool");
 
 /* Alloc pool for struct variable_def with MAX_VAR_PARTS entries.  */
-static alloc_pool var_pool;
+
+static pool_allocator var_pool
+  ("variable_def pool", sizeof (variable) +
+   (MAX_VAR_PARTS - 1) * sizeof (((variable *)NULL)->var_part[0]));
 
 /* Alloc pool for struct variable_def with a single var_part entry.  */
-static alloc_pool valvar_pool;
+static pool_allocator valvar_pool
+  ("small variable_def pool", sizeof (variable));
 
-/* Alloc pool for struct location_chain_def.  */
-static alloc_pool loc_chain_pool;
+/* Alloc pool for struct location_chain.  */
+static object_allocator<location_chain> location_chain_pool
+  ("location_chain pool");
 
-/* Alloc pool for struct shared_hash_def.  */
-static alloc_pool shared_hash_pool;
+/* Alloc pool for struct shared_hash.  */
+static object_allocator<shared_hash> shared_hash_pool ("shared_hash pool");
 
 /* Alloc pool for struct loc_exp_dep_s for NOT_ONEPART variables.  */
-static alloc_pool loc_exp_dep_pool;
+object_allocator<loc_exp_dep> loc_exp_dep_pool ("loc_exp_dep pool");
 
 /* Changed variables, notes will be emitted for them.  */
-static variable_table_type changed_variables;
+static variable_table_type *changed_variables;
 
 /* Shall notes be emitted?  */
 static bool emit_notes;
@@ -597,23 +600,23 @@ static bool emit_notes;
 /* Values whose dynamic location lists have gone empty, but whose
    cselib location lists are still usable.  Use this to hold the
    current location, the backlinks, etc, during emit_notes.  */
-static variable_table_type dropped_values;
+static variable_table_type *dropped_values;
 
 /* Empty shared hashtable.  */
-static shared_hash empty_shared_hash;
+static shared_hash *empty_shared_hash;
 
 /* Scratch register bitmap used by cselib_expand_value_rtx.  */
 static bitmap scratch_regs = NULL;
 
 #ifdef HAVE_window_save
-typedef struct GTY(()) parm_reg {
+struct GTY(()) parm_reg {
   rtx outgoing;
   rtx incoming;
-} parm_reg_t;
+};
 
 
 /* Vector of windowed parameter registers, if any.  */
-static vec<parm_reg_t, va_gc> *windowed_parm_regs = NULL;
+static vec<parm_reg, va_gc> *windowed_parm_regs = NULL;
 #endif
 
 /* Variable used to tell whether cselib_process_insn called our hook.  */
@@ -622,20 +625,20 @@ static bool cselib_hook_called;
 /* Local function prototypes.  */
 static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
                                          HOST_WIDE_INT *);
-static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
+static void insn_stack_adjust_offset_pre_post (rtx_insn *, HOST_WIDE_INT *,
                                               HOST_WIDE_INT *);
 static bool vt_stack_adjustments (void);
 
-static void init_attrs_list_set (attrs *);
-static void attrs_list_clear (attrs *);
-static attrs attrs_list_member (attrs, decl_or_value, HOST_WIDE_INT);
-static void attrs_list_insert (attrs *, decl_or_value, HOST_WIDE_INT, rtx);
-static void attrs_list_copy (attrs *, attrs);
-static void attrs_list_union (attrs *, attrs);
+static void init_attrs_list_set (attrs **);
+static void attrs_list_clear (attrs **);
+static attrs *attrs_list_member (attrs *, decl_or_value, HOST_WIDE_INT);
+static void attrs_list_insert (attrs **, decl_or_value, HOST_WIDE_INT, rtx);
+static void attrs_list_copy (attrs **, attrs *);
+static void attrs_list_union (attrs **, attrs *);
 
-static variable_def **unshare_variable (dataflow_set *set, variable_def **slot,
-                                       variable var, enum var_init_status);
-static void vars_copy (variable_table_type, variable_table_type);
+static variable **unshare_variable (dataflow_set *set, variable **slot,
+                                       variable *var, enum var_init_status);
+static void vars_copy (variable_table_type *, variable_table_type *);
 static tree var_debug_decl (tree);
 static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
 static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
@@ -652,44 +655,43 @@ static void dataflow_set_clear (dataflow_set *);
 static void dataflow_set_copy (dataflow_set *, dataflow_set *);
 static int variable_union_info_cmp_pos (const void *, const void *);
 static void dataflow_set_union (dataflow_set *, dataflow_set *);
-static location_chain find_loc_in_1pdv (rtx, variable, variable_table_type);
+static location_chain *find_loc_in_1pdv (rtx, variable *,
+                                        variable_table_type *);
 static bool canon_value_cmp (rtx, rtx);
 static int loc_cmp (rtx, rtx);
 static bool variable_part_different_p (variable_part *, variable_part *);
-static bool onepart_variable_different_p (variable, variable);
-static bool variable_different_p (variable, variable);
+static bool onepart_variable_different_p (variable *, variable *);
+static bool variable_different_p (variable *, variable *);
 static bool dataflow_set_different (dataflow_set *, dataflow_set *);
 static void dataflow_set_destroy (dataflow_set *);
 
-static bool contains_symbol_ref (rtx);
 static bool track_expr_p (tree, bool);
 static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
-static int add_uses (rtx *, void *);
 static void add_uses_1 (rtx *, void *);
 static void add_stores (rtx, const_rtx, void *);
 static bool compute_bb_dataflow (basic_block);
 static bool vt_find_locations (void);
 
-static void dump_attrs_list (attrs);
-static void dump_var (variable);
-static void dump_vars (variable_table_type);
+static void dump_attrs_list (attrs *);
+static void dump_var (variable *);
+static void dump_vars (variable_table_type *);
 static void dump_dataflow_set (dataflow_set *);
 static void dump_dataflow_sets (void);
 
 static void set_dv_changed (decl_or_value, bool);
-static void variable_was_changed (variable, dataflow_set *);
-static variable_def **set_slot_part (dataflow_set *, rtx, variable_def **,
-                                    decl_or_value, HOST_WIDE_INT,
-                                    enum var_init_status, rtx);
+static void variable_was_changed (variable *, dataflow_set *);
+static variable **set_slot_part (dataflow_set *, rtx, variable **,
+                                decl_or_value, HOST_WIDE_INT,
+                                enum var_init_status, rtx);
 static void set_variable_part (dataflow_set *, rtx,
                               decl_or_value, HOST_WIDE_INT,
                               enum var_init_status, rtx, enum insert_option);
-static variable_def **clobber_slot_part (dataflow_set *, rtx,
-                                        variable_def **, HOST_WIDE_INT, rtx);
+static variable **clobber_slot_part (dataflow_set *, rtx,
+                                    variable **, HOST_WIDE_INT, rtx);
 static void clobber_variable_part (dataflow_set *, rtx,
                                   decl_or_value, HOST_WIDE_INT, rtx);
-static variable_def **delete_slot_part (dataflow_set *, rtx, variable_def **,
-                                       HOST_WIDE_INT);
+static variable **delete_slot_part (dataflow_set *, rtx, variable **,
+                                   HOST_WIDE_INT);
 static void delete_variable_part (dataflow_set *, rtx,
                                  decl_or_value, HOST_WIDE_INT);
 static void emit_notes_in_bb (basic_block, dataflow_set *);
@@ -700,6 +702,39 @@ static void vt_add_function_parameters (void);
 static bool vt_initialize (void);
 static void vt_finalize (void);
 
+/* Callback for stack_adjust_offset_pre_post, called via for_each_inc_dec.  */
+
+static int
+stack_adjust_offset_pre_post_cb (rtx, rtx op, rtx dest, rtx src, rtx srcoff,
+                                void *arg)
+{
+  if (dest != stack_pointer_rtx)
+    return 0;
+
+  switch (GET_CODE (op))
+    {
+    case PRE_INC:
+    case PRE_DEC:
+      ((HOST_WIDE_INT *)arg)[0] -= INTVAL (srcoff);
+      return 0;
+    case POST_INC:
+    case POST_DEC:
+      ((HOST_WIDE_INT *)arg)[1] -= INTVAL (srcoff);
+      return 0;
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      /* We handle only adjustments by constant amount.  */
+      gcc_assert (GET_CODE (src) == PLUS
+                 && CONST_INT_P (XEXP (src, 1))
+                 && XEXP (src, 0) == stack_pointer_rtx);
+      ((HOST_WIDE_INT *)arg)[GET_CODE (op) == POST_MODIFY]
+       -= INTVAL (XEXP (src, 1));
+      return 0;
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Given a SET, calculate the amount of stack adjustment it contains
    PRE- and POST-modifying stack pointer.
    This function is similar to stack_adjust_offset.  */
@@ -725,75 +760,19 @@ stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INT *pre,
        *post += INTVAL (XEXP (src, 1));
       else
        *post -= INTVAL (XEXP (src, 1));
+      return;
     }
-  else if (MEM_P (dest))
-    {
-      /* (set (mem (pre_dec (reg sp))) (foo)) */
-      src = XEXP (dest, 0);
-      code = GET_CODE (src);
-
-      switch (code)
-       {
-       case PRE_MODIFY:
-       case POST_MODIFY:
-         if (XEXP (src, 0) == stack_pointer_rtx)
-           {
-             rtx val = XEXP (XEXP (src, 1), 1);
-             /* We handle only adjustments by constant amount.  */
-             gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS &&
-                         CONST_INT_P (val));
-
-             if (code == PRE_MODIFY)
-               *pre -= INTVAL (val);
-             else
-               *post -= INTVAL (val);
-             break;
-           }
-         return;
-
-       case PRE_DEC:
-         if (XEXP (src, 0) == stack_pointer_rtx)
-           {
-             *pre += GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           }
-         return;
-
-       case POST_DEC:
-         if (XEXP (src, 0) == stack_pointer_rtx)
-           {
-             *post += GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           }
-         return;
-
-       case PRE_INC:
-         if (XEXP (src, 0) == stack_pointer_rtx)
-           {
-             *pre -= GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           }
-         return;
-
-       case POST_INC:
-         if (XEXP (src, 0) == stack_pointer_rtx)
-           {
-             *post -= GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           }
-         return;
-
-       default:
-         return;
-       }
-    }
+  HOST_WIDE_INT res[2] = { 0, 0 };
+  for_each_inc_dec (pattern, stack_adjust_offset_pre_post_cb, res);
+  *pre += res[0];
+  *post += res[1];
 }
 
 /* Given an INSN, calculate the amount of stack adjustment it contains
    PRE- and POST-modifying stack pointer.  */
 
 static void
-insn_stack_adjust_offset_pre_post (rtx insn, HOST_WIDE_INT *pre,
+insn_stack_adjust_offset_pre_post (rtx_insn *insn, HOST_WIDE_INT *pre,
                                   HOST_WIDE_INT *post)
 {
   rtx pattern;
@@ -836,10 +815,10 @@ vt_stack_adjustments (void)
 
   /* Initialize entry block.  */
   VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->visited = true;
-  VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->in.stack_adjust =
- INCOMING_FRAME_SP_OFFSET;
-  VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out.stack_adjust =
- INCOMING_FRAME_SP_OFFSET;
+  VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->in.stack_adjust
   = INCOMING_FRAME_SP_OFFSET;
+  VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out.stack_adjust
   = INCOMING_FRAME_SP_OFFSET;
 
   /* Allocate stack for back-tracking up CFG.  */
   stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun) + 1);
@@ -862,7 +841,7 @@ vt_stack_adjustments (void)
       /* Check if the edge destination has been visited yet.  */
       if (!VTI (dest)->visited)
        {
-         rtx insn;
+         rtx_insn *insn;
          HOST_WIDE_INT pre, post, offset;
          VTI (dest)->visited = true;
          VTI (dest)->in.stack_adjust = offset = VTI (src)->out.stack_adjust;
@@ -886,8 +865,25 @@ vt_stack_adjustments (void)
        }
       else
        {
-         /* Check whether the adjustments on the edges are the same.  */
-         if (VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
+         /* We can end up with different stack adjustments for the exit block
+            of a shrink-wrapped function if stack_adjust_offset_pre_post
+            doesn't understand the rtx pattern used to restore the stack
+            pointer in the epilogue.  For example, on s390(x), the stack
+            pointer is often restored via a load-multiple instruction
+            and so no stack_adjust offset is recorded for it.  This means
+            that the stack offset at the end of the epilogue block is the
+            same as the offset before the epilogue, whereas other paths
+            to the exit block will have the correct stack_adjust.
+
+            It is safe to ignore these differences because (a) we never
+            use the stack_adjust for the exit block in this pass and
+            (b) dwarf2cfi checks whether the CFA notes in a shrink-wrapped
+            function are correct.
+
+            We must check whether the adjustments on other edges are
+            the same though.  */
+         if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
+             && VTI (dest)->in.stack_adjust != VTI (src)->out.stack_adjust)
            {
              free (stack);
              return false;
@@ -929,52 +925,52 @@ static HOST_WIDE_INT hard_frame_pointer_adjustment = -1;
 struct adjust_mem_data
 {
   bool store;
-  enum machine_mode mem_mode;
+  machine_mode mem_mode;
   HOST_WIDE_INT stack_adjust;
-  rtx side_effects;
+  auto_vec<rtx> side_effects;
 };
 
-/* Helper for adjust_mems.  Return 1 if *loc is unsuitable for
-   transformation of wider mode arithmetics to narrower mode,
-   -1 if it is suitable and subexpressions shouldn't be
-   traversed and 0 if it is suitable and subexpressions should
-   be traversed.  Called through for_each_rtx.  */
+/* Helper for adjust_mems.  Return true if X is suitable for
+   transformation of wider mode arithmetics to narrower mode.  */
 
-static int
-use_narrower_mode_test (rtx *loc, void *data)
+static bool
+use_narrower_mode_test (rtx x, const_rtx subreg)
 {
-  rtx subreg = (rtx) data;
-
-  if (CONSTANT_P (*loc))
-    return -1;
-  switch (GET_CODE (*loc))
+  subrtx_var_iterator::array_type array;
+  FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
     {
-    case REG:
-      if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
-       return 1;
-      if (!validate_subreg (GET_MODE (subreg), GET_MODE (*loc),
-                           *loc, subreg_lowpart_offset (GET_MODE (subreg),
-                                                        GET_MODE (*loc))))
-       return 1;
-      return -1;
-    case PLUS:
-    case MINUS:
-    case MULT:
-      return 0;
-    case ASHIFT:
-      if (for_each_rtx (&XEXP (*loc, 0), use_narrower_mode_test, data))
-       return 1;
+      rtx x = *iter;
+      if (CONSTANT_P (x))
+       iter.skip_subrtxes ();
       else
-       return -1;
-    default:
-      return 1;
+       switch (GET_CODE (x))
+         {
+         case REG:
+           if (cselib_lookup (x, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
+             return false;
+           if (!validate_subreg (GET_MODE (subreg), GET_MODE (x), x,
+                                 subreg_lowpart_offset (GET_MODE (subreg),
+                                                        GET_MODE (x))))
+             return false;
+           break;
+         case PLUS:
+         case MINUS:
+         case MULT:
+           break;
+         case ASHIFT:
+           iter.substitute (XEXP (x, 0));
+           break;
+         default:
+           return false;
+         }
     }
+  return true;
 }
 
 /* Transform X into narrower mode MODE from wider mode WMODE.  */
 
 static rtx
-use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode)
+use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
 {
   rtx op0, op1;
   if (CONSTANT_P (x))
@@ -991,7 +987,13 @@ use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode)
       return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
     case ASHIFT:
       op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
-      return simplify_gen_binary (ASHIFT, mode, op0, XEXP (x, 1));
+      op1 = XEXP (x, 1);
+      /* Ensure shift amount is not wider than mode.  */
+      if (GET_MODE (op1) == VOIDmode)
+       op1 = lowpart_subreg (mode, op1, wmode);
+      else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1)))
+       op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
+      return simplify_gen_binary (ASHIFT, mode, op0, op1);
     default:
       gcc_unreachable ();
     }
@@ -1004,8 +1006,9 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
 {
   struct adjust_mem_data *amd = (struct adjust_mem_data *) data;
   rtx mem, addr = loc, tem;
-  enum machine_mode mem_mode_save;
+  machine_mode mem_mode_save;
   bool store_save;
+  scalar_int_mode tem_mode, tem_subreg_mode;
   switch (GET_CODE (loc))
     {
     case REG:
@@ -1055,6 +1058,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
                                         ? GET_MODE_SIZE (amd->mem_mode)
                                         : -GET_MODE_SIZE (amd->mem_mode),
                                         GET_MODE (loc)));
+      /* FALLTHRU */
     case POST_INC:
     case POST_DEC:
       if (addr == loc)
@@ -1067,24 +1071,26 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
                                        ? GET_MODE_SIZE (amd->mem_mode)
                                        : -GET_MODE_SIZE (amd->mem_mode),
                                        GET_MODE (loc)));
-      amd->side_effects = alloc_EXPR_LIST (0,
-                                          gen_rtx_SET (VOIDmode,
-                                                       XEXP (loc, 0),
-                                                       tem),
-                                          amd->side_effects);
+      store_save = amd->store;
+      amd->store = false;
+      tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data);
+      amd->store = store_save;
+      amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
       return addr;
     case PRE_MODIFY:
       addr = XEXP (loc, 1);
+      /* FALLTHRU */
     case POST_MODIFY:
       if (addr == loc)
        addr = XEXP (loc, 0);
       gcc_assert (amd->mem_mode != VOIDmode);
       addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
-      amd->side_effects = alloc_EXPR_LIST (0,
-                                          gen_rtx_SET (VOIDmode,
-                                                       XEXP (loc, 0),
-                                                       XEXP (loc, 1)),
-                                          amd->side_effects);
+      store_save = amd->store;
+      amd->store = false;
+      tem = simplify_replace_fn_rtx (XEXP (loc, 1), old_rtx,
+                                    adjust_mems, data);
+      amd->store = store_save;
+      amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem));
       return addr;
     case SUBREG:
       /* First try without delegitimization of whole MEMs and
@@ -1117,14 +1123,14 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
              || GET_CODE (SUBREG_REG (tem)) == MINUS
              || GET_CODE (SUBREG_REG (tem)) == MULT
              || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
-         && GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
-         && GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
-         && GET_MODE_SIZE (GET_MODE (tem))
-            < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tem)))
+         && is_a <scalar_int_mode> (GET_MODE (tem), &tem_mode)
+         && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (tem)),
+                                    &tem_subreg_mode)
+         && (GET_MODE_PRECISION (tem_mode)
+             < GET_MODE_PRECISION (tem_subreg_mode))
          && subreg_lowpart_p (tem)
-         && !for_each_rtx (&SUBREG_REG (tem), use_narrower_mode_test, tem))
-       return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
-                                 GET_MODE (SUBREG_REG (tem)));
+         && use_narrower_mode_test (SUBREG_REG (tem), tem))
+       return use_narrower_mode (SUBREG_REG (tem), tem_mode, tem_subreg_mode);
       return tem;
     case ASM_OPERANDS:
       /* Don't do any replacements in second and following
@@ -1174,9 +1180,8 @@ adjust_mem_stores (rtx loc, const_rtx expr, void *data)
    as other sets to the insn.  */
 
 static void
-adjust_insn (basic_block bb, rtx insn)
+adjust_insn (basic_block bb, rtx_insn *insn)
 {
-  struct adjust_mem_data amd;
   rtx set;
 
 #ifdef HAVE_window_save
@@ -1187,12 +1192,12 @@ adjust_insn (basic_block bb, rtx insn)
     {
       unsigned int i, nregs = vec_safe_length (windowed_parm_regs);
       rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2));
-      parm_reg_t *p;
+      parm_reg *p;
 
       FOR_EACH_VEC_SAFE_ELT (windowed_parm_regs, i, p)
        {
          XVECEXP (rtl, 0, i * 2)
-           = gen_rtx_SET (VOIDmode, p->incoming, p->outgoing);
+           = gen_rtx_SET (p->incoming, p->outgoing);
          /* Do not clobber the attached DECL, but only the REG.  */
          XVECEXP (rtl, 0, i * 2 + 1)
            = gen_rtx_CLOBBER (GET_MODE (p->outgoing),
@@ -1205,9 +1210,9 @@ adjust_insn (basic_block bb, rtx insn)
     }
 #endif
 
+  adjust_mem_data amd;
   amd.mem_mode = VOIDmode;
   amd.stack_adjust = -VTI (bb)->out.stack_adjust;
-  amd.side_effects = NULL_RTX;
 
   amd.store = true;
   note_stores (PATTERN (insn), adjust_mem_stores, &amd);
@@ -1273,10 +1278,10 @@ adjust_insn (basic_block bb, rtx insn)
        validate_change (NULL_RTX, &SET_SRC (set), XEXP (note, 0), true);
     }
 
-  if (amd.side_effects)
+  if (!amd.side_effects.is_empty ())
     {
-      rtx *pat, new_pat, s;
-      int i, oldn, newn;
+      rtx *pat, new_pat;
+      int i, oldn;
 
       pat = &PATTERN (insn);
       if (GET_CODE (*pat) == COND_EXEC)
@@ -1285,17 +1290,18 @@ adjust_insn (basic_block bb, rtx insn)
        oldn = XVECLEN (*pat, 0);
       else
        oldn = 1;
-      for (s = amd.side_effects, newn = 0; s; newn++)
-       s = XEXP (s, 1);
+      unsigned int newn = amd.side_effects.length ();
       new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn));
       if (GET_CODE (*pat) == PARALLEL)
        for (i = 0; i < oldn; i++)
          XVECEXP (new_pat, 0, i) = XVECEXP (*pat, 0, i);
       else
        XVECEXP (new_pat, 0, 0) = *pat;
-      for (s = amd.side_effects, i = oldn; i < oldn + newn; i++, s = XEXP (s, 1))
-       XVECEXP (new_pat, 0, i) = XEXP (s, 0);
-      free_EXPR_LIST_list (&amd.side_effects);
+
+      rtx effect;
+      unsigned int j;
+      FOR_EACH_VEC_ELT_REVERSE (amd.side_effects, j, effect)
+       XVECEXP (new_pat, 0, j + oldn) = effect;
       validate_change (NULL_RTX, pat, new_pat, true);
     }
 }
@@ -1318,7 +1324,7 @@ dv_as_rtx (decl_or_value dv)
 /* Return nonzero if a decl_or_value must not have more than one
    variable part.  The returned value discriminates among various
    kinds of one-part DVs ccording to enum onepart_enum.  */
-static inline onepart_enum_t
+static inline onepart_enum
 dv_onepart_p (decl_or_value dv)
 {
   tree decl;
@@ -1341,12 +1347,19 @@ dv_onepart_p (decl_or_value dv)
 }
 
 /* Return the variable pool to be used for a dv of type ONEPART.  */
-static inline alloc_pool
-onepart_pool (onepart_enum_t onepart)
+static inline pool_allocator &
+onepart_pool (onepart_enum onepart)
 {
   return onepart ? valvar_pool : var_pool;
 }
 
+/* Allocate a variable_def from the corresponding variable pool.  */
+static inline variable *
+onepart_pool_allocate (onepart_enum onepart)
+{
+  return (variable*) onepart_pool (onepart).allocate ();
+}
+
 /* Build a decl_or_value out of a decl.  */
 static inline decl_or_value
 dv_from_decl (tree decl)
@@ -1402,7 +1415,7 @@ debug_dv (decl_or_value dv)
     debug_generic_stmt (dv_as_decl (dv));
 }
 
-static void loc_exp_dep_clear (variable var);
+static void loc_exp_dep_clear (variable *var);
 
 /* Free the element of VARIABLE_HTAB (its type is struct variable_def).  */
 
@@ -1410,8 +1423,8 @@ static void
 variable_htab_free (void *elem)
 {
   int i;
-  variable var = (variable) elem;
-  location_chain node, next;
+  variable *var = (variable *) elem;
+  location_chain *node, *next;
 
   gcc_checking_assert (var->refcount > 0);
 
@@ -1424,7 +1437,7 @@ variable_htab_free (void *elem)
       for (node = var->var_part[i].loc_chain; node; node = next)
        {
          next = node->next;
-         pool_free (loc_chain_pool, node);
+         delete node;
        }
       var->var_part[i].loc_chain = NULL;
     }
@@ -1439,13 +1452,13 @@ variable_htab_free (void *elem)
       if (var->onepart == ONEPART_DEXPR)
        set_dv_changed (var->dv, true);
     }
-  pool_free (onepart_pool (var->onepart), var);
+  onepart_pool (var->onepart).remove (var);
 }
 
 /* Initialize the set (array) SET of attrs to empty lists.  */
 
 static void
-init_attrs_list_set (attrs *set)
+init_attrs_list_set (attrs **set)
 {
   int i;
 
@@ -1456,22 +1469,22 @@ init_attrs_list_set (attrs *set)
 /* Make the list *LISTP empty.  */
 
 static void
-attrs_list_clear (attrs *listp)
+attrs_list_clear (attrs **listp)
 {
-  attrs list, next;
+  attrs *list, *next;
 
   for (list = *listp; list; list = next)
     {
       next = list->next;
-      pool_free (attrs_pool, list);
+      delete list;
     }
   *listp = NULL;
 }
 
 /* Return true if the pair of DECL and OFFSET is the member of the LIST.  */
 
-static attrs
-attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
+static attrs *
+attrs_list_member (attrs *list, decl_or_value dv, HOST_WIDE_INT offset)
 {
   for (; list; list = list->next)
     if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
@@ -1482,12 +1495,10 @@ attrs_list_member (attrs list, decl_or_value dv, HOST_WIDE_INT offset)
 /* Insert the triplet DECL, OFFSET, LOC to the list *LISTP.  */
 
 static void
-attrs_list_insert (attrs *listp, decl_or_value dv,
+attrs_list_insert (attrs **listp, decl_or_value dv,
                   HOST_WIDE_INT offset, rtx loc)
 {
-  attrs list;
-
-  list = (attrs) pool_alloc (attrs_pool);
+  attrs *list = new attrs;
   list->loc = loc;
   list->dv = dv;
   list->offset = offset;
@@ -1498,14 +1509,12 @@ attrs_list_insert (attrs *listp, decl_or_value dv,
 /* Copy all nodes from SRC and create a list *DSTP of the copies.  */
 
 static void
-attrs_list_copy (attrs *dstp, attrs src)
+attrs_list_copy (attrs **dstp, attrs *src)
 {
-  attrs n;
-
   attrs_list_clear (dstp);
   for (; src; src = src->next)
     {
-      n = (attrs) pool_alloc (attrs_pool);
+      attrs *n = new attrs;
       n->loc = src->loc;
       n->dv = src->dv;
       n->offset = src->offset;
@@ -1517,7 +1526,7 @@ attrs_list_copy (attrs *dstp, attrs src)
 /* Add all nodes from SRC which are not in *DSTP to *DSTP.  */
 
 static void
-attrs_list_union (attrs *dstp, attrs src)
+attrs_list_union (attrs **dstp, attrs *src)
 {
   for (; src; src = src->next)
     {
@@ -1530,7 +1539,7 @@ attrs_list_union (attrs *dstp, attrs src)
    *DSTP.  */
 
 static void
-attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
+attrs_list_mpdv_union (attrs **dstp, attrs *src, attrs *src2)
 {
   gcc_assert (!*dstp);
   for (; src; src = src->next)
@@ -1551,15 +1560,15 @@ attrs_list_mpdv_union (attrs *dstp, attrs src, attrs src2)
 /* Return true if VARS is shared.  */
 
 static inline bool
-shared_hash_shared (shared_hash vars)
+shared_hash_shared (shared_hash *vars)
 {
   return vars->refcount > 1;
 }
 
 /* Return the hash table for VARS.  */
 
-static inline variable_table_type
-shared_hash_htab (shared_hash vars)
+static inline variable_table_type *
+shared_hash_htab (shared_hash *vars)
 {
   return vars->htab;
 }
@@ -1567,7 +1576,7 @@ shared_hash_htab (shared_hash vars)
 /* Return true if VAR is shared, or maybe because VARS is shared.  */
 
 static inline bool
-shared_var_p (variable var, shared_hash vars)
+shared_var_p (variable *var, shared_hash *vars)
 {
   /* Don't count an entry in the changed_variables table as a duplicate.  */
   return ((var->refcount > 1 + (int) var->in_changed_variables)
@@ -1576,13 +1585,13 @@ shared_var_p (variable var, shared_hash vars)
 
 /* Copy variables into a new hash table.  */
 
-static shared_hash
-shared_hash_unshare (shared_hash vars)
+static shared_hash *
+shared_hash_unshare (shared_hash *vars)
 {
-  shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
+  shared_hash *new_vars = new shared_hash;
   gcc_assert (vars->refcount > 1);
   new_vars->refcount = 1;
-  new_vars->htab.create (vars->htab.elements () + 3);
+  new_vars->htab = new variable_table_type (vars->htab->elements () + 3);
   vars_copy (new_vars->htab, vars->htab);
   vars->refcount--;
   return new_vars;
@@ -1590,8 +1599,8 @@ shared_hash_unshare (shared_hash vars)
 
 /* Increment reference counter on VARS and return it.  */
 
-static inline shared_hash
-shared_hash_copy (shared_hash vars)
+static inline shared_hash *
+shared_hash_copy (shared_hash *vars)
 {
   vars->refcount++;
   return vars;
@@ -1601,30 +1610,30 @@ shared_hash_copy (shared_hash vars)
    anymore.  */
 
 static void
-shared_hash_destroy (shared_hash vars)
+shared_hash_destroy (shared_hash *vars)
 {
   gcc_checking_assert (vars->refcount > 0);
   if (--vars->refcount == 0)
     {
-      vars->htab.dispose ();
-      pool_free (shared_hash_pool, vars);
+      delete vars->htab;
+      delete vars;
     }
 }
 
 /* Unshare *PVARS if shared and return slot for DV.  If INS is
    INSERT, insert it if not already present.  */
 
-static inline variable_def **
-shared_hash_find_slot_unshare_1 (shared_hash *pvars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
                                 hashval_t dvhash, enum insert_option ins)
 {
   if (shared_hash_shared (*pvars))
     *pvars = shared_hash_unshare (*pvars);
-  return shared_hash_htab (*pvars).find_slot_with_hash (dv, dvhash, ins);
+  return shared_hash_htab (*pvars)->find_slot_with_hash (dv, dvhash, ins);
 }
 
-static inline variable_def **
-shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
                               enum insert_option ins)
 {
   return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
@@ -1634,31 +1643,31 @@ shared_hash_find_slot_unshare (shared_hash *pvars, decl_or_value dv,
    If it is not present, insert it only VARS is not shared, otherwise
    return NULL.  */
 
-static inline variable_def **
-shared_hash_find_slot_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
+static inline variable **
+shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
 {
-  return shared_hash_htab (vars).find_slot_with_hash (dv, dvhash,
-                                                     shared_hash_shared (vars)
-                                                     ? NO_INSERT : INSERT);
+  return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash,
+                                                      shared_hash_shared (vars)
+                                                      ? NO_INSERT : INSERT);
 }
 
-static inline variable_def **
-shared_hash_find_slot (shared_hash vars, decl_or_value dv)
+static inline variable **
+shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
 }
 
 /* Return slot for DV only if it is already present in the hash table.  */
 
-static inline variable_def **
-shared_hash_find_slot_noinsert_1 (shared_hash vars, decl_or_value dv,
+static inline variable **
+shared_hash_find_slot_noinsert_1 (shared_hash *vars, decl_or_value dv,
                                  hashval_t dvhash)
 {
-  return shared_hash_htab (vars).find_slot_with_hash (dv, dvhash, NO_INSERT);
+  return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash, NO_INSERT);
 }
 
-static inline variable_def **
-shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
+static inline variable **
+shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
 }
@@ -1666,14 +1675,14 @@ shared_hash_find_slot_noinsert (shared_hash vars, decl_or_value dv)
 /* Return variable for DV or NULL if not already present in the hash
    table.  */
 
-static inline variable
-shared_hash_find_1 (shared_hash vars, decl_or_value dv, hashval_t dvhash)
+static inline variable *
+shared_hash_find_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
 {
-  return shared_hash_htab (vars).find_with_hash (dv, dvhash);
+  return shared_hash_htab (vars)->find_with_hash (dv, dvhash);
 }
 
-static inline variable
-shared_hash_find (shared_hash vars, decl_or_value dv)
+static inline variable *
+shared_hash_find (shared_hash *vars, decl_or_value dv)
 {
   return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
 }
@@ -1698,14 +1707,14 @@ static bool dst_can_be_shared;
 
 /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
 
-static variable_def **
-unshare_variable (dataflow_set *set, variable_def **slot, variable var,
+static variable **
+unshare_variable (dataflow_set *set, variable **slot, variable *var,
                  enum var_init_status initialized)
 {
-  variable new_var;
+  variable *new_var;
   int i;
 
-  new_var = (variable) pool_alloc (onepart_pool (var->onepart));
+  new_var = onepart_pool_allocate (var->onepart);
   new_var->dv = var->dv;
   new_var->refcount = 1;
   var->refcount--;
@@ -1718,8 +1727,8 @@ unshare_variable (dataflow_set *set, variable_def **slot, variable var,
 
   for (i = 0; i < var->n_var_parts; i++)
     {
-      location_chain node;
-      location_chain *nextp;
+      location_chain *node;
+      location_chain **nextp;
 
       if (i == 0 && var->onepart)
        {
@@ -1736,9 +1745,9 @@ unshare_variable (dataflow_set *set, variable_def **slot, variable var,
       nextp = &new_var->var_part[i].loc_chain;
       for (node = var->var_part[i].loc_chain; node; node = node->next)
        {
-         location_chain new_lc;
+         location_chain *new_lc;
 
-         new_lc = (location_chain) pool_alloc (loc_chain_pool);
+         new_lc = new location_chain;
          new_lc->next = NULL;
          if (node->init > initialized)
            new_lc->init = node->init;
@@ -1765,9 +1774,10 @@ unshare_variable (dataflow_set *set, variable_def **slot, variable var,
   *slot = new_var;
   if (var->in_changed_variables)
     {
-      variable_def **cslot
-       = changed_variables.find_slot_with_hash (var->dv,
-                                   dv_htab_hash (var->dv), NO_INSERT);
+      variable **cslot
+       = changed_variables->find_slot_with_hash (var->dv,
+                                                 dv_htab_hash (var->dv),
+                                                 NO_INSERT);
       gcc_assert (*cslot == (void *) var);
       var->in_changed_variables = false;
       variable_htab_free (var);
@@ -1780,16 +1790,17 @@ unshare_variable (dataflow_set *set, variable_def **slot, variable var,
 /* Copy all variables from hash table SRC to hash table DST.  */
 
 static void
-vars_copy (variable_table_type dst, variable_table_type src)
+vars_copy (variable_table_type *dst, variable_table_type *src)
 {
   variable_iterator_type hi;
-  variable var;
+  variable *var;
 
-  FOR_EACH_HASH_TABLE_ELEMENT (src, var, variable, hi)
+  FOR_EACH_HASH_TABLE_ELEMENT (*src, var, variable, hi)
     {
-      variable_def **dstp;
+      variable **dstp;
       var->refcount++;
-      dstp = dst.find_slot_with_hash (var->dv, dv_htab_hash (var->dv), INSERT);
+      dstp = dst->find_slot_with_hash (var->dv, dv_htab_hash (var->dv),
+                                      INSERT);
       *dstp = var;
     }
 }
@@ -1799,8 +1810,7 @@ vars_copy (variable_table_type dst, variable_table_type src)
 static inline tree
 var_debug_decl (tree decl)
 {
-  if (decl && TREE_CODE (decl) == VAR_DECL
-      && DECL_HAS_DEBUG_EXPR_P (decl))
+  if (decl && VAR_P (decl) && DECL_HAS_DEBUG_EXPR_P (decl))
     {
       tree debugdecl = DECL_DEBUG_EXPR (decl);
       if (DECL_P (debugdecl))
@@ -1817,7 +1827,7 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
                  decl_or_value dv, HOST_WIDE_INT offset, rtx set_src,
                  enum insert_option iopt)
 {
-  attrs node;
+  attrs *node;
   bool decl_p = dv_is_decl_p (dv);
 
   if (decl_p)
@@ -1848,7 +1858,7 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
 static enum var_init_status
 get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
 {
-  variable var;
+  variable *var;
   int i;
   enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
 
@@ -1860,7 +1870,7 @@ get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
     {
       for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
        {
-         location_chain nextp;
+         location_chain *nextp;
          for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
            if (rtx_equal_p (nextp->loc, loc))
              {
@@ -1886,8 +1896,8 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
 {
   tree decl = REG_EXPR (loc);
   HOST_WIDE_INT offset = REG_OFFSET (loc);
-  attrs node, next;
-  attrs *nextp;
+  attrs *node, *next;
+  attrs **nextp;
 
   decl = var_debug_decl (decl);
 
@@ -1901,7 +1911,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
       if (dv_as_opaque (node->dv) != decl || node->offset != offset)
        {
          delete_variable_part (set, node->loc, node->dv, node->offset);
-         pool_free (attrs_pool, node);
+         delete node;
          *nextp = next;
        }
       else
@@ -1923,8 +1933,8 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
 static void
 var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
 {
-  attrs *nextp = &set->regs[REGNO (loc)];
-  attrs node, next;
+  attrs **nextp = &set->regs[REGNO (loc)];
+  attrs *node, *next;
 
   if (clobber)
     {
@@ -1942,7 +1952,7 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
       if (clobber || !dv_onepart_p (node->dv))
        {
          delete_variable_part (set, node->loc, node->dv, node->offset);
-         pool_free (attrs_pool, node);
+         delete node;
          *nextp = next;
        }
       else
@@ -1955,14 +1965,14 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
 static void
 var_regno_delete (dataflow_set *set, int regno)
 {
-  attrs *reg = &set->regs[regno];
-  attrs node, next;
+  attrs **reg = &set->regs[regno];
+  attrs *node, *next;
 
   for (node = *reg; node; node = next)
     {
       next = node->next;
       delete_variable_part (set, node->loc, node->dv, node->offset);
-      pool_free (attrs_pool, node);
+      delete node;
     }
   *reg = NULL;
 }
@@ -1972,7 +1982,7 @@ static bool
 negative_power_of_two_p (HOST_WIDE_INT i)
 {
   unsigned HOST_WIDE_INT x = -(unsigned HOST_WIDE_INT)i;
-  return x == (x & -x);
+  return pow2_or_zerop (x);
 }
 
 /* Strip constant offsets and alignments off of LOC.  Return the base
@@ -1993,12 +2003,12 @@ vt_get_canonicalize_base (rtx loc)
 
 /* This caches canonicalized addresses for VALUEs, computed using
    information in the global cselib table.  */
-static struct pointer_map_t *global_get_addr_cache;
+static hash_map<rtx, rtx> *global_get_addr_cache;
 
 /* This caches canonicalized addresses for VALUEs, computed using
    information from the global cache and information pertaining to a
    basic block being analyzed.  */
-static struct pointer_map_t *local_get_addr_cache;
+static hash_map<rtx, rtx> *local_get_addr_cache;
 
 static rtx vt_canonicalize_addr (dataflow_set *, rtx);
 
@@ -2010,13 +2020,13 @@ static rtx
 get_addr_from_global_cache (rtx const loc)
 {
   rtx x;
-  void **slot;
 
   gcc_checking_assert (GET_CODE (loc) == VALUE);
-  
-  slot = pointer_map_insert (global_get_addr_cache, loc);
-  if (*slot)
-    return (rtx)*slot;
+
+  bool existed;
+  rtx *slot = &global_get_addr_cache->get_or_insert (loc, &existed);
+  if (existed)
+    return *slot;
 
   x = canon_rtx (get_addr (loc));
 
@@ -2030,8 +2040,7 @@ get_addr_from_global_cache (rtx const loc)
        {
          /* The table may have moved during recursion, recompute
             SLOT.  */
-         slot = pointer_map_contains (global_get_addr_cache, loc);
-         *slot = x = nx;
+         *global_get_addr_cache->get (loc) = x = nx;
        }
     }
 
@@ -2046,19 +2055,19 @@ static rtx
 get_addr_from_local_cache (dataflow_set *set, rtx const loc)
 {
   rtx x;
-  void **slot;
   decl_or_value dv;
-  variable var;
-  location_chain l;
+  variable *var;
+  location_chain *l;
 
   gcc_checking_assert (GET_CODE (loc) == VALUE);
-  
-  slot = pointer_map_insert (local_get_addr_cache, loc);
-  if (*slot)
-    return (rtx)*slot;
+
+  bool existed;
+  rtx *slot = &local_get_addr_cache->get_or_insert (loc, &existed);
+  if (existed)
+    return *slot;
 
   x = get_addr_from_global_cache (loc);
-  
+
   /* Tentative, avoiding infinite recursion.  */
   *slot = x;
 
@@ -2069,7 +2078,7 @@ get_addr_from_local_cache (dataflow_set *set, rtx const loc)
       rtx nx = vt_canonicalize_addr (set, x);
       if (nx != x)
        {
-         slot = pointer_map_contains (local_get_addr_cache, loc);
+         slot = local_get_addr_cache->get (loc);
          *slot = x = nx;
        }
       return x;
@@ -2090,7 +2099,7 @@ get_addr_from_local_cache (dataflow_set *set, rtx const loc)
          rtx nx = vt_canonicalize_addr (set, l->loc);
          if (x != nx)
            {
-             slot = pointer_map_contains (local_get_addr_cache, loc);
+             slot = local_get_addr_cache->get (loc);
              *slot = x = nx;
            }
          break;
@@ -2118,7 +2127,7 @@ static rtx
 vt_canonicalize_addr (dataflow_set *set, rtx oloc)
 {
   HOST_WIDE_INT ofst = 0;
-  enum machine_mode mode = GET_MODE (oloc);
+  machine_mode mode = GET_MODE (oloc);
   rtx loc = oloc;
   rtx x;
   bool retry = true;
@@ -2212,20 +2221,20 @@ struct overlapping_mems
 };
 
 /* Remove all MEMs that overlap with COMS->LOC from the location list
-   of a hash table entry for a value.  COMS->ADDR must be a
+   of a hash table entry for a onepart variable.  COMS->ADDR must be a
    canonicalized form of COMS->LOC's address, and COMS->LOC must be
    canonicalized itself.  */
 
 int
-drop_overlapping_mem_locs (variable_def **slot, overlapping_mems *coms)
+drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
 {
   dataflow_set *set = coms->set;
   rtx mloc = coms->loc, addr = coms->addr;
-  variable var = *slot;
+  variable *var = *slot;
 
-  if (var->onepart == ONEPART_VALUE)
+  if (var->onepart != NOT_ONEPART)
     {
-      location_chain loc, *locp;
+      location_chain *loc, **locp;
       bool changed = false;
       rtx cur_loc;
 
@@ -2270,7 +2279,7 @@ drop_overlapping_mem_locs (variable_def **slot, overlapping_mems *coms)
              if (VAR_LOC_1PAUX (var))
                VAR_LOC_FROM (var) = NULL;
            }
-         pool_free (loc_chain_pool, loc);
+         delete loc;
        }
 
       if (!var->var_part[0].loc_chain)
@@ -2300,7 +2309,7 @@ clobber_overlapping_mems (dataflow_set *set, rtx loc)
 
   set->traversed_vars = set->vars;
   shared_hash_htab (set->vars)
-    .traverse <overlapping_mems*, drop_overlapping_mem_locs> (&coms);
+    ->traverse <overlapping_mems*, drop_overlapping_mem_locs> (&coms);
   set->traversed_vars = NULL;
 }
 
@@ -2446,7 +2455,8 @@ val_bind (dataflow_set *set, rtx val, rtx loc, bool modified)
    values bound to it.  */
 
 static void
-val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
+val_store (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn,
+          bool modified)
 {
   cselib_val *v = CSELIB_VAL_PTR (val);
 
@@ -2477,11 +2487,10 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
 
 /* Clear (canonical address) slots that reference X.  */
 
-static bool
-local_get_addr_clear_given_value (const void *v ATTRIBUTE_UNUSED,
-                                 void **slot, void *x)
+bool
+local_get_addr_clear_given_value (rtx const &, rtx *slot, rtx x)
 {
-  if (vt_get_canonicalize_base ((rtx)*slot) == x)
+  if (vt_get_canonicalize_base (*slot) == x)
     *slot = NULL;
   return true;
 }
@@ -2492,8 +2501,8 @@ local_get_addr_clear_given_value (const void *v ATTRIBUTE_UNUSED,
 static void
 val_reset (dataflow_set *set, decl_or_value dv)
 {
-  variable var = shared_hash_find (set->vars, dv) ;
-  location_chain node;
+  variable *var = shared_hash_find (set->vars, dv) ;
+  location_chain *node;
   rtx cval;
 
   if (!var || !var->n_var_parts)
@@ -2504,11 +2513,10 @@ val_reset (dataflow_set *set, decl_or_value dv)
   if (var->onepart == ONEPART_VALUE)
     {
       rtx x = dv_as_value (dv);
-      void **slot;
-      
+
       /* Relationships in the global cache don't change, so reset the
         local cache entry only.  */
-      slot = pointer_map_contains (local_get_addr_cache, x);
+      rtx *slot = local_get_addr_cache->get (x);
       if (slot)
        {
          /* If the value resolved back to itself, odds are that other
@@ -2517,8 +2525,8 @@ val_reset (dataflow_set *set, decl_or_value dv)
             old X but resolved to something else remain ok as long as
             that something else isn't also reset.  */
          if (*slot == x)
-           pointer_map_traverse (local_get_addr_cache,
-                                 local_get_addr_clear_given_value, x);
+           local_get_addr_cache
+             ->traverse<rtx, local_get_addr_clear_given_value> (x);
          *slot = NULL;
        }
     }
@@ -2546,7 +2554,7 @@ val_reset (dataflow_set *set, decl_or_value dv)
     {
       decl_or_value cdv = dv_from_value (cval);
 
-      /* Keep the remaining values connected, accummulating links
+      /* Keep the remaining values connected, accumulating links
         in the canonical value.  */
       for (node = var->var_part[0].loc_chain; node; node = node->next)
        {
@@ -2577,7 +2585,7 @@ val_reset (dataflow_set *set, decl_or_value dv)
    value.  */
 
 static void
-val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
+val_resolve (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn)
 {
   decl_or_value dv = dv_from_value (val);
 
@@ -2599,7 +2607,7 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
 
   if (REG_P (loc))
     {
-      attrs node, found = NULL;
+      attrs *node, *found = NULL;
 
       for (node = set->regs[REGNO (loc)]; node; node = node->next)
        if (dv_is_value_p (node->dv)
@@ -2675,7 +2683,7 @@ dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
 struct variable_union_info
 {
   /* Node of the location chain.  */
-  location_chain lc;
+  location_chain *lc;
 
   /* The sum of positions in the input chains.  */
   int pos;
@@ -2715,10 +2723,10 @@ variable_union_info_cmp_pos (const void *n1, const void *n2)
    we keep the newest locations in the beginning.  */
 
 static int
-variable_union (variable src, dataflow_set *set)
+variable_union (variable *src, dataflow_set *set)
 {
-  variable dst;
-  variable_def **dstp;
+  variable *dst;
+  variable **dstp;
   int i, j, k;
 
   dstp = shared_hash_find_slot (set->vars, src->dv);
@@ -2745,7 +2753,7 @@ variable_union (variable src, dataflow_set *set)
      entries are in canonical order.  */
   if (src->onepart)
     {
-      location_chain *nodep, dnode, snode;
+      location_chain **nodep, *dnode, *snode;
 
       gcc_assert (src->n_var_parts == 1
                  && dst->n_var_parts == 1);
@@ -2764,7 +2772,7 @@ variable_union (variable src, dataflow_set *set)
 
          if (r > 0)
            {
-             location_chain nnode;
+             location_chain *nnode;
 
              if (shared_var_p (dst, set->vars))
                {
@@ -2774,7 +2782,7 @@ variable_union (variable src, dataflow_set *set)
                  goto restart_onepart_unshared;
                }
 
-             *nodep = nnode = (location_chain) pool_alloc (loc_chain_pool);
+             *nodep = nnode = new location_chain;
              nnode->loc = snode->loc;
              nnode->init = snode->init;
              if (!snode->set_src || MEM_P (snode->set_src))
@@ -2832,7 +2840,7 @@ variable_union (variable src, dataflow_set *set)
 
   for (k--; k >= 0; k--)
     {
-      location_chain node, node2;
+      location_chain *node, *node2;
 
       if (i >= 0 && j >= 0
          && VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
@@ -2867,7 +2875,7 @@ variable_union (variable src, dataflow_set *set)
                {
                  dstp = unshare_variable (set, dstp, dst,
                                           VAR_INIT_STATUS_UNKNOWN);
-                 dst = (variable)*dstp;
+                 dst = (variable *)*dstp;
                }
            }
 
@@ -2881,7 +2889,7 @@ variable_union (variable src, dataflow_set *set)
          if (dst_l == 1)
            {
              /* The most common case, much simpler, no qsort is needed.  */
-             location_chain dstnode = dst->var_part[j].loc_chain;
+             location_chain *dstnode = dst->var_part[j].loc_chain;
              dst->var_part[k].loc_chain = dstnode;
              VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
              node2 = dstnode;
@@ -2891,10 +2899,10 @@ variable_union (variable src, dataflow_set *set)
                       && REGNO (dstnode->loc) == REGNO (node->loc))
                      || rtx_equal_p (dstnode->loc, node->loc)))
                  {
-                   location_chain new_node;
+                   location_chain *new_node;
 
                    /* Copy the location from SRC.  */
-                   new_node = (location_chain) pool_alloc (loc_chain_pool);
+                   new_node = new location_chain;
                    new_node->loc = node->loc;
                    new_node->init = node->init;
                    if (!node->set_src || MEM_P (node->set_src))
@@ -2946,10 +2954,10 @@ variable_union (variable src, dataflow_set *set)
                    }
                  if (jj >= dst_l)      /* The location has not been found.  */
                    {
-                     location_chain new_node;
+                     location_chain *new_node;
 
                      /* Copy the location from SRC.  */
-                     new_node = (location_chain) pool_alloc (loc_chain_pool);
+                     new_node = new location_chain;
                      new_node->loc = node->loc;
                      new_node->init = node->init;
                      if (!node->set_src || MEM_P (node->set_src))
@@ -3037,15 +3045,15 @@ variable_union (variable src, dataflow_set *set)
                && VAR_PART_OFFSET (src, i) > VAR_PART_OFFSET (dst, j))
               || j < 0)
        {
-         location_chain *nextp;
+         location_chain **nextp;
 
          /* Copy the chain from SRC.  */
          nextp = &dst->var_part[k].loc_chain;
          for (node = src->var_part[i].loc_chain; node; node = node->next)
            {
-             location_chain new_lc;
+             location_chain *new_lc;
 
-             new_lc = (location_chain) pool_alloc (loc_chain_pool);
+             new_lc = new location_chain;
              new_lc->next = NULL;
              new_lc->init = node->init;
              if (!node->set_src || MEM_P (node->set_src))
@@ -3067,7 +3075,7 @@ variable_union (variable src, dataflow_set *set)
   if (flag_var_tracking_uninit)
     for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
       {
-       location_chain node, node2;
+       location_chain *node, *node2;
        for (node = src->var_part[i].loc_chain; node; node = node->next)
          for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
            if (rtx_equal_p (node->loc, node2->loc))
@@ -3099,9 +3107,9 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
   else
     {
       variable_iterator_type hi;
-      variable var;
+      variable *var;
 
-      FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (src->vars),
+      FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (src->vars),
                                   var, variable, hi)
        variable_union (var, dst);
     }
@@ -3141,7 +3149,7 @@ set_dv_changed (decl_or_value dv, bool newv)
     case ONEPART_DEXPR:
       if (newv)
        NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv))) = false;
-      /* Fall through...  */
+      /* Fall through.  */
 
     default:
       DECL_CHANGED (dv_as_decl (dv)) = newv;
@@ -3164,10 +3172,10 @@ dv_changed_p (decl_or_value dv)
    any values recursively mentioned in the location lists.  VARS must
    be in star-canonical form.  */
 
-static location_chain
-find_loc_in_1pdv (rtx loc, variable var, variable_table_type vars)
+static location_chain *
+find_loc_in_1pdv (rtx loc, variable *var, variable_table_type *vars)
 {
-  location_chain node;
+  location_chain *node;
   enum rtx_code loc_code;
 
   if (!var)
@@ -3184,7 +3192,7 @@ find_loc_in_1pdv (rtx loc, variable var, variable_table_type vars)
   for (node = var->var_part[0].loc_chain; node; node = node->next)
     {
       decl_or_value dv;
-      variable rvar;
+      variable *rvar;
 
       if (GET_CODE (node->loc) != loc_code)
        {
@@ -3222,7 +3230,7 @@ find_loc_in_1pdv (rtx loc, variable var, variable_table_type vars)
       gcc_checking_assert (!node->next);
 
       dv = dv_from_value (node->loc);
-      rvar = vars.find_with_hash (dv, dv_htab_hash (dv));
+      rvar = vars->find_with_hash (dv, dv_htab_hash (dv));
       return find_loc_in_1pdv (loc, rvar, vars);
     }
 
@@ -3248,10 +3256,10 @@ struct dfset_merge
    loc_cmp order, and it is maintained as such.  */
 
 static void
-insert_into_intersection (location_chain *nodep, rtx loc,
+insert_into_intersection (location_chain **nodep, rtx loc,
                          enum var_init_status status)
 {
-  location_chain node;
+  location_chain *node;
   int r;
 
   for (node = *nodep; node; nodep = &node->next, node = *nodep)
@@ -3263,7 +3271,7 @@ insert_into_intersection (location_chain *nodep, rtx loc,
     else if (r > 0)
       break;
 
-  node = (location_chain) pool_alloc (loc_chain_pool);
+  node = new location_chain;
 
   node->loc = loc;
   node->set_src = NULL;
@@ -3278,16 +3286,16 @@ insert_into_intersection (location_chain *nodep, rtx loc,
    DSM->dst.  */
 
 static void
-intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
-                     location_chain s1node, variable s2var)
+intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
+                     location_chain *s1node, variable *s2var)
 {
   dataflow_set *s1set = dsm->cur;
   dataflow_set *s2set = dsm->src;
-  location_chain found;
+  location_chain *found;
 
   if (s2var)
     {
-      location_chain s2node;
+      location_chain *s2node;
 
       gcc_checking_assert (s2var->onepart);
 
@@ -3324,7 +3332,7 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
          && !VALUE_RECURSED_INTO (s1node->loc))
        {
          decl_or_value dv = dv_from_value (s1node->loc);
-         variable svar = shared_hash_find (s1set->vars, dv);
+         variable *svar = shared_hash_find (s1set->vars, dv);
          if (svar)
            {
              if (svar->n_var_parts == 1)
@@ -3531,19 +3539,35 @@ loc_cmp (rtx x, rtx y)
       default:
        gcc_unreachable ();
       }
+  if (CONST_WIDE_INT_P (x))
+    {
+      /* Compare the vector length first.  */
+      if (CONST_WIDE_INT_NUNITS (x) >= CONST_WIDE_INT_NUNITS (y))
+       return 1;
+      else if (CONST_WIDE_INT_NUNITS (x) < CONST_WIDE_INT_NUNITS (y))
+       return -1;
+
+      /* Compare the vectors elements.  */;
+      for (j = CONST_WIDE_INT_NUNITS (x) - 1; j >= 0 ; j--)
+       {
+         if (CONST_WIDE_INT_ELT (x, j) < CONST_WIDE_INT_ELT (y, j))
+           return -1;
+         if (CONST_WIDE_INT_ELT (x, j) > CONST_WIDE_INT_ELT (y, j))
+           return 1;
+       }
+    }
 
   return 0;
 }
 
-#if ENABLE_CHECKING
 /* Check the order of entries in one-part variables.   */
 
 int
-canonicalize_loc_order_check (variable_def **slot,
+canonicalize_loc_order_check (variable **slot,
                              dataflow_set *data ATTRIBUTE_UNUSED)
 {
-  variable var = *slot;
-  location_chain node, next;
+  variable *var = *slot;
+  location_chain *node, *next;
 
 #ifdef ENABLE_RTL_CHECKING
   int i;
@@ -3567,7 +3591,6 @@ canonicalize_loc_order_check (variable_def **slot,
 
   return 1;
 }
-#endif
 
 /* Mark with VALUE_RECURSED_INTO values that have neighbors that are
    more likely to be chosen as canonical for an equivalence set.
@@ -3575,12 +3598,12 @@ canonicalize_loc_order_check (variable_def **slot,
    the connections bidirectional.  */
 
 int
-canonicalize_values_mark (variable_def **slot, dataflow_set *set)
+canonicalize_values_mark (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
   rtx val;
-  location_chain node;
+  location_chain *node;
 
   if (!dv_is_value_p (dv))
     return 1;
@@ -3597,7 +3620,7 @@ canonicalize_values_mark (variable_def **slot, dataflow_set *set)
        else
          {
            decl_or_value odv = dv_from_value (node->loc);
-           variable_def **oslot;
+           variable **oslot;
            oslot = shared_hash_find_slot_noinsert (set->vars, odv);
 
            set_slot_part (set, val, oslot, odv, 0,
@@ -3614,14 +3637,14 @@ canonicalize_values_mark (variable_def **slot, dataflow_set *set)
    variables, canonicalizing equivalence sets into star shapes.  */
 
 int
-canonicalize_values_star (variable_def **slot, dataflow_set *set)
+canonicalize_values_star (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
-  location_chain node;
+  location_chain *node;
   decl_or_value cdv;
   rtx val, cval;
-  variable_def **cslot;
+  variable **cslot;
   bool has_value;
   bool has_marks;
 
@@ -3738,7 +3761,7 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
          }
        else if (GET_CODE (node->loc) == REG)
          {
-           attrs list = set->regs[REGNO (node->loc)], *listp;
+           attrs *list = set->regs[REGNO (node->loc)], **listp;
 
            /* Change an existing attribute referring to dv so that it
               refers to cdv, removing any duplicate this might
@@ -3767,7 +3790,7 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
                    if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
                      {
                        *listp = list->next;
-                       pool_free (attrs_pool, list);
+                       delete list;
                        list = *listp;
                        break;
                      }
@@ -3785,7 +3808,7 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
                    if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
                      {
                        *listp = list->next;
-                       pool_free (attrs_pool, list);
+                       delete list;
                        list = *listp;
                        break;
                      }
@@ -3796,17 +3819,16 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
            else
              gcc_unreachable ();
 
-#if ENABLE_CHECKING
-           while (list)
-             {
-               if (list->offset == 0
-                   && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
-                       || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
-                 gcc_unreachable ();
+           if (flag_checking)
+             while (list)
+               {
+                 if (list->offset == 0
+                     && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
+                         || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
+                   gcc_unreachable ();
 
-               list = list->next;
-             }
-#endif
+                 list = list->next;
+               }
          }
       }
 
@@ -3835,16 +3857,16 @@ canonicalize_values_star (variable_def **slot, dataflow_set *set)
    get to a variable that references another member of the set.  */
 
 int
-canonicalize_vars_star (variable_def **slot, dataflow_set *set)
+canonicalize_vars_star (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
   decl_or_value dv = var->dv;
-  location_chain node;
+  location_chain *node;
   rtx cval;
   decl_or_value cdv;
-  variable_def **cslot;
-  variable cvar;
-  location_chain cnode;
+  variable **cslot;
+  variable *cvar;
+  location_chain *cnode;
 
   if (!var->onepart || var->onepart == ONEPART_VALUE)
     return 1;
@@ -3893,16 +3915,16 @@ canonicalize_vars_star (variable_def **slot, dataflow_set *set)
    intersection.  */
 
 static int
-variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
+variable_merge_over_cur (variable *s1var, struct dfset_merge *dsm)
 {
   dataflow_set *dst = dsm->dst;
-  variable_def **dstslot;
-  variable s2var, dvar = NULL;
+  variable **dstslot;
+  variable *s2var, *dvar = NULL;
   decl_or_value dv = s1var->dv;
-  onepart_enum_t onepart = s1var->onepart;
+  onepart_enum onepart = s1var->onepart;
   rtx val;
   hashval_t dvhash;
-  location_chain node, *nodep;
+  location_chain *node, **nodep;
 
   /* If the incoming onepart variable has an empty location list, then
      the intersection will be just as empty.  For other variables,
@@ -3966,7 +3988,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
        {
          if (node)
            {
-             dvar = (variable) pool_alloc (onepart_pool (onepart));
+             dvar = onepart_pool_allocate (onepart);
              dvar->dv = dv;
              dvar->refcount = 1;
              dvar->n_var_parts = 1;
@@ -3993,11 +4015,11 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
   nodep = &dvar->var_part[0].loc_chain;
   while ((node = *nodep))
     {
-      location_chain *nextp = &node->next;
+      location_chain **nextp = &node->next;
 
       if (GET_CODE (node->loc) == REG)
        {
-         attrs list;
+         attrs *list;
 
          for (list = dst->regs[REGNO (node->loc)]; list; list = list->next)
            if (GET_MODE (node->loc) == GET_MODE (list->loc)
@@ -4093,7 +4115,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
              if (GET_CODE (node->loc) == VALUE)
                {
                  decl_or_value dv = dv_from_value (node->loc);
-                 variable_def **slot = NULL;
+                 variable **slot = NULL;
 
                  if (shared_hash_shared (dst->vars))
                    slot = shared_hash_find_slot_noinsert (dst->vars, dv);
@@ -4102,8 +4124,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
                                                          INSERT);
                  if (!*slot)
                    {
-                     variable var = (variable) pool_alloc (onepart_pool
-                                                           (ONEPART_VALUE));
+                     variable *var = onepart_pool_allocate (ONEPART_VALUE);
                      var->dv = dv;
                      var->refcount = 1;
                      var->n_var_parts = 1;
@@ -4154,14 +4175,14 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
    variable_merge_over_cur().  */
 
 static int
-variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
+variable_merge_over_src (variable *s2var, struct dfset_merge *dsm)
 {
   dataflow_set *dst = dsm->dst;
   decl_or_value dv = s2var->dv;
 
   if (!s2var->onepart)
     {
-      variable_def **dstp = shared_hash_find_slot (dst->vars, dv);
+      variable **dstp = shared_hash_find_slot (dst->vars, dv);
       *dstp = s2var;
       s2var->refcount++;
       return 1;
@@ -4183,16 +4204,16 @@ dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
   int i;
   size_t src1_elems, src2_elems;
   variable_iterator_type hi;
-  variable var;
+  variable *var;
 
-  src1_elems = shared_hash_htab (src1->vars).elements ();
-  src2_elems = shared_hash_htab (src2->vars).elements ();
+  src1_elems = shared_hash_htab (src1->vars)->elements ();
+  src2_elems = shared_hash_htab (src2->vars)->elements ();
   dataflow_set_init (dst);
   dst->stack_adjust = cur.stack_adjust;
   shared_hash_destroy (dst->vars);
-  dst->vars = (shared_hash) pool_alloc (shared_hash_pool);
+  dst->vars = new shared_hash;
   dst->vars->refcount = 1;
-  dst->vars->htab.create (MAX (src1_elems, src2_elems));
+  dst->vars->htab = new variable_table_type (MAX (src1_elems, src2_elems));
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
@@ -4202,10 +4223,10 @@ dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
   dsm.cur = src1;
   dsm.src_onepart_cnt = 0;
 
-  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (dsm.src->vars),
+  FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.src->vars),
                               var, variable, hi)
     variable_merge_over_src (var, &dsm);
-  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (dsm.cur->vars),
+  FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.cur->vars),
                               var, variable, hi)
     variable_merge_over_cur (var, &dsm);
 
@@ -4221,7 +4242,7 @@ static void
 dataflow_set_equiv_regs (dataflow_set *set)
 {
   int i;
-  attrs list, *listp;
+  attrs *list, **listp;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -4276,7 +4297,7 @@ dataflow_set_equiv_regs (dataflow_set *set)
        if (list->offset == 0 && dv_onepart_p (list->dv))
          {
            rtx cval = canon[(int)GET_MODE (list->loc)];
-           variable_def **slot;
+           variable **slot;
 
            if (!cval)
              continue;
@@ -4300,9 +4321,9 @@ dataflow_set_equiv_regs (dataflow_set *set)
    be unshared and 1-part.  */
 
 static void
-remove_duplicate_values (variable var)
+remove_duplicate_values (variable *var)
 {
-  location_chain node, *nodep;
+  location_chain *node, **nodep;
 
   gcc_assert (var->onepart);
   gcc_assert (var->n_var_parts == 1);
@@ -4316,7 +4337,7 @@ remove_duplicate_values (variable var)
            {
              /* Remove duplicate value node.  */
              *nodep = node->next;
-             pool_free (loc_chain_pool, node);
+             delete node;
              continue;
            }
          else
@@ -4348,11 +4369,11 @@ struct dfset_post_merge
    variables that don't have value numbers for them.  */
 
 int
-variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
+variable_post_merge_new_vals (variable **slot, dfset_post_merge *dfpm)
 {
   dataflow_set *set = dfpm->set;
-  variable var = *slot;
-  location_chain node;
+  variable *var = *slot;
+  location_chain *node;
 
   if (!var->onepart || !var->n_var_parts)
     return 1;
@@ -4370,7 +4391,7 @@ variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
            gcc_assert (!VALUE_RECURSED_INTO (node->loc));
          else if (GET_CODE (node->loc) == REG)
            {
-             attrs att, *attp, *curp = NULL;
+             attrs *att, **attp, **curp = NULL;
 
              if (var->refcount != 1)
                {
@@ -4469,7 +4490,7 @@ variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
                 to be added when we bring perm in.  */
              att = *curp;
              *curp = att->next;
-             pool_free (attrs_pool, att);
+             delete att;
            }
        }
 
@@ -4484,13 +4505,13 @@ variable_post_merge_new_vals (variable_def **slot, dfset_post_merge *dfpm)
    chosen expression.  */
 
 int
-variable_post_merge_perm_vals (variable_def **pslot, dfset_post_merge *dfpm)
+variable_post_merge_perm_vals (variable **pslot, dfset_post_merge *dfpm)
 {
   dataflow_set *set = dfpm->set;
-  variable pvar = *pslot, var;
-  location_chain pnode;
+  variable *pvar = *pslot, *var;
+  location_chain *pnode;
   decl_or_value dv;
-  attrs att;
+  attrs *att;
 
   gcc_assert (dv_is_value_p (pvar->dv)
              && pvar->n_var_parts == 1);
@@ -4552,27 +4573,27 @@ dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
   dfpm.permp = permp;
 
   shared_hash_htab (set->vars)
-    .traverse <dfset_post_merge*, variable_post_merge_new_vals> (&dfpm);
+    ->traverse <dfset_post_merge*, variable_post_merge_new_vals> (&dfpm);
   if (*permp)
     shared_hash_htab ((*permp)->vars)
-      .traverse <dfset_post_merge*, variable_post_merge_perm_vals> (&dfpm);
+      ->traverse <dfset_post_merge*, variable_post_merge_perm_vals> (&dfpm);
   shared_hash_htab (set->vars)
-    .traverse <dataflow_set *, canonicalize_values_star> (set);
+    ->traverse <dataflow_set *, canonicalize_values_star> (set);
   shared_hash_htab (set->vars)
-    .traverse <dataflow_set *, canonicalize_vars_star> (set);
+    ->traverse <dataflow_set *, canonicalize_vars_star> (set);
 }
 
 /* Return a node whose loc is a MEM that refers to EXPR in the
    location list of a one-part variable or value VAR, or in that of
    any values recursively mentioned in the location lists.  */
 
-static location_chain
-find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type vars)
+static location_chain *
+find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
 {
-  location_chain node;
+  location_chain *node;
   decl_or_value dv;
-  variable var;
-  location_chain where = NULL;
+  variable *var;
+  location_chain *where = NULL;
 
   if (!val)
     return NULL;
@@ -4581,7 +4602,7 @@ find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type vars)
              && !VALUE_RECURSED_INTO (val));
 
   dv = dv_from_value (val);
-  var = vars.find_with_hash (dv, dv_htab_hash (dv));
+  var = vars->find_with_hash (dv, dv_htab_hash (dv));
 
   if (!var)
     return NULL;
@@ -4639,14 +4660,14 @@ mem_dies_at_call (rtx mem)
    the variable itself, directly or within a VALUE.  */
 
 int
-dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
     {
       tree decl = dv_as_decl (var->dv);
-      location_chain loc, *locp;
+      location_chain *loc, **locp;
       bool changed = false;
 
       if (!var->n_var_parts)
@@ -4658,11 +4679,11 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
        {
          for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
            {
-             /* We want to remove dying MEMs that doesn't refer to DECL.  */
+             /* We want to remove dying MEMs that don't refer to DECL.  */
              if (GET_CODE (loc->loc) == MEM
                  && (MEM_EXPR (loc->loc) != decl
                      || INT_MEM_OFFSET (loc->loc) != 0)
-                 && !mem_dies_at_call (loc->loc))
+                 && mem_dies_at_call (loc->loc))
                break;
              /* We want to move here MEMs that do refer to DECL.  */
              else if (GET_CODE (loc->loc) == VALUE
@@ -4685,7 +4706,7 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
          rtx old_loc = loc->loc;
          if (GET_CODE (old_loc) == VALUE)
            {
-             location_chain mem_node
+             location_chain *mem_node
                = find_mem_expr_in_1pdv (decl, loc->loc,
                                         shared_hash_htab (set->vars));
 
@@ -4729,7 +4750,7 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
                }
            }
          *locp = loc->next;
-         pool_free (loc_chain_pool, loc);
+         delete loc;
        }
 
       if (!var->var_part[0].loc_chain)
@@ -4745,16 +4766,16 @@ dataflow_set_preserve_mem_locs (variable_def **slot, dataflow_set *set)
 }
 
 /* Remove all MEMs from the location list of a hash table entry for a
-   value.  */
+   onepart variable.  */
 
 int
-dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
+dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
-  if (var->onepart == ONEPART_VALUE)
+  if (var->onepart != NOT_ONEPART)
     {
-      location_chain loc, *locp;
+      location_chain *loc, **locp;
       bool changed = false;
       rtx cur_loc;
 
@@ -4801,7 +4822,7 @@ dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
              if (VAR_LOC_1PAUX (var))
                VAR_LOC_FROM (var) = NULL;
            }
-         pool_free (loc_chain_pool, loc);
+         delete loc;
        }
 
       if (!var->var_part[0].loc_chain)
@@ -4820,22 +4841,26 @@ dataflow_set_remove_mem_locs (variable_def **slot, dataflow_set *set)
    registers, as well as associations between MEMs and VALUEs.  */
 
 static void
-dataflow_set_clear_at_call (dataflow_set *set)
+dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
 {
   unsigned int r;
   hard_reg_set_iterator hrsi;
+  HARD_REG_SET invalidated_regs;
 
-  EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, r, hrsi)
+  get_call_reg_set_usage (call_insn, &invalidated_regs,
+                         regs_invalidated_by_call);
+
+  EXECUTE_IF_SET_IN_HARD_REG_SET (invalidated_regs, 0, r, hrsi)
     var_regno_delete (set, r);
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
       set->traversed_vars = set->vars;
       shared_hash_htab (set->vars)
-       .traverse <dataflow_set *, dataflow_set_preserve_mem_locs> (set);
+       ->traverse <dataflow_set *, dataflow_set_preserve_mem_locs> (set);
       set->traversed_vars = set->vars;
       shared_hash_htab (set->vars)
-       .traverse <dataflow_set *, dataflow_set_remove_mem_locs> (set);
+       ->traverse <dataflow_set *, dataflow_set_remove_mem_locs> (set);
       set->traversed_vars = NULL;
     }
 }
@@ -4843,7 +4868,7 @@ dataflow_set_clear_at_call (dataflow_set *set)
 static bool
 variable_part_different_p (variable_part *vp1, variable_part *vp2)
 {
-  location_chain lc1, lc2;
+  location_chain *lc1, *lc2;
 
   for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
     {
@@ -4867,9 +4892,9 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2)
    They must be in canonical order.  */
 
 static bool
-onepart_variable_different_p (variable var1, variable var2)
+onepart_variable_different_p (variable *var1, variable *var2)
 {
-  location_chain lc1, lc2;
+  location_chain *lc1, *lc2;
 
   if (var1 == var2)
     return false;
@@ -4893,10 +4918,67 @@ onepart_variable_different_p (variable var1, variable var2)
   return lc1 != lc2;
 }
 
+/* Return true if one-part variables VAR1 and VAR2 are different.
+   They must be in canonical order.  */
+
+static void
+dump_onepart_variable_differences (variable *var1, variable *var2)
+{
+  location_chain *lc1, *lc2;
+
+  gcc_assert (var1 != var2);
+  gcc_assert (dump_file);
+  gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
+  gcc_assert (var1->n_var_parts == 1
+             && var2->n_var_parts == 1);
+
+  lc1 = var1->var_part[0].loc_chain;
+  lc2 = var2->var_part[0].loc_chain;
+
+  gcc_assert (lc1 && lc2);
+
+  while (lc1 && lc2)
+    {
+      switch (loc_cmp (lc1->loc, lc2->loc))
+       {
+       case -1:
+         fprintf (dump_file, "removed: ");
+         print_rtl_single (dump_file, lc1->loc);
+         lc1 = lc1->next;
+         continue;
+       case 0:
+         break;
+       case 1:
+         fprintf (dump_file, "added: ");
+         print_rtl_single (dump_file, lc2->loc);
+         lc2 = lc2->next;
+         continue;
+       default:
+         gcc_unreachable ();
+       }
+      lc1 = lc1->next;
+      lc2 = lc2->next;
+    }
+
+  while (lc1)
+    {
+      fprintf (dump_file, "removed: ");
+      print_rtl_single (dump_file, lc1->loc);
+      lc1 = lc1->next;
+    }
+
+  while (lc2)
+    {
+      fprintf (dump_file, "added: ");
+      print_rtl_single (dump_file, lc2->loc);
+      lc2 = lc2->next;
+    }
+}
+
 /* Return true if variables VAR1 and VAR2 are different.  */
 
 static bool
-variable_different_p (variable var1, variable var2)
+variable_different_p (variable *var1, variable *var2)
 {
   int i;
 
@@ -4935,20 +5017,33 @@ static bool
 dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
 {
   variable_iterator_type hi;
-  variable var1;
+  variable *var1;
+  bool diffound = false;
+  bool details = (dump_file && (dump_flags & TDF_DETAILS));
+
+#define RETRUE                                 \
+  do                                           \
+    {                                          \
+      if (!details)                            \
+       return true;                            \
+      else                                     \
+       diffound = true;                        \
+    }                                          \
+  while (0)
 
   if (old_set->vars == new_set->vars)
     return false;
 
-  if (shared_hash_htab (old_set->vars).elements ()
-      != shared_hash_htab (new_set->vars).elements ())
-    return true;
+  if (shared_hash_htab (old_set->vars)->elements ()
+      != shared_hash_htab (new_set->vars)->elements ())
+    RETRUE;
 
-  FOR_EACH_HASH_TABLE_ELEMENT (shared_hash_htab (old_set->vars),
+  FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (old_set->vars),
                               var1, variable, hi)
     {
-      variable_table_type htab = shared_hash_htab (new_set->vars);
-      variable var2 = htab.find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+      variable_table_type *htab = shared_hash_htab (new_set->vars);
+      variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+
       if (!var2)
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4956,26 +5051,49 @@ dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
              fprintf (dump_file, "dataflow difference found: removal of:\n");
              dump_var (var1);
            }
-         return true;
+         RETRUE;
        }
-
-      if (variable_different_p (var1, var2))
+      else if (variable_different_p (var1, var2))
        {
-         if (dump_file && (dump_flags & TDF_DETAILS))
+         if (details)
            {
              fprintf (dump_file, "dataflow difference found: "
                       "old and new follow:\n");
              dump_var (var1);
+             if (dv_onepart_p (var1->dv))
+               dump_onepart_variable_differences (var1, var2);
              dump_var (var2);
            }
-         return true;
+         RETRUE;
        }
     }
 
-  /* No need to traverse the second hashtab, if both have the same number
-     of elements and the second one had all entries found in the first one,
-     then it can't have any extra entries.  */
-  return false;
+  /* There's no need to traverse the second hashtab unless we want to
+     print the details.  If both have the same number of elements and
+     the second one had all entries found in the first one, then the
+     second can't have any extra entries.  */
+  if (!details)
+    return diffound;
+
+  FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (new_set->vars),
+                              var1, variable, hi)
+    {
+      variable_table_type *htab = shared_hash_htab (old_set->vars);
+      variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
+      if (!var2)
+       {
+         if (details)
+           {
+             fprintf (dump_file, "dataflow difference found: addition of:\n");
+             dump_var (var1);
+           }
+         RETRUE;
+       }
+    }
+
+#undef RETRUE
+
+  return diffound;
 }
 
 /* Free the contents of dataflow set SET.  */
@@ -4992,40 +5110,26 @@ dataflow_set_destroy (dataflow_set *set)
   set->vars = NULL;
 }
 
-/* Return true if RTL X contains a SYMBOL_REF.  */
+/* Return true if T is a tracked parameter with non-degenerate record type.  */
 
 static bool
-contains_symbol_ref (rtx x)
+tracked_record_parameter_p (tree t)
 {
-  const char *fmt;
-  RTX_CODE code;
-  int i;
+  if (TREE_CODE (t) != PARM_DECL)
+    return false;
 
-  if (!x)
+  if (DECL_MODE (t) == BLKmode)
     return false;
 
-  code = GET_CODE (x);
-  if (code == SYMBOL_REF)
-    return true;
+  tree type = TREE_TYPE (t);
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return false;
 
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (contains_symbol_ref (XEXP (x, i)))
-           return true;
-       }
-      else if (fmt[i] == 'E')
-       {
-         int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           if (contains_symbol_ref (XVECEXP (x, i, j)))
-             return true;
-       }
-    }
+  if (TYPE_FIELDS (type) == NULL_TREE
+      || DECL_CHAIN (TYPE_FIELDS (type)) == NULL_TREE)
+    return false;
 
-  return false;
+  return true;
 }
 
 /* Shall EXPR be tracked?  */
@@ -5040,7 +5144,7 @@ track_expr_p (tree expr, bool need_rtl)
     return DECL_RTL_SET_P (expr);
 
   /* If EXPR is not a parameter or a variable do not track it.  */
-  if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
+  if (!VAR_P (expr) && TREE_CODE (expr) != PARM_DECL)
     return 0;
 
   /* It also must have a name...  */
@@ -5056,7 +5160,7 @@ track_expr_p (tree expr, bool need_rtl)
      don't need to track this expression if the ultimate declaration is
      ignored.  */
   realdecl = expr;
-  if (TREE_CODE (realdecl) == VAR_DECL && DECL_HAS_DEBUG_EXPR_P (realdecl))
+  if (VAR_P (realdecl) && DECL_HAS_DEBUG_EXPR_P (realdecl))
     {
       realdecl = DECL_DEBUG_EXPR (realdecl);
       if (!DECL_P (realdecl))
@@ -5066,16 +5170,15 @@ track_expr_p (tree expr, bool need_rtl)
                  && TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
            {
              HOST_WIDE_INT bitsize, bitpos, maxsize;
+             bool reverse;
              tree innerdecl
                = get_ref_base_and_extent (realdecl, &bitpos, &bitsize,
-                                          &maxsize);
+                                          &maxsize, &reverse);
              if (!DECL_P (innerdecl)
                  || DECL_IGNORED_P (innerdecl)
-                 /* Do not track declarations for parts of tracked parameters
-                    since we want to track them as a whole instead.  */
-                 || (TREE_CODE (innerdecl) == PARM_DECL
-                     && DECL_MODE (innerdecl) != BLKmode
-                     && TREE_CODE (TREE_TYPE (innerdecl)) != UNION_TYPE)
+                 /* Do not track declarations for parts of tracked record
+                    parameters since we want to track them as a whole.  */
+                 || tracked_record_parameter_p (innerdecl)
                  || TREE_STATIC (innerdecl)
                  || bitsize <= 0
                  || bitpos + bitsize > 256
@@ -5108,7 +5211,7 @@ track_expr_p (tree expr, bool need_rtl)
      char **_dl_argv;
   */
   if (decl_rtl && MEM_P (decl_rtl)
-      && contains_symbol_ref (XEXP (decl_rtl, 0)))
+      && contains_symbol_ref_p (XEXP (decl_rtl, 0)))
     return 0;
 
   /* If RTX is a memory it should not be very large (because it would be
@@ -5116,8 +5219,9 @@ track_expr_p (tree expr, bool need_rtl)
   if (decl_rtl && MEM_P (decl_rtl))
     {
       /* Do not track structures and arrays.  */
-      if (GET_MODE (decl_rtl) == BLKmode
-         || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
+      if ((GET_MODE (decl_rtl) == BLKmode
+          || AGGREGATE_TYPE_P (TREE_TYPE (realdecl)))
+         && !tracked_record_parameter_p (realdecl))
        return 0;
       if (MEM_SIZE_KNOWN_P (decl_rtl)
          && MEM_SIZE (decl_rtl) > MAX_VAR_PARTS)
@@ -5175,9 +5279,9 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
 
 static bool
 track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
-            enum machine_mode *mode_out, HOST_WIDE_INT *offset_out)
+            machine_mode *mode_out, HOST_WIDE_INT *offset_out)
 {
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (expr == NULL || !track_expr_p (expr, true))
     return false;
@@ -5187,10 +5291,10 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
   mode = GET_MODE (loc);
   if (REG_P (loc) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc)))
     {
-      enum machine_mode pseudo_mode;
+      machine_mode pseudo_mode;
 
       pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
-      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
+      if (paradoxical_subreg_p (mode, pseudo_mode))
        {
          offset += byte_lowpart_offset (pseudo_mode, mode);
          mode = pseudo_mode;
@@ -5204,7 +5308,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
      because the real and imaginary parts are represented as separate
      pseudo registers, even if the whole complex value fits into one
      hard register.  */
-  if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
+  if ((paradoxical_subreg_p (mode, DECL_MODE (expr))
        || (store_reg_p
           && !COMPLEX_MODE_P (DECL_MODE (expr))
           && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))
@@ -5229,7 +5333,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
    on the returned value are updated.  */
 
 static rtx
-var_lowpart (enum machine_mode mode, rtx loc)
+var_lowpart (machine_mode mode, rtx loc)
 {
   unsigned int offset, reg_offset, regno;
 
@@ -5255,7 +5359,7 @@ var_lowpart (enum machine_mode mode, rtx loc)
 struct count_use_info
 {
   /* The insn where the RTX is.  */
-  rtx insn;
+  rtx_insn *insn;
 
   /* The basic block where insn is.  */
   basic_block bb;
@@ -5271,7 +5375,7 @@ struct count_use_info
 /* Find a VALUE corresponding to X.   */
 
 static inline cselib_val *
-find_use_val (rtx x, enum machine_mode mode, struct count_use_info *cui)
+find_use_val (rtx x, machine_mode mode, struct count_use_info *cui)
 {
   int i;
 
@@ -5325,23 +5429,23 @@ replace_expr_with_values (rtx loc)
     return cselib_subst_to_values (loc, VOIDmode);
 }
 
-/* Return true if *X is a DEBUG_EXPR.  Usable as an argument to
-   for_each_rtx to tell whether there are any DEBUG_EXPRs within
-   RTX.  */
+/* Return true if X contains a DEBUG_EXPR.  */
 
-static int
-rtx_debug_expr_p (rtx *x, void *data ATTRIBUTE_UNUSED)
+static bool
+rtx_debug_expr_p (const_rtx x)
 {
-  rtx loc = *x;
-
-  return GET_CODE (loc) == DEBUG_EXPR;
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
+    if (GET_CODE (*iter) == DEBUG_EXPR)
+      return true;
+  return false;
 }
 
 /* Determine what kind of micro operation to choose for a USE.  Return
    MO_CLOBBER if no micro operation is to be generated.  */
 
 static enum micro_operation_type
-use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
+use_type (rtx loc, struct count_use_info *cui, machine_mode *modep)
 {
   tree expr;
 
@@ -5424,7 +5528,7 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
                  DEBUG_EXPRs (only happens in the presence of debug
                  insns).  */
               && (!MAY_HAVE_DEBUG_INSNS
-                  || !for_each_rtx (&XEXP (loc, 0), rtx_debug_expr_p, NULL)))
+                  || !rtx_debug_expr_p (XEXP (loc, 0))))
        return MO_USE;
       else
        return MO_CLOBBER;
@@ -5437,7 +5541,7 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
    INSN of BB.  */
 
 static inline void
-log_op_type (rtx x, basic_block bb, rtx insn,
+log_op_type (rtx x, basic_block bb, rtx_insn *insn,
             enum micro_operation_type mopt, FILE *out)
 {
   fprintf (out, "bb %i op %i insn %i %s ",
@@ -5481,38 +5585,41 @@ preserve_value (cselib_val *val)
    any rtxes not suitable for CONST use not replaced by VALUEs
    are discovered.  */
 
-static int
-non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED)
+static bool
+non_suitable_const (const_rtx x)
 {
-  if (*x == NULL_RTX)
-    return 0;
-
-  switch (GET_CODE (*x))
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
     {
-    case REG:
-    case DEBUG_EXPR:
-    case PC:
-    case SCRATCH:
-    case CC0:
-    case ASM_INPUT:
-    case ASM_OPERANDS:
-      return 1;
-    case MEM:
-      return !MEM_READONLY_P (*x);
-    default:
-      return 0;
+      const_rtx x = *iter;
+      switch (GET_CODE (x))
+       {
+       case REG:
+       case DEBUG_EXPR:
+       case PC:
+       case SCRATCH:
+       case CC0:
+       case ASM_INPUT:
+       case ASM_OPERANDS:
+         return true;
+       case MEM:
+         if (!MEM_READONLY_P (x))
+           return true;
+         break;
+       default:
+         break;
+       }
     }
+  return false;
 }
 
 /* Add uses (register and memory references) LOC which will be tracked
-   to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
+   to VTI (bb)->mos.  */
 
-static int
-add_uses (rtx *ploc, void *data)
+static void
+add_uses (rtx loc, struct count_use_info *cui)
 {
-  rtx loc = *ploc;
-  enum machine_mode mode = VOIDmode;
-  struct count_use_info *cui = (struct count_use_info *)data;
+  machine_mode mode = VOIDmode;
   enum micro_operation_type type = use_type (loc, cui, &mode);
 
   if (type != MO_CLOBBER)
@@ -5537,7 +5644,7 @@ add_uses (rtx *ploc, void *data)
              && !MEM_P (XEXP (vloc, 0)))
            {
              rtx mloc = vloc;
-             enum machine_mode address_mode = get_address_mode (mloc);
+             machine_mode address_mode = get_address_mode (mloc);
              cselib_val *val
                = cselib_lookup (XEXP (mloc, 0), address_mode, 0,
                                 GET_MODE (mloc));
@@ -5547,13 +5654,12 @@ add_uses (rtx *ploc, void *data)
            }
 
          if (CONSTANT_P (vloc)
-             && (GET_CODE (vloc) != CONST
-                 || for_each_rtx (&vloc, non_suitable_const, NULL)))
+             && (GET_CODE (vloc) != CONST || non_suitable_const (vloc)))
            /* For constants don't look up any value.  */;
          else if (!VAR_LOC_UNKNOWN_P (vloc) && !unsuitable_loc (vloc)
                   && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
            {
-             enum machine_mode mode2;
+             machine_mode mode2;
              enum micro_operation_type type2;
              rtx nloc = NULL;
              bool resolvable = REG_P (vloc) || MEM_P (vloc);
@@ -5591,7 +5697,7 @@ add_uses (rtx *ploc, void *data)
        }
       else if (type == MO_VAL_USE)
        {
-         enum machine_mode mode2 = VOIDmode;
+         machine_mode mode2 = VOIDmode;
          enum micro_operation_type type2;
          cselib_val *val = find_use_val (loc, GET_MODE (loc), cui);
          rtx vloc, oloc = loc, nloc;
@@ -5603,7 +5709,7 @@ add_uses (rtx *ploc, void *data)
              && !MEM_P (XEXP (oloc, 0)))
            {
              rtx mloc = oloc;
-             enum machine_mode address_mode = get_address_mode (mloc);
+             machine_mode address_mode = get_address_mode (mloc);
              cselib_val *val
                = cselib_lookup (XEXP (mloc, 0), address_mode, 0,
                                 GET_MODE (mloc));
@@ -5659,8 +5765,6 @@ add_uses (rtx *ploc, void *data)
        log_op_type (mo.u.loc, cui->bb, cui->insn, mo.type, dump_file);
       VTI (bb)->mos.safe_push (mo);
     }
-
-  return 0;
 }
 
 /* Helper function for finding all uses of REG/MEM in X in insn INSN.  */
@@ -5668,7 +5772,9 @@ add_uses (rtx *ploc, void *data)
 static void
 add_uses_1 (rtx *x, void *cui)
 {
-  for_each_rtx (x, add_uses, cui);
+  subrtx_var_iterator::array_type array;
+  FOR_EACH_SUBRTX_VAR (iter, array, *x, NONCONST)
+    add_uses (*iter, (struct count_use_info *) cui);
 }
 
 /* This is the value used during expansion of locations.  We want it
@@ -5689,7 +5795,7 @@ add_uses_1 (rtx *x, void *cui)
    no longer live we can express its value as VAL - 6.  */
 
 static void
-reverse_op (rtx val, const_rtx expr, rtx insn)
+reverse_op (rtx val, const_rtx expr, rtx_insn *insn)
 {
   rtx src, arg, ret;
   cselib_val *v;
@@ -5779,11 +5885,6 @@ reverse_op (rtx val, const_rtx expr, rtx insn)
            return;
        }
       ret = simplify_gen_binary (code, GET_MODE (val), val, arg);
-      if (ret == val)
-       /* Ensure ret isn't VALUE itself (which can happen e.g. for
-          (plus (reg1) (reg2)) when reg2 is known to be 0), as that
-          breaks a lot of routines during var-tracking.  */
-       ret = gen_rtx_fmt_ee (PLUS, GET_MODE (val), val, const0_rtx);
       break;
     default:
       gcc_unreachable ();
@@ -5799,7 +5900,7 @@ reverse_op (rtx val, const_rtx expr, rtx insn)
 static void
 add_stores (rtx loc, const_rtx expr, void *cuip)
 {
-  enum machine_mode mode = VOIDmode, mode2;
+  machine_mode mode = VOIDmode, mode2;
   struct count_use_info *cui = (struct count_use_info *)cuip;
   basic_block bb = cui->bb;
   micro_operation mo;
@@ -5829,7 +5930,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
              && find_use_val (loc, mode, cui))
            {
              gcc_checking_assert (type == MO_VAL_SET);
-             mo.u.loc = gen_rtx_SET (VOIDmode, loc, SET_SRC (expr));
+             mo.u.loc = gen_rtx_SET (loc, SET_SRC (expr));
            }
        }
       else
@@ -5847,7 +5948,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
            }
          else
            {
-             rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
+             rtx xexpr = gen_rtx_SET (loc, src);
              if (same_variable_part_p (src, REG_EXPR (loc), REG_OFFSET (loc)))
                {
                  /* If this is an instruction copying (part of) a parameter
@@ -5883,7 +5984,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
          && !MEM_P (XEXP (loc, 0)))
        {
          rtx mloc = loc;
-         enum machine_mode address_mode = get_address_mode (mloc);
+         machine_mode address_mode = get_address_mode (mloc);
          cselib_val *val = cselib_lookup (XEXP (mloc, 0),
                                           address_mode, 0,
                                           GET_MODE (mloc));
@@ -5912,7 +6013,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
            }
          else
            {
-             rtx xexpr = gen_rtx_SET (VOIDmode, loc, src);
+             rtx xexpr = gen_rtx_SET (loc, src);
              if (same_variable_part_p (SET_SRC (xexpr),
                                        MEM_EXPR (loc),
                                        INT_MEM_OFFSET (loc)))
@@ -5930,21 +6031,6 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
   if (type != MO_VAL_SET)
     goto log_and_return;
 
-  /* We cannot track values for multiple-part variables, so we track only
-     locations for tracked parameters passed either by invisible reference
-     or directly in multiple locations.  */
-  if (track_p
-      && REG_P (loc)
-      && REG_EXPR (loc)
-      && TREE_CODE (REG_EXPR (loc)) == PARM_DECL
-      && DECL_MODE (REG_EXPR (loc)) != BLKmode
-      && TREE_CODE (TREE_TYPE (REG_EXPR (loc))) != UNION_TYPE
-      && ((MEM_P (DECL_INCOMING_RTL (REG_EXPR (loc)))
-          && XEXP (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) != arg_pointer_rtx)
-          || (GET_CODE (DECL_INCOMING_RTL (REG_EXPR (loc))) == PARALLEL
-             && XVECLEN (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) > 1)))
-    goto log_and_return;
-
   v = find_use_val (oloc, mode, cui);
 
   if (!v)
@@ -5952,6 +6038,22 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
 
   resolve = preserve = !cselib_preserved_value_p (v);
 
+  /* We cannot track values for multiple-part variables, so we track only
+     locations for tracked record parameters.  */
+  if (track_p
+      && REG_P (loc)
+      && REG_EXPR (loc)
+      && tracked_record_parameter_p (REG_EXPR (loc)))
+    {
+      /* Although we don't use the value here, it could be used later by the
+        mere virtue of its existence as the operand of the reverse operation
+        that gave rise to it (typically extension/truncation).  Make sure it
+        is preserved as required by vt_expand_var_loc_chain.  */
+      if (preserve)
+       preserve_value (v);
+      goto log_and_return;
+    }
+
   if (loc == stack_pointer_rtx
       && hard_frame_pointer_adjustment != -1
       && preserve)
@@ -5965,7 +6067,8 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
     {
       cselib_val *oval = cselib_lookup (oloc, GET_MODE (oloc), 0, VOIDmode);
 
-      gcc_assert (oval != v);
+      if (oval == v)
+       return;
       gcc_assert (REG_P (oloc) || MEM_P (oloc));
 
       if (oval && !cselib_preserved_value_p (oval))
@@ -6002,7 +6105,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
        }
 
       if (nloc && nloc != SET_SRC (mo.u.loc))
-       oloc = gen_rtx_SET (GET_MODE (mo.u.loc), oloc, nloc);
+       oloc = gen_rtx_SET (oloc, nloc);
       else
        {
          if (oloc == SET_DEST (mo.u.loc))
@@ -6078,7 +6181,7 @@ static rtx call_arguments;
 /* Compute call_arguments.  */
 
 static void
-prepare_call_arguments (basic_block bb, rtx insn)
+prepare_call_arguments (basic_block bb, rtx_insn *insn)
 {
   rtx link, x, call;
   rtx prev, cur, next;
@@ -6132,7 +6235,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
                  && targetm.calls.struct_value_rtx (type, 0) == 0)
                {
                  tree struct_addr = build_pointer_type (TREE_TYPE (type));
-                 enum machine_mode mode = TYPE_MODE (struct_addr);
+                 machine_mode mode = TYPE_MODE (struct_addr);
                  rtx reg;
                  INIT_CUMULATIVE_ARGS (args_so_far_v, type, NULL_RTX, fndecl,
                                        nargs + 1);
@@ -6157,7 +6260,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
                                      nargs);
              if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node)
                {
-                 enum machine_mode mode;
+                 machine_mode mode;
                  t = TYPE_ARG_TYPES (type);
                  mode = TYPE_MODE (TREE_VALUE (t));
                  this_arg = targetm.calls.function_arg (args_so_far, mode,
@@ -6188,24 +6291,28 @@ prepare_call_arguments (basic_block bb, rtx insn)
        if (GET_MODE (link) == VOIDmode
            || GET_MODE (link) == BLKmode
            || (GET_MODE (link) != GET_MODE (x)
-               && (GET_MODE_CLASS (GET_MODE (link)) != MODE_INT
-                   || GET_MODE_CLASS (GET_MODE (x)) != MODE_INT)))
+               && ((GET_MODE_CLASS (GET_MODE (link)) != MODE_INT
+                    && GET_MODE_CLASS (GET_MODE (link)) != MODE_PARTIAL_INT)
+                   || (GET_MODE_CLASS (GET_MODE (x)) != MODE_INT
+                       && GET_MODE_CLASS (GET_MODE (x)) != MODE_PARTIAL_INT))))
          /* Can't do anything for these, if the original type mode
             isn't known or can't be converted.  */;
        else if (REG_P (x))
          {
            cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
+           scalar_int_mode mode;
            if (val && cselib_preserved_value_p (val))
              item = val->val_rtx;
-           else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+           else if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
              {
-               enum machine_mode mode = GET_MODE (x);
-
-               while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode
-                      && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
+               opt_scalar_int_mode mode_iter;
+               FOR_EACH_WIDER_MODE (mode_iter, mode)
                  {
-                   rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
+                   mode = mode_iter.require ();
+                   if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
+                     break;
 
+                   rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
                    if (reg == NULL_RTX || !REG_P (reg))
                      continue;
                    val = cselib_lookup (reg, mode, 0, VOIDmode);
@@ -6227,21 +6334,22 @@ prepare_call_arguments (basic_block bb, rtx insn)
                struct adjust_mem_data amd;
                amd.mem_mode = VOIDmode;
                amd.stack_adjust = -VTI (bb)->out.stack_adjust;
-               amd.side_effects = NULL_RTX;
                amd.store = true;
                mem = simplify_replace_fn_rtx (mem, NULL_RTX, adjust_mems,
                                               &amd);
-               gcc_assert (amd.side_effects == NULL_RTX);
+               gcc_assert (amd.side_effects.is_empty ());
              }
            val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode);
            if (val && cselib_preserved_value_p (val))
              item = val->val_rtx;
-           else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT)
+           else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT
+                    && GET_MODE_CLASS (GET_MODE (mem)) != MODE_PARTIAL_INT)
              {
                /* For non-integer stack argument see also if they weren't
                   initialized by integers.  */
-               enum machine_mode imode = int_mode_for_mode (GET_MODE (mem));
-               if (imode != GET_MODE (mem) && imode != BLKmode)
+               scalar_int_mode imode;
+               if (int_mode_for_mode (GET_MODE (mem)).exists (&imode)
+                   && imode != GET_MODE (mem))
                  {
                    val = cselib_lookup (adjust_address_nv (mem, imode, 0),
                                         imode, 0, VOIDmode);
@@ -6265,7 +6373,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
        if (t && t != void_list_node)
          {
            tree argtype = TREE_VALUE (t);
-           enum machine_mode mode = TYPE_MODE (argtype);
+           machine_mode mode = TYPE_MODE (argtype);
            rtx reg;
            if (pass_by_reference (&args_so_far_v, mode, argtype, true))
              {
@@ -6279,13 +6387,14 @@ prepare_call_arguments (basic_block bb, rtx insn)
                && reg
                && REG_P (reg)
                && GET_MODE (reg) == mode
-               && GET_MODE_CLASS (mode) == MODE_INT
+               && (GET_MODE_CLASS (mode) == MODE_INT
+                   || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
                && REG_P (x)
                && REGNO (x) == REGNO (reg)
                && GET_MODE (x) == mode
                && item)
              {
-               enum machine_mode indmode
+               machine_mode indmode
                  = TYPE_MODE (TREE_TYPE (argtype));
                rtx mem = gen_rtx_MEM (indmode, x);
                cselib_val *val = cselib_lookup (mem, indmode, 0, VOIDmode);
@@ -6346,7 +6455,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
            {
              rtx item;
              tree dtemp = (**debug_args)[ix + 1];
-             enum machine_mode mode = DECL_MODE (dtemp);
+             machine_mode mode = DECL_MODE (dtemp);
              item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
              item = gen_rtx_CONCAT (mode, item, DECL_RTL_KNOWN_SET (dtemp));
              call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
@@ -6391,7 +6500,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
     }
   if (this_arg)
     {
-      enum machine_mode mode
+      machine_mode mode
        = TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref)));
       rtx clobbered = gen_rtx_MEM (mode, this_arg);
       HOST_WIDE_INT token
@@ -6414,7 +6523,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
    first place, in which case sets and n_sets will be 0).  */
 
 static void
-add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
+add_with_sets (rtx_insn *insn, struct cselib_set *sets, int n_sets)
 {
   basic_block bb = BLOCK_FOR_INSN (insn);
   int n1, n2;
@@ -6443,13 +6552,7 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
       while (n1 < n2 && mos[n2].type != MO_USE)
        n2--;
       if (n1 < n2)
-       {
-         micro_operation sw;
-
-         sw = mos[n1];
-         mos[n1] = mos[n2];
-         mos[n2] = sw;
-       }
+       std::swap (mos[n1], mos[n2]);
     }
 
   n2 = VTI (bb)->mos.length () - 1;
@@ -6460,13 +6563,7 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
       while (n1 < n2 && mos[n2].type == MO_VAL_LOC)
        n2--;
       if (n1 < n2)
-       {
-         micro_operation sw;
-
-         sw = mos[n1];
-         mos[n1] = mos[n2];
-         mos[n2] = sw;
-       }
+       std::swap (mos[n1], mos[n2]);
     }
 
   if (CALL_P (insn))
@@ -6502,13 +6599,7 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
       while (n1 < n2 && mos[n2].type != MO_VAL_USE)
        n2--;
       if (n1 < n2)
-       {
-         micro_operation sw;
-
-         sw = mos[n1];
-         mos[n1] = mos[n2];
-         mos[n2] = sw;
-       }
+       std::swap (mos[n1], mos[n2]);
     }
 
   n2 = VTI (bb)->mos.length () - 1;
@@ -6519,13 +6610,7 @@ add_with_sets (rtx insn, struct cselib_set *sets, int n_sets)
       while (n1 < n2 && mos[n2].type != MO_CLOBBER)
        n2--;
       if (n1 < n2)
-       {
-         micro_operation sw;
-
-         sw = mos[n1];
-         mos[n1] = mos[n2];
-         mos[n2] = sw;
-       }
+       std::swap (mos[n1], mos[n2]);
     }
 }
 
@@ -6558,8 +6643,8 @@ find_src_set_src (dataflow_set *set, rtx src)
 {
   tree decl = NULL_TREE;   /* The variable being copied around.          */
   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
-  variable var;
-  location_chain nextp;
+  variable *var;
+  location_chain *nextp;
   int i;
   bool found;
 
@@ -6608,16 +6693,16 @@ compute_bb_dataflow (basic_block bb)
   dataflow_set_copy (out, in);
 
   if (MAY_HAVE_DEBUG_INSNS)
-    local_get_addr_cache = pointer_map_create ();
+    local_get_addr_cache = new hash_map<rtx, rtx>;
 
   FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo)
     {
-      rtx insn = mo->insn;
+      rtx_insn *insn = mo->insn;
 
       switch (mo->type)
        {
          case MO_CALL:
-           dataflow_set_clear_at_call (out);
+           dataflow_set_clear_at_call (out, insn);
            break;
 
          case MO_USE:
@@ -6891,18 +6976,17 @@ compute_bb_dataflow (basic_block bb)
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
-      pointer_map_destroy (local_get_addr_cache);
+      delete local_get_addr_cache;
       local_get_addr_cache = NULL;
 
       dataflow_set_equiv_regs (out);
       shared_hash_htab (out->vars)
-       .traverse <dataflow_set *, canonicalize_values_mark> (out);
+       ->traverse <dataflow_set *, canonicalize_values_mark> (out);
       shared_hash_htab (out->vars)
-       .traverse <dataflow_set *, canonicalize_values_star> (out);
-#if ENABLE_CHECKING
-      shared_hash_htab (out->vars)
-       .traverse <dataflow_set *, canonicalize_loc_order_check> (out);
-#endif
+       ->traverse <dataflow_set *, canonicalize_values_star> (out);
+      if (flag_checking)
+       shared_hash_htab (out->vars)
+         ->traverse <dataflow_set *, canonicalize_loc_order_check> (out);
     }
   changed = dataflow_set_different (&old_out, out);
   dataflow_set_destroy (&old_out);
@@ -6914,8 +6998,9 @@ compute_bb_dataflow (basic_block bb)
 static bool
 vt_find_locations (void)
 {
-  fibheap_t worklist, pending, fibheap_swap;
-  sbitmap visited, in_worklist, in_pending, sbitmap_swap;
+  bb_heap_t *worklist = new bb_heap_t (LONG_MIN);
+  bb_heap_t *pending = new bb_heap_t (LONG_MIN);
+  sbitmap in_worklist, in_pending;
   basic_block bb;
   edge e;
   int *bb_order;
@@ -6935,31 +7020,25 @@ vt_find_locations (void)
     bb_order[rc_order[i]] = i;
   free (rc_order);
 
-  worklist = fibheap_new ();
-  pending = fibheap_new ();
-  visited = sbitmap_alloc (last_basic_block_for_fn (cfun));
+  auto_sbitmap visited (last_basic_block_for_fn (cfun));
   in_worklist = sbitmap_alloc (last_basic_block_for_fn (cfun));
   in_pending = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_clear (in_worklist);
 
   FOR_EACH_BB_FN (bb, cfun)
-    fibheap_insert (pending, bb_order[bb->index], bb);
+    pending->insert (bb_order[bb->index], bb);
   bitmap_ones (in_pending);
 
-  while (success && !fibheap_empty (pending))
+  while (success && !pending->empty ())
     {
-      fibheap_swap = pending;
-      pending = worklist;
-      worklist = fibheap_swap;
-      sbitmap_swap = in_pending;
-      in_pending = in_worklist;
-      in_worklist = sbitmap_swap;
+      std::swap (worklist, pending);
+      std::swap (in_worklist, in_pending);
 
       bitmap_clear (visited);
 
-      while (!fibheap_empty (worklist))
+      while (!worklist->empty ())
        {
-         bb = (basic_block) fibheap_extract_min (worklist);
+         bb = worklist->extract_min ();
          bitmap_clear_bit (in_worklist, bb->index);
          gcc_assert (!bitmap_bit_p (visited, bb->index));
          if (!bitmap_bit_p (visited, bb->index))
@@ -6973,10 +7052,11 @@ vt_find_locations (void)
              if (VTI (bb)->in.vars)
                {
                  htabsz
-                   -= shared_hash_htab (VTI (bb)->in.vars).size ()
-                       + shared_hash_htab (VTI (bb)->out.vars).size ();
-                 oldinsz = shared_hash_htab (VTI (bb)->in.vars).elements ();
-                 oldoutsz = shared_hash_htab (VTI (bb)->out.vars).elements ();
+                   -= shared_hash_htab (VTI (bb)->in.vars)->size ()
+                       + shared_hash_htab (VTI (bb)->out.vars)->size ();
+                 oldinsz = shared_hash_htab (VTI (bb)->in.vars)->elements ();
+                 oldoutsz
+                   = shared_hash_htab (VTI (bb)->out.vars)->elements ();
                }
              else
                oldinsz = oldoutsz = 0;
@@ -7011,13 +7091,14 @@ vt_find_locations (void)
                  if (adjust)
                    {
                      dataflow_post_merge_adjust (in, &VTI (bb)->permp);
-#if ENABLE_CHECKING
-                     /* Merge and merge_adjust should keep entries in
-                        canonical order.  */
-                     shared_hash_htab (in->vars)
-                       .traverse <dataflow_set *,
-                                  canonicalize_loc_order_check> (in);
-#endif
+
+                     if (flag_checking)
+                       /* Merge and merge_adjust should keep entries in
+                          canonical order.  */
+                       shared_hash_htab (in->vars)
+                         ->traverse <dataflow_set *,
+                                     canonicalize_loc_order_check> (in);
+
                      if (dst_can_be_shared)
                        {
                          shared_hash_destroy (in->vars);
@@ -7036,8 +7117,8 @@ vt_find_locations (void)
                }
 
              changed = compute_bb_dataflow (bb);
-             htabsz += shared_hash_htab (VTI (bb)->in.vars).size ()
-                        + shared_hash_htab (VTI (bb)->out.vars).size ();
+             htabsz += shared_hash_htab (VTI (bb)->in.vars)->size ()
+                        + shared_hash_htab (VTI (bb)->out.vars)->size ();
 
              if (htabmax && htabsz > htabmax)
                {
@@ -7065,17 +7146,16 @@ vt_find_locations (void)
                            {
                              /* Send E->DEST to next round.  */
                              bitmap_set_bit (in_pending, e->dest->index);
-                             fibheap_insert (pending,
-                                             bb_order[e->dest->index],
-                                             e->dest);
+                             pending->insert (bb_order[e->dest->index],
+                                              e->dest);
                            }
                        }
                      else if (!bitmap_bit_p (in_worklist, e->dest->index))
                        {
                          /* Add E->DEST to current round.  */
                          bitmap_set_bit (in_worklist, e->dest->index);
-                         fibheap_insert (worklist, bb_order[e->dest->index],
-                                         e->dest);
+                         worklist->insert (bb_order[e->dest->index],
+                                           e->dest);
                        }
                    }
                }
@@ -7084,11 +7164,12 @@ vt_find_locations (void)
                fprintf (dump_file,
                         "BB %i: in %i (was %i), out %i (was %i), rem %i + %i, tsz %i\n",
                         bb->index,
-                        (int)shared_hash_htab (VTI (bb)->in.vars).size (),
+                        (int)shared_hash_htab (VTI (bb)->in.vars)->size (),
                         oldinsz,
-                        (int)shared_hash_htab (VTI (bb)->out.vars).size (),
+                        (int)shared_hash_htab (VTI (bb)->out.vars)->size (),
                         oldoutsz,
-                        (int)worklist->nodes, (int)pending->nodes, htabsz);
+                        (int)worklist->nodes (), (int)pending->nodes (),
+                        htabsz);
 
              if (dump_file && (dump_flags & TDF_DETAILS))
                {
@@ -7106,9 +7187,8 @@ vt_find_locations (void)
       gcc_assert (VTI (bb)->flooded);
 
   free (bb_order);
-  fibheap_delete (worklist);
-  fibheap_delete (pending);
-  sbitmap_free (visited);
+  delete worklist;
+  delete pending;
   sbitmap_free (in_worklist);
   sbitmap_free (in_pending);
 
@@ -7119,7 +7199,7 @@ vt_find_locations (void)
 /* Print the content of the LIST to dump file.  */
 
 static void
-dump_attrs_list (attrs list)
+dump_attrs_list (attrs *list)
 {
   for (; list; list = list->next)
     {
@@ -7135,9 +7215,9 @@ dump_attrs_list (attrs list)
 /* Print the information about variable *SLOT to dump file.  */
 
 int
-dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
+dump_var_tracking_slot (variable **slot, void *data ATTRIBUTE_UNUSED)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   dump_var (var);
 
@@ -7148,10 +7228,10 @@ dump_var_tracking_slot (variable_def **slot, void *data ATTRIBUTE_UNUSED)
 /* Print the information about variable VAR to dump file.  */
 
 static void
-dump_var (variable var)
+dump_var (variable *var)
 {
   int i;
-  location_chain node;
+  location_chain *node;
 
   if (dv_is_decl_p (var->dv))
     {
@@ -7193,12 +7273,12 @@ dump_var (variable var)
 /* Print the information about variables from hash table VARS to dump file.  */
 
 static void
-dump_vars (variable_table_type vars)
+dump_vars (variable_table_type *vars)
 {
-  if (vars.elements () > 0)
+  if (vars->elements () > 0)
     {
       fprintf (dump_file, "Variables:\n");
-      vars.traverse <void *, dump_var_tracking_slot> (NULL);
+      vars->traverse <void *, dump_var_tracking_slot> (NULL);
     }
 }
 
@@ -7243,14 +7323,14 @@ dump_dataflow_sets (void)
 /* Return the variable for DV in dropped_values, inserting one if
    requested with INSERT.  */
 
-static inline variable
+static inline variable *
 variable_from_dropped (decl_or_value dv, enum insert_option insert)
 {
-  variable_def **slot;
-  variable empty_var;
-  onepart_enum_t onepart;
+  variable **slot;
+  variable *empty_var;
+  onepart_enum onepart;
 
-  slot = dropped_values.find_slot_with_hash (dv, dv_htab_hash (dv), insert);
+  slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv), insert);
 
   if (!slot)
     return NULL;
@@ -7264,7 +7344,7 @@ variable_from_dropped (decl_or_value dv, enum insert_option insert)
 
   gcc_checking_assert (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR);
 
-  empty_var = (variable) pool_alloc (onepart_pool (onepart));
+  empty_var = onepart_pool_allocate (onepart);
   empty_var->dv = dv;
   empty_var->refcount = 1;
   empty_var->n_var_parts = 0;
@@ -7283,9 +7363,9 @@ variable_from_dropped (decl_or_value dv, enum insert_option insert)
 /* Recover the one-part aux from dropped_values.  */
 
 static struct onepart_aux *
-recover_dropped_1paux (variable var)
+recover_dropped_1paux (variable *var)
 {
-  variable dvar;
+  variable *dvar;
 
   gcc_checking_assert (var->onepart);
 
@@ -7310,22 +7390,22 @@ recover_dropped_1paux (variable var)
    if it has no locations delete it from SET's hash table.  */
 
 static void
-variable_was_changed (variable var, dataflow_set *set)
+variable_was_changed (variable *var, dataflow_set *set)
 {
   hashval_t hash = dv_htab_hash (var->dv);
 
   if (emit_notes)
     {
-      variable_def **slot;
+      variable **slot;
 
       /* Remember this decl or VALUE has been added to changed_variables.  */
       set_dv_changed (var->dv, true);
 
-      slot = changed_variables.find_slot_with_hash (var->dv, hash, INSERT);
+      slot = changed_variables->find_slot_with_hash (var->dv, hash, INSERT);
 
       if (*slot)
        {
-         variable old_var = *slot;
+         variable *old_var = *slot;
          gcc_assert (old_var->in_changed_variables);
          old_var->in_changed_variables = false;
          if (var != old_var && var->onepart)
@@ -7342,15 +7422,15 @@ variable_was_changed (variable var, dataflow_set *set)
 
       if (set && var->n_var_parts == 0)
        {
-         onepart_enum_t onepart = var->onepart;
-         variable empty_var = NULL;
-         variable_def **dslot = NULL;
+         onepart_enum onepart = var->onepart;
+         variable *empty_var = NULL;
+         variable **dslot = NULL;
 
          if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
            {
-             dslot = dropped_values.find_slot_with_hash (var->dv,
-                                               dv_htab_hash (var->dv),
-                                               INSERT);
+             dslot = dropped_values->find_slot_with_hash (var->dv,
+                                                          dv_htab_hash (var->dv),
+                                                          INSERT);
              empty_var = *dslot;
 
              if (empty_var)
@@ -7368,7 +7448,7 @@ variable_was_changed (variable var, dataflow_set *set)
 
          if (!empty_var)
            {
-             empty_var = (variable) pool_alloc (onepart_pool (onepart));
+             empty_var = onepart_pool_allocate (onepart);
              empty_var->dv = var->dv;
              empty_var->refcount = 1;
              empty_var->n_var_parts = 0;
@@ -7406,7 +7486,7 @@ variable_was_changed (variable var, dataflow_set *set)
       gcc_assert (set);
       if (var->n_var_parts == 0)
        {
-         variable_def **slot;
+         variable **slot;
 
        drop_var:
          slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
@@ -7415,7 +7495,7 @@ variable_was_changed (variable var, dataflow_set *set)
              if (shared_hash_shared (set->vars))
                slot = shared_hash_find_slot_unshare (&set->vars, var->dv,
                                                      NO_INSERT);
-             shared_hash_htab (set->vars).clear_slot (slot);
+             shared_hash_htab (set->vars)->clear_slot (slot);
            }
        }
     }
@@ -7427,7 +7507,7 @@ variable_was_changed (variable var, dataflow_set *set)
    have, if it should be inserted.  */
 
 static inline int
-find_variable_location_part (variable var, HOST_WIDE_INT offset,
+find_variable_location_part (variable *var, HOST_WIDE_INT offset,
                             int *insertion_point)
 {
   int pos, low, high;
@@ -7465,16 +7545,16 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
   return -1;
 }
 
-static variable_def **
-set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+set_slot_part (dataflow_set *set, rtx loc, variable **slot,
               decl_or_value dv, HOST_WIDE_INT offset,
               enum var_init_status initialized, rtx set_src)
 {
   int pos;
-  location_chain node, next;
-  location_chain *nextp;
-  variable var;
-  onepart_enum_t onepart;
+  location_chain *node, *next;
+  location_chain **nextp;
+  variable *var;
+  onepart_enum onepart;
 
   var = *slot;
 
@@ -7492,7 +7572,7 @@ set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
   if (!var)
     {
       /* Create new variable information.  */
-      var = (variable) pool_alloc (onepart_pool (onepart));
+      var = onepart_pool_allocate (onepart);
       var->dv = dv;
       var->refcount = 1;
       var->n_var_parts = 1;
@@ -7687,7 +7767,7 @@ set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
                set_src = node->set_src;
              if (var->var_part[pos].cur_loc == node->loc)
                var->var_part[pos].cur_loc = NULL;
-             pool_free (loc_chain_pool, node);
+             delete node;
              *nextp = next;
              break;
            }
@@ -7699,7 +7779,7 @@ set_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
     }
 
   /* Add the location to the beginning.  */
-  node = (location_chain) pool_alloc (loc_chain_pool);
+  node = new location_chain;
   node->loc = loc;
   node->init = initialized;
   node->set_src = set_src;
@@ -7725,7 +7805,7 @@ set_variable_part (dataflow_set *set, rtx loc,
                   enum var_init_status initialized, rtx set_src,
                   enum insert_option iopt)
 {
-  variable_def **slot;
+  variable **slot;
 
   if (iopt == NO_INSERT)
     slot = shared_hash_find_slot_noinsert (set->vars, dv);
@@ -7743,16 +7823,16 @@ set_variable_part (dataflow_set *set, rtx loc,
    The variable part is specified by variable's declaration or value
    DV and offset OFFSET.  */
 
-static variable_def **
-clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+clobber_slot_part (dataflow_set *set, rtx loc, variable **slot,
                   HOST_WIDE_INT offset, rtx set_src)
 {
-  variable var = *slot;
+  variable *var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);
 
   if (pos >= 0)
     {
-      location_chain node, next;
+      location_chain *node, *next;
 
       /* Remove the register locations from the dataflow set.  */
       next = var->var_part[pos].loc_chain;
@@ -7767,8 +7847,8 @@ clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
            {
              if (REG_P (node->loc))
                {
-                 attrs anode, anext;
-                 attrs *anextp;
+                 attrs *anode, *anext;
+                 attrs **anextp;
 
                  /* Remove the variable part from the register's
                     list, but preserve any other variable parts
@@ -7781,7 +7861,7 @@ clobber_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
                      if (dv_as_opaque (anode->dv) == dv_as_opaque (var->dv)
                          && anode->offset == offset)
                        {
-                         pool_free (attrs_pool, anode);
+                         delete anode;
                          *anextp = anext;
                        }
                      else
@@ -7806,7 +7886,7 @@ static void
 clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
                       HOST_WIDE_INT offset, rtx set_src)
 {
-  variable_def **slot;
+  variable **slot;
 
   if (!dv_as_opaque (dv)
       || (!dv_is_value_p (dv) && ! DECL_P (dv_as_decl (dv))))
@@ -7823,17 +7903,17 @@ clobber_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
    variable part is specified by its SET->vars slot SLOT and offset
    OFFSET and the part's location by LOC.  */
 
-static variable_def **
-delete_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
+static variable **
+delete_slot_part (dataflow_set *set, rtx loc, variable **slot,
                  HOST_WIDE_INT offset)
 {
-  variable var = *slot;
+  variable *var = *slot;
   int pos = find_variable_location_part (var, offset, NULL);
 
   if (pos >= 0)
     {
-      location_chain node, next;
-      location_chain *nextp;
+      location_chain *node, *next;
+      location_chain **nextp;
       bool changed;
       rtx cur_loc;
 
@@ -7881,7 +7961,7 @@ delete_slot_part (dataflow_set *set, rtx loc, variable_def **slot,
                  if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
                    VAR_LOC_FROM (var) = NULL;
                }
-             pool_free (loc_chain_pool, node);
+             delete node;
              *nextp = next;
              break;
            }
@@ -7914,7 +7994,7 @@ static void
 delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
                      HOST_WIDE_INT offset)
 {
-  variable_def **slot = shared_hash_find_slot_noinsert (set->vars, dv);
+  variable **slot = shared_hash_find_slot_noinsert (set->vars, dv);
   if (!slot)
     return;
 
@@ -7927,7 +8007,7 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
 struct expand_loc_callback_data
 {
   /* The variables and values active at this point.  */
-  variable_table_type vars;
+  variable_table_type *vars;
 
   /* Stack of values and debug_exprs under expansion, and their
      children.  */
@@ -7950,7 +8030,7 @@ struct expand_loc_callback_data
    room for COUNT dependencies.  */
 
 static void
-loc_exp_dep_alloc (variable var, int count)
+loc_exp_dep_alloc (variable *var, int count)
 {
   size_t allocsize;
 
@@ -7998,7 +8078,7 @@ loc_exp_dep_alloc (variable var, int count)
    removing them from the back-links lists too.  */
 
 static void
-loc_exp_dep_clear (variable var)
+loc_exp_dep_clear (variable *var)
 {
   while (VAR_LOC_DEP_VEC (var) && !VAR_LOC_DEP_VEC (var)->is_empty ())
     {
@@ -8016,17 +8096,17 @@ loc_exp_dep_clear (variable var)
    back-links in VARS.  */
 
 static void
-loc_exp_insert_dep (variable var, rtx x, variable_table_type vars)
+loc_exp_insert_dep (variable *var, rtx x, variable_table_type *vars)
 {
   decl_or_value dv;
-  variable xvar;
+  variable *xvar;
   loc_exp_dep *led;
 
   dv = dv_from_rtx (x);
 
   /* ??? Build a vector of variables parallel to EXPANDING, to avoid
      an additional look up?  */
-  xvar = vars.find_with_hash (dv, dv_htab_hash (dv));
+  xvar = vars->find_with_hash (dv, dv_htab_hash (dv));
 
   if (!xvar)
     {
@@ -8042,7 +8122,7 @@ loc_exp_insert_dep (variable var, rtx x, variable_table_type vars)
     return;
 
   if (var->onepart == NOT_ONEPART)
-    led = (loc_exp_dep *) pool_alloc (loc_exp_dep_pool);
+    led = new loc_exp_dep;
   else
     {
       loc_exp_dep empty;
@@ -8066,8 +8146,8 @@ loc_exp_insert_dep (variable var, rtx x, variable_table_type vars)
    true if we found any pending-recursion results.  */
 
 static bool
-loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
-                variable_table_type vars)
+loc_exp_dep_set (variable *var, rtx result, rtx *value, int count,
+                variable_table_type *vars)
 {
   bool pending_recursion = false;
 
@@ -8096,14 +8176,14 @@ loc_exp_dep_set (variable var, rtx result, rtx *value, int count,
    attempt to compute a current location.  */
 
 static void
-notify_dependents_of_resolved_value (variable ivar, variable_table_type vars)
+notify_dependents_of_resolved_value (variable *ivar, variable_table_type *vars)
 {
   loc_exp_dep *led, *next;
 
   for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
     {
       decl_or_value dv = led->dv;
-      variable var;
+      variable *var;
 
       next = led->next;
 
@@ -8134,7 +8214,7 @@ notify_dependents_of_resolved_value (variable ivar, variable_table_type vars)
            continue;
       }
 
-      var = vars.find_with_hash (dv, dv_htab_hash (dv));
+      var = vars->find_with_hash (dv, dv_htab_hash (dv));
 
       if (!var)
        var = variable_from_dropped (dv, NO_INSERT);
@@ -8188,11 +8268,12 @@ update_depth (expand_depth saved_depth, expand_depth best_depth)
    it is pending recursion resolution.  */
 
 static inline rtx
-vt_expand_var_loc_chain (variable var, bitmap regs, void *data, bool *pendrecp)
+vt_expand_var_loc_chain (variable *var, bitmap regs, void *data,
+                        bool *pendrecp)
 {
   struct expand_loc_callback_data *elcd
     = (struct expand_loc_callback_data *) data;
-  location_chain loc, next;
+  location_chain *loc, *next;
   rtx result = NULL;
   int first_child, result_first_child, last_child;
   bool pending_recursion;
@@ -8332,7 +8413,7 @@ vt_expand_loc_callback (rtx x, bitmap regs,
   struct expand_loc_callback_data *elcd
     = (struct expand_loc_callback_data *) data;
   decl_or_value dv;
-  variable var;
+  variable *var;
   rtx result, subreg;
   bool pending_recursion = false;
   bool from_empty = false;
@@ -8378,7 +8459,7 @@ vt_expand_loc_callback (rtx x, bitmap regs,
       return NULL;
     }
 
-  var = elcd->vars.find_with_hash (dv, dv_htab_hash (dv));
+  var = elcd->vars->find_with_hash (dv, dv_htab_hash (dv));
 
   if (!var)
     {
@@ -8485,7 +8566,7 @@ resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending)
    equivalences in VARS, updating their CUR_LOCs in the process.  */
 
 static rtx
-vt_expand_loc (rtx loc, variable_table_type vars)
+vt_expand_loc (rtx loc, variable_table_type *vars)
 {
   struct expand_loc_callback_data data;
   rtx result;
@@ -8507,7 +8588,7 @@ vt_expand_loc (rtx loc, variable_table_type vars)
    in VARS, updating their CUR_LOCs in the process.  */
 
 static rtx
-vt_expand_1pvar (variable var, variable_table_type vars)
+vt_expand_1pvar (variable *var, variable_table_type *vars)
 {
   struct expand_loc_callback_data data;
   rtx loc;
@@ -8533,13 +8614,14 @@ vt_expand_1pvar (variable var, variable_table_type vars)
    before or after instruction INSN.  */
 
 int
-emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
+emit_note_insn_var_location (variable **varp, emit_note_data *data)
 {
-  variable var = *varp;
-  rtx insn = data->insn;
+  variable *var = *varp;
+  rtx_insn *insn = data->insn;
   enum emit_note_where where = data->where;
-  variable_table_type vars = data->vars;
-  rtx note, note_vl;
+  variable_table_type *vars = data->vars;
+  rtx_note *note;
+  rtx note_vl;
   int i, j, n_var_parts;
   bool complete;
   enum var_init_status initialized = VAR_INIT_STATUS_UNINITIALIZED;
@@ -8548,7 +8630,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
   HOST_WIDE_INT offsets[MAX_VAR_PARTS];
   rtx loc[MAX_VAR_PARTS];
   tree decl;
-  location_chain lc;
+  location_chain *lc;
 
   gcc_checking_assert (var->onepart == NOT_ONEPART
                       || var->onepart == ONEPART_VDECL);
@@ -8564,7 +8646,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
        var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
   for (i = 0; i < var->n_var_parts; i++)
     {
-      enum machine_mode mode, wider_mode;
+      machine_mode mode, wider_mode;
       rtx loc2;
       HOST_WIDE_INT offset;
 
@@ -8624,12 +8706,11 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
 
       /* Attempt to merge adjacent registers or memory.  */
-      wider_mode = GET_MODE_WIDER_MODE (mode);
       for (j = i + 1; j < var->n_var_parts; j++)
        if (last_limit <= VAR_PART_OFFSET (var, j))
          break;
       if (j < var->n_var_parts
-         && wider_mode != VOIDmode
+         && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
          && var->var_part[j].cur_loc
          && mode == GET_MODE (var->var_part[j].cur_loc)
          && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
@@ -8699,8 +8780,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
 
   note_vl = NULL_RTX;
   if (!complete)
-    note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX,
-                                   (int) initialized);
+    note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, NULL_RTX, initialized);
   else if (n_var_parts == 1)
     {
       rtx expr_list;
@@ -8710,8 +8790,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
       else
        expr_list = loc[0];
 
-      note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list,
-                                     (int) initialized);
+      note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl, expr_list, initialized);
     }
   else if (n_var_parts)
     {
@@ -8724,7 +8803,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
       parallel = gen_rtx_PARALLEL (VOIDmode,
                                   gen_rtvec_v (n_var_parts, loc));
       note_vl = gen_rtx_VAR_LOCATION (VOIDmode, decl,
-                                     parallel, (int) initialized);
+                                     parallel, initialized);
     }
 
   if (where != EMIT_NOTE_BEFORE_INSN)
@@ -8755,7 +8834,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
   set_dv_changed (var->dv, false);
   gcc_assert (var->in_changed_variables);
   var->in_changed_variables = false;
-  changed_variables.clear_slot (varp);
+  changed_variables->clear_slot (varp);
 
   /* Continue traversing the hash table.  */
   return 1;
@@ -8765,10 +8844,10 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
    values) entries that aren't user variables.  */
 
 int
-var_track_values_to_stack (variable_def **slot,
+var_track_values_to_stack (variable **slot,
                           vec<rtx, va_heap> *changed_values_stack)
 {
-  variable var = *slot;
+  variable *var = *slot;
 
   if (var->onepart == ONEPART_VALUE)
     changed_values_stack->safe_push (dv_as_value (var->dv));
@@ -8784,14 +8863,14 @@ static void
 remove_value_from_changed_variables (rtx val)
 {
   decl_or_value dv = dv_from_rtx (val);
-  variable_def **slot;
-  variable var;
+  variable **slot;
+  variable *var;
 
-  slot = changed_variables.find_slot_with_hash (dv, dv_htab_hash (dv),
+  slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
                                                NO_INSERT);
   var = *slot;
   var->in_changed_variables = false;
-  changed_variables.clear_slot (slot);
+  changed_variables->clear_slot (slot);
 }
 
 /* If VAL (a value or debug_expr) has backlinks to variables actively
@@ -8800,27 +8879,27 @@ remove_value_from_changed_variables (rtx val)
    have dependencies of their own to notify.  */
 
 static void
-notify_dependents_of_changed_value (rtx val, variable_table_type htab,
+notify_dependents_of_changed_value (rtx val, variable_table_type *htab,
                                    vec<rtx, va_heap> *changed_values_stack)
 {
-  variable_def **slot;
-  variable var;
+  variable **slot;
+  variable *var;
   loc_exp_dep *led;
   decl_or_value dv = dv_from_rtx (val);
 
-  slot = changed_variables.find_slot_with_hash (dv, dv_htab_hash (dv),
+  slot = changed_variables->find_slot_with_hash (dv, dv_htab_hash (dv),
                                                NO_INSERT);
   if (!slot)
-    slot = htab.find_slot_with_hash (dv, dv_htab_hash (dv), NO_INSERT);
+    slot = htab->find_slot_with_hash (dv, dv_htab_hash (dv), NO_INSERT);
   if (!slot)
-    slot = dropped_values.find_slot_with_hash (dv, dv_htab_hash (dv),
-                                              NO_INSERT);
+    slot = dropped_values->find_slot_with_hash (dv, dv_htab_hash (dv),
+                                               NO_INSERT);
   var = *slot;
 
   while ((led = VAR_LOC_DEP_LST (var)))
     {
       decl_or_value ldv = led->dv;
-      variable ivar;
+      variable *ivar;
 
       /* Deactivate and remove the backlink, as it was “used up”.  It
         makes no sense to attempt to notify the same entity again:
@@ -8845,14 +8924,14 @@ notify_dependents_of_changed_value (rtx val, variable_table_type htab,
          break;
 
        case ONEPART_VDECL:
-         ivar = htab.find_with_hash (ldv, dv_htab_hash (ldv));
+         ivar = htab->find_with_hash (ldv, dv_htab_hash (ldv));
          gcc_checking_assert (!VAR_LOC_DEP_LST (ivar));
          variable_was_changed (ivar, NULL);
          break;
 
        case NOT_ONEPART:
-         pool_free (loc_exp_dep_pool, led);
-         ivar = htab.find_with_hash (ldv, dv_htab_hash (ldv));
+         delete led;
+         ivar = htab->find_with_hash (ldv, dv_htab_hash (ldv));
          if (ivar)
            {
              int i = ivar->n_var_parts;
@@ -8882,7 +8961,7 @@ notify_dependents_of_changed_value (rtx val, variable_table_type htab,
    CHANGED_VARIABLES.  */
 
 static void
-process_changed_values (variable_table_type htab)
+process_changed_values (variable_table_type *htab)
 {
   int i, n;
   rtx val;
@@ -8890,7 +8969,7 @@ process_changed_values (variable_table_type htab)
 
   /* Move values from changed_variables to changed_values_stack.  */
   changed_variables
-    .traverse <vec<rtx, va_heap>*, var_track_values_to_stack>
+    ->traverse <vec<rtx, va_heap>*, var_track_values_to_stack>
       (&changed_values_stack);
 
   /* Back-propagate change notifications in values while popping
@@ -8918,13 +8997,13 @@ process_changed_values (variable_table_type htab)
    the notes shall be emitted before of after instruction INSN.  */
 
 static void
-emit_notes_for_changes (rtx insn, enum emit_note_where where,
-                       shared_hash vars)
+emit_notes_for_changes (rtx_insn *insn, enum emit_note_where where,
+                       shared_hash *vars)
 {
   emit_note_data data;
-  variable_table_type htab = shared_hash_htab (vars);
+  variable_table_type *htab = shared_hash_htab (vars);
 
-  if (!changed_variables.elements ())
+  if (!changed_variables->elements ())
     return;
 
   if (MAY_HAVE_DEBUG_INSNS)
@@ -8935,24 +9014,24 @@ emit_notes_for_changes (rtx insn, enum emit_note_where where,
   data.vars = htab;
 
   changed_variables
-    .traverse <emit_note_data*, emit_note_insn_var_location> (&data);
+    ->traverse <emit_note_data*, emit_note_insn_var_location> (&data);
 }
 
 /* Add variable *SLOT to the chain CHANGED_VARIABLES if it differs from the
    same variable in hash table DATA or is not there at all.  */
 
 int
-emit_notes_for_differences_1 (variable_def **slot, variable_table_type new_vars)
+emit_notes_for_differences_1 (variable **slot, variable_table_type *new_vars)
 {
-  variable old_var, new_var;
+  variable *old_var, *new_var;
 
   old_var = *slot;
-  new_var = new_vars.find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));
+  new_var = new_vars->find_with_hash (old_var->dv, dv_htab_hash (old_var->dv));
 
   if (!new_var)
     {
       /* Variable has disappeared.  */
-      variable empty_var = NULL;
+      variable *empty_var = NULL;
 
       if (old_var->onepart == ONEPART_VALUE
          || old_var->onepart == ONEPART_DEXPR)
@@ -8973,7 +9052,7 @@ emit_notes_for_differences_1 (variable_def **slot, variable_table_type new_vars)
 
       if (!empty_var)
        {
-         empty_var = (variable) pool_alloc (onepart_pool (old_var->onepart));
+         empty_var = onepart_pool_allocate (old_var->onepart);
          empty_var->dv = old_var->dv;
          empty_var->refcount = 0;
          empty_var->n_var_parts = 0;
@@ -9014,12 +9093,12 @@ emit_notes_for_differences_1 (variable_def **slot, variable_table_type new_vars)
    table DATA.  */
 
 int
-emit_notes_for_differences_2 (variable_def **slot, variable_table_type old_vars)
+emit_notes_for_differences_2 (variable **slot, variable_table_type *old_vars)
 {
-  variable old_var, new_var;
+  variable *old_var, *new_var;
 
   new_var = *slot;
-  old_var = old_vars.find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
+  old_var = old_vars->find_with_hash (new_var->dv, dv_htab_hash (new_var->dv));
   if (!old_var)
     {
       int i;
@@ -9036,22 +9115,22 @@ emit_notes_for_differences_2 (variable_def **slot, variable_table_type old_vars)
    NEW_SET.  */
 
 static void
-emit_notes_for_differences (rtx insn, dataflow_set *old_set,
+emit_notes_for_differences (rtx_insn *insn, dataflow_set *old_set,
                            dataflow_set *new_set)
 {
   shared_hash_htab (old_set->vars)
-    .traverse <variable_table_type, emit_notes_for_differences_1>
+    ->traverse <variable_table_type *, emit_notes_for_differences_1>
       (shared_hash_htab (new_set->vars));
   shared_hash_htab (new_set->vars)
-    .traverse <variable_table_type, emit_notes_for_differences_2>
+    ->traverse <variable_table_type *, emit_notes_for_differences_2>
       (shared_hash_htab (old_set->vars));
   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN, new_set->vars);
 }
 
 /* Return the next insn after INSN that is not a NOTE_INSN_VAR_LOCATION.  */
 
-static rtx
-next_non_note_insn_var_location (rtx insn)
+static rtx_insn *
+next_non_note_insn_var_location (rtx_insn *insn)
 {
   while (insn)
     {
@@ -9078,16 +9157,17 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
 
   FOR_EACH_VEC_ELT (VTI (bb)->mos, i, mo)
     {
-      rtx insn = mo->insn;
-      rtx next_insn = next_non_note_insn_var_location (insn);
+      rtx_insn *insn = mo->insn;
+      rtx_insn *next_insn = next_non_note_insn_var_location (insn);
 
       switch (mo->type)
        {
          case MO_CALL:
-           dataflow_set_clear_at_call (set);
+           dataflow_set_clear_at_call (set, insn);
            emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars);
            {
-             rtx arguments = mo->u.loc, *p = &arguments, note;
+             rtx arguments = mo->u.loc, *p = &arguments;
+             rtx_note *note;
              while (*p)
                {
                  XEXP (XEXP (*p, 0), 1)
@@ -9399,7 +9479,7 @@ vt_emit_notes (void)
   basic_block bb;
   dataflow_set cur;
 
-  gcc_assert (!changed_variables.elements ());
+  gcc_assert (!changed_variables->elements ());
 
   /* Free memory occupied by the out hash tables, as they aren't used
      anymore.  */
@@ -9412,9 +9492,7 @@ vt_emit_notes (void)
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
-      dropped_values.create (cselib_get_next_uid () * 2);
-      loc_exp_dep_pool = create_alloc_pool ("loc_exp_dep pool",
-                                           sizeof (loc_exp_dep), 64);
+      dropped_values = new variable_table_type (cselib_get_next_uid () * 2);
     }
 
   dataflow_set_init (&cur);
@@ -9426,28 +9504,30 @@ vt_emit_notes (void)
       emit_notes_for_differences (BB_HEAD (bb), &cur, &VTI (bb)->in);
 
       if (MAY_HAVE_DEBUG_INSNS)
-       local_get_addr_cache = pointer_map_create ();
+       local_get_addr_cache = new hash_map<rtx, rtx>;
 
       /* Emit the notes for the changes in the basic block itself.  */
       emit_notes_in_bb (bb, &cur);
 
       if (MAY_HAVE_DEBUG_INSNS)
-       pointer_map_destroy (local_get_addr_cache);
+       delete local_get_addr_cache;
       local_get_addr_cache = NULL;
 
       /* Free memory occupied by the in hash table, we won't need it
         again.  */
       dataflow_set_clear (&VTI (bb)->in);
     }
-#ifdef ENABLE_CHECKING
-  shared_hash_htab (cur.vars)
-    .traverse <variable_table_type, emit_notes_for_differences_1>
-      (shared_hash_htab (empty_shared_hash));
-#endif
+
+  if (flag_checking)
+    shared_hash_htab (cur.vars)
+      ->traverse <variable_table_type *, emit_notes_for_differences_1>
+       (shared_hash_htab (empty_shared_hash));
+
   dataflow_set_destroy (&cur);
 
   if (MAY_HAVE_DEBUG_INSNS)
-    dropped_values.dispose ();
+    delete dropped_values;
+  dropped_values = NULL;
 
   emit_notes = false;
 }
@@ -9526,7 +9606,7 @@ vt_add_function_parameter (tree parm)
   rtx decl_rtl = DECL_RTL_IF_SET (parm);
   rtx incoming = DECL_INCOMING_RTL (parm);
   tree decl;
-  enum machine_mode mode;
+  machine_mode mode;
   HOST_WIDE_INT offset;
   dataflow_set *out;
   decl_or_value dv;
@@ -9570,7 +9650,7 @@ vt_add_function_parameter (tree parm)
          && HARD_REGISTER_P (incoming)
          && OUTGOING_REGNO (REGNO (incoming)) != REGNO (incoming))
        {
-         parm_reg_t p;
+         parm_reg p;
          p.incoming = incoming;
          incoming
            = gen_rtx_REG_offset (incoming, GET_MODE (incoming),
@@ -9587,7 +9667,7 @@ vt_add_function_parameter (tree parm)
          for (i = 0; i < XVECLEN (incoming, 0); i++)
            {
              rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
-             parm_reg_t p;
+             parm_reg p;
              p.incoming = reg;
              reg = gen_rtx_REG_offset (reg, GET_MODE (reg),
                                        OUTGOING_REGNO (REGNO (reg)), 0);
@@ -9607,7 +9687,7 @@ vt_add_function_parameter (tree parm)
          rtx reg = XEXP (incoming, 0);
          if (OUTGOING_REGNO (REGNO (reg)) != REGNO (reg))
            {
-             parm_reg_t p;
+             parm_reg p;
              p.incoming = reg;
              reg = gen_raw_REG (GET_MODE (reg), OUTGOING_REGNO (REGNO (reg)));
              p.outgoing = reg;
@@ -9717,7 +9797,7 @@ vt_add_function_parameter (tree parm)
          if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
              && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
            {
-             enum machine_mode indmode
+             machine_mode indmode
                = TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
              rtx mem = gen_rtx_MEM (indmode, incoming);
              cselib_val *val = cselib_lookup_from_insn (mem, indmode, true,
@@ -9764,7 +9844,8 @@ vt_add_function_parameters (void)
 
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm; parm = DECL_CHAIN (parm))
-    vt_add_function_parameter (parm);
+    if (!POINTER_BOUNDS_P (parm))
+      vt_add_function_parameter (parm);
 
   if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl)))
     {
@@ -9829,23 +9910,12 @@ vt_initialize (void)
   basic_block bb;
   HOST_WIDE_INT fp_cfa_offset = -1;
 
-  alloc_aux_for_blocks (sizeof (struct variable_tracking_info_def));
-
-  attrs_pool = create_alloc_pool ("attrs_def pool",
-                                 sizeof (struct attrs_def), 1024);
-  var_pool = create_alloc_pool ("variable_def pool",
-                               sizeof (struct variable_def)
-                               + (MAX_VAR_PARTS - 1)
-                               * sizeof (((variable)NULL)->var_part[0]), 64);
-  loc_chain_pool = create_alloc_pool ("location_chain_def pool",
-                                     sizeof (struct location_chain_def),
-                                     1024);
-  shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
-                                       sizeof (struct shared_hash_def), 256);
-  empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
+  alloc_aux_for_blocks (sizeof (variable_tracking_info));
+
+  empty_shared_hash = shared_hash_pool.allocate ();
   empty_shared_hash->refcount = 1;
-  empty_shared_hash->htab.create (1);
-  changed_variables.create (10);
+  empty_shared_hash->htab = new variable_table_type (1);
+  changed_variables = new variable_table_type (10);
 
   /* Init the IN and OUT sets.  */
   FOR_ALL_BB_FN (bb, cfun)
@@ -9861,15 +9931,12 @@ vt_initialize (void)
     {
       cselib_init (CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS);
       scratch_regs = BITMAP_ALLOC (NULL);
-      valvar_pool = create_alloc_pool ("small variable_def pool",
-                                      sizeof (struct variable_def), 256);
       preserved_values.create (256);
-      global_get_addr_cache = pointer_map_create ();
+      global_get_addr_cache = new hash_map<rtx, rtx>;
     }
   else
     {
       scratch_regs = NULL;
-      valvar_pool = NULL;
       global_get_addr_cache = NULL;
     }
 
@@ -9892,7 +9959,8 @@ vt_initialize (void)
       val = cselib_lookup_from_insn (reg, GET_MODE (reg), 1,
                                     VOIDmode, get_insns ());
       preserve_value (val);
-      cselib_preserve_cfa_base_value (val, REGNO (reg));
+      if (reg != hard_frame_pointer_rtx && fixed_regs[REGNO (reg)])
+       cselib_preserve_cfa_base_value (val, REGNO (reg));
       expr = plus_constant (GET_MODE (stack_pointer_rtx),
                            stack_pointer_rtx, -ofst);
       cselib_add_permanent_equiv (val, expr, get_insns ());
@@ -9998,7 +10066,7 @@ vt_initialize (void)
 
   FOR_EACH_BB_FN (bb, cfun)
     {
-      rtx insn;
+      rtx_insn *insn;
       HOST_WIDE_INT pre, post = 0;
       basic_block first_bb, last_bb;
 
@@ -10134,7 +10202,7 @@ static void
 delete_debug_insns (void)
 {
   basic_block bb;
-  rtx insn, next;
+  rtx_insn *insn, *next;
 
   if (!MAY_HAVE_DEBUG_INSNS)
     return;
@@ -10198,22 +10266,22 @@ vt_finalize (void)
        }
     }
   free_aux_for_blocks ();
-  empty_shared_hash->htab.dispose ();
-  changed_variables.dispose ();
-  free_alloc_pool (attrs_pool);
-  free_alloc_pool (var_pool);
-  free_alloc_pool (loc_chain_pool);
-  free_alloc_pool (shared_hash_pool);
+  delete empty_shared_hash->htab;
+  empty_shared_hash->htab = NULL;
+  delete changed_variables;
+  changed_variables = NULL;
+  attrs_pool.release ();
+  var_pool.release ();
+  location_chain_pool.release ();
+  shared_hash_pool.release ();
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
       if (global_get_addr_cache)
-       pointer_map_destroy (global_get_addr_cache);
+       delete global_get_addr_cache;
       global_get_addr_cache = NULL;
-      if (loc_exp_dep_pool)
-       free_alloc_pool (loc_exp_dep_pool);
-      loc_exp_dep_pool = NULL;
-      free_alloc_pool (valvar_pool);
+      loc_exp_dep_pool.release ();
+      valvar_pool.release ();
       preserved_values.release ();
       cselib_finish ();
       BITMAP_FREE (scratch_regs);
@@ -10237,7 +10305,10 @@ variable_tracking_main_1 (void)
 {
   bool success;
 
-  if (flag_var_tracking_assignments < 0)
+  if (flag_var_tracking_assignments < 0
+      /* Var-tracking right now assumes the IR doesn't contain
+        any pseudos at this point.  */
+      || targetm.no_register_allocation)
     {
       delete_debug_insns ();
       return 0;
@@ -10311,14 +10382,6 @@ variable_tracking_main (void)
   return ret;
 }
 \f
-static bool
-gate_handle_var_tracking (void)
-{
-  return (flag_var_tracking && !targetm.delay_vartrack);
-}
-
-
-
 namespace {
 
 const pass_data pass_data_variable_tracking =
@@ -10326,14 +10389,12 @@ const pass_data pass_data_variable_tracking =
   RTL_PASS, /* type */
   "vartrack", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_VAR_TRACKING, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  ( TODO_verify_rtl_sharing | TODO_verify_flow ), /* todo_flags_finish */
+  0, /* todo_flags_finish */
 };
 
 class pass_variable_tracking : public rtl_opt_pass
@@ -10344,8 +10405,15 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_handle_var_tracking (); }
-  unsigned int execute () { return variable_tracking_main (); }
+  virtual bool gate (function *)
+    {
+      return (flag_var_tracking && !targetm.delay_vartrack);
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return variable_tracking_main ();
+    }
 
 }; // class pass_variable_tracking
 
This page took 0.179956 seconds and 5 git commands to generate.