[PATCH 6/6] Use a linked list for insn defs and uses

Richard Sandiford rdsandiford@googlemail.com
Sat Jun 14 19:53:00 GMT 2014


This is the main change, which is hard to break down much further.

Most of this is pretty mechanical.  Some of it is reindentation,
since it's no longer meaningful (if it was before) to test the
defs or artificial_defs against null to see whether a structure
had been initialised.  Also, df_ref_change_reg_with_loc_1 would
choose the wrong reference array for definitions.

Richard


gcc/
	* df.h (df_mw_hardreg, df_base_ref): Add a link pointer.
	(df_insn_info): Turn defs, uses, eq_uses and mw_hardregs into linked
	lists.
	(df_scan_bb_info): Likewise artificial_defs and artificial_uses.
	(FOR_EACH_INSN_INFO_DEF, FOR_EACH_INSN_INFO_USE)
	(FOR_EACH_INSN_INFO_EQ_USE, FOR_EACH_INSN_INFO_MW)
	(FOR_EACH_ARTIFICIAL_USE, FOR_EACH_ARTIFICIAL_DEF)
	(df_get_artificial_defs, df_get_artificial_uses)
	(df_single_def, df_single_use): Update accordingly.
	(df_refs_chain_dump): Take the first element in a linked list as
	parameter, rather than a pointer to an array of pointers.
	* df-core.c (df_refs_chain_dump, df_mws_dump): Likewise.
	* df-problems.c (df_rd_bb_local_compute_process_def): Likewise.
	(df_chain_create_bb_process_use): Likewise.
	(df_md_bb_local_compute_process_def): Likewise.
	* fwprop.c (process_defs, process_uses): Likewise.
	(register_active_defs, update_uses): Likewise.
	(forward_propagate_asm): Update for new df_ref linking.
	* df-scan.c (df_scan_free_ref_vec, df_scan_free_mws_vec): Delete.
	(df_null_ref_rec, df_null_mw_rec): Likewise.
	(df_scan_free_internal): Don't free df_ref and df_mw_hardreg lists
	explicitly.
	(df_scan_free_bb_info): Remove check for null artificial_defs.
	(df_install_ref_incremental): Adjust for new df_ref linking.
	Use a single-element insertion rather than a full sort.
	(df_ref_chain_delete_du_chain): Take the first element
	in a linked list as parameter, rather than a pointer to an array of
	pointers.
	(df_ref_chain_delete, df_mw_hardreg_chain_delete): Likewise.
	(df_add_refs_to_table, df_refs_verify, df_mws_verify): Likewise.
	(df_insn_info_delete): Remove check for null defs and call to
	df_scan_free_mws_vec.
	(df_insn_rescan): Initialize df_ref and df_mw_hardreg lists to
	null rather than df_null_*_rec.
	(df_insn_rescan_debug_internal): Likewise, and update null
	checks in the same way.  Remove check for null defs.
	(df_ref_change_reg_with_loc_1): Fix choice of list for defs.
	Move a single element rather doing a full sort.
	(df_mw_hardreg_chain_delete_eq_uses): Adjust for new df_mw_hardreg
	linking.
	(df_notes_rescan): Likewise.  Use a merge rather than a full sort.
	Initialize df_ref and df_mw_hardreg lists to null rather than
	df_null_*_rec.
	(df_ref_compare): Take df_refs as parameter, transferring the
	old interface to...
	(df_ref_ptr_compare): ...this new function.
	(df_sort_and_compress_refs): Update accordingly.
	(df_mw_compare): Take df_mw_hardregs as parameter, transferring the
	old interface to...
	(df_mw_ptr_compare): ...this new function.
	(df_sort_and_compress_mws): Update accordingly.
	(df_install_refs, df_install_mws): Return a linked list rather than
	an array of pointers.
	(df_refs_add_to_chains): Assert that old lists are empty rather
	than freeing them.
	(df_insn_refs_verify): Don't handle null defs speciailly.
	* web.c (union_match_dups): Update for new df_ref linking.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-14 20:16:24.996757215 +0100
+++ gcc/df.h	2014-06-14 20:16:25.448761158 +0100
@@ -339,6 +339,7 @@ struct dataflow
    REG_UNUSED notes.  */
 struct df_mw_hardreg
 {
+  df_mw_hardreg *next;		/* Next entry for this instruction.  */
   rtx mw_reg;                   /* The multiword hardreg.  */
   /* These two bitfields are intentionally oversized, in the hope that
      accesses to 16-bit fields will usually be quicker.  */
@@ -365,6 +366,7 @@ struct df_base_ref
   int flags : 16;		/* Various df_ref_flags.  */
   unsigned int regno;		/* The register number referenced.  */
   rtx reg;			/* The register referenced.  */
+  union df_ref_d *next_loc;	/* Next ref for same insn or bb.  */
   struct df_link *chain;	/* Head of def-use, use-def.  */
   /* Pointer to the insn info of the containing instruction.  FIXME!
      Currently this is NULL for artificial refs but this will be used
@@ -420,11 +422,11 @@ typedef union df_ref_d *df_ref;
 struct df_insn_info
 {
   rtx insn;                     /* The insn this info comes from.  */
-  df_ref *defs;	                /* Head of insn-def chain.  */
-  df_ref *uses;	                /* Head of insn-use chain.  */
+  df_ref defs;	                /* Head of insn-def chain.  */
+  df_ref uses;	                /* Head of insn-use chain.  */
   /* Head of insn-use chain for uses in REG_EQUAL/EQUIV notes.  */
-  df_ref *eq_uses;
-  struct df_mw_hardreg **mw_hardregs;
+  df_ref eq_uses;
+  struct df_mw_hardreg *mw_hardregs;
   /* The logical uid of the insn in the basic block.  This is valid
      after any call to df_analyze but may rot after insns are added,
      deleted or moved. */
@@ -755,20 +757,16 @@ #define DF_INSN_UID_EQ_USES(INSN) (DF_IN
 #define DF_INSN_UID_MWS(INSN) (DF_INSN_UID_GET (INSN)->mw_hardregs)
 
 #define FOR_EACH_INSN_INFO_DEF(ITER, INSN) \
-  for (df_ref *ITER##_ = DF_INSN_INFO_DEFS (INSN); (ITER = *ITER##_); \
-       ++ITER##_)
+  for (ITER = DF_INSN_INFO_DEFS (INSN); ITER; ITER = ITER->base.next_loc)
 
 #define FOR_EACH_INSN_INFO_USE(ITER, INSN) \
-  for (df_ref *ITER##_ = DF_INSN_INFO_USES (INSN); (ITER = *ITER##_); \
-       ++ITER##_)
+  for (ITER = DF_INSN_INFO_USES (INSN); ITER; ITER = ITER->base.next_loc)
 
 #define FOR_EACH_INSN_INFO_EQ_USE(ITER, INSN) \
-  for (df_ref *ITER##_ = DF_INSN_INFO_EQ_USES (INSN); (ITER = *ITER##_); \
-       ++ITER##_)
+  for (ITER = DF_INSN_INFO_EQ_USES (INSN); ITER; ITER = ITER->base.next_loc)
 
 #define FOR_EACH_INSN_INFO_MW(ITER, INSN) \
-  for (df_mw_hardreg **ITER##_ = DF_INSN_INFO_MWS (INSN); (ITER = *ITER##_); \
-       ++ITER##_)
+  for (ITER = DF_INSN_INFO_MWS (INSN); ITER; ITER = ITER->next)
 
 #define FOR_EACH_INSN_DEF(ITER, INSN) \
   FOR_EACH_INSN_INFO_DEF(ITER, DF_INSN_INFO_GET (INSN))
@@ -780,12 +778,12 @@ #define FOR_EACH_INSN_EQ_USE(ITER, INSN)
   FOR_EACH_INSN_INFO_EQ_USE(ITER, DF_INSN_INFO_GET (INSN))
 
 #define FOR_EACH_ARTIFICIAL_USE(ITER, BB_INDEX) \
-  for (df_ref *ITER##_ = df_get_artificial_uses (BB_INDEX); \
-       (ITER = *ITER##_); ++ITER##_)
+  for (ITER = df_get_artificial_uses (BB_INDEX); ITER; \
+       ITER = ITER->base.next_loc)
 
 #define FOR_EACH_ARTIFICIAL_DEF(ITER, BB_INDEX) \
-  for (df_ref *ITER##_ = df_get_artificial_defs (BB_INDEX); \
-       (ITER = *ITER##_); ++ITER##_)
+  for (ITER = df_get_artificial_defs (BB_INDEX); ITER; \
+       ITER = ITER->base.next_loc)
 
 /* An obstack for bitmap not related to specific dataflow problems.
    This obstack should e.g. be used for bitmaps with a short life time
@@ -806,13 +804,13 @@ struct df_scan_bb_info
 
      Blocks that are the targets of non-local goto's have the hard
      frame pointer defined at the top of the block.  */
-  df_ref *artificial_defs;
+  df_ref artificial_defs;
 
   /* Blocks that are targets of exception edges may have some
      artificial uses.  These are logically at the top of the block.
 
      Most blocks have artificial uses at the bottom of the block.  */
-  df_ref *artificial_uses;
+  df_ref artificial_uses;
 };
 
 
@@ -967,7 +965,7 @@ extern void df_dump_top (basic_block, FI
 extern void df_dump_bottom (basic_block, FILE *);
 extern void df_dump_insn_top (const_rtx, FILE *);
 extern void df_dump_insn_bottom (const_rtx, FILE *);
-extern void df_refs_chain_dump (df_ref *, bool, FILE *);
+extern void df_refs_chain_dump (df_ref, bool, FILE *);
 extern void df_regs_chain_dump (df_ref,  FILE *);
 extern void df_insn_debug (rtx, bool, FILE *);
 extern void df_insn_debug_regno (rtx, FILE *);
@@ -1147,7 +1145,7 @@ df_get_live_in (basic_block bb)
 /* Get basic block info.  */
 /* Get the artificial defs for a basic block.  */
 
-static inline df_ref *
+static inline df_ref
 df_get_artificial_defs (unsigned int bb_index)
 {
   return df_scan_get_bb_info (bb_index)->artificial_defs;
@@ -1156,7 +1154,7 @@ df_get_artificial_defs (unsigned int bb_
 
 /* Get the artificial uses for a basic block.  */
 
-static inline df_ref *
+static inline df_ref
 df_get_artificial_uses (unsigned int bb_index)
 {
   return df_scan_get_bb_info (bb_index)->artificial_uses;
@@ -1168,8 +1166,8 @@ df_get_artificial_uses (unsigned int bb_
 static inline df_ref
 df_single_def (const df_insn_info *info)
 {
-  df_ref *defs = DF_INSN_INFO_DEFS (info);
-  return defs[0] && !defs[1] ? defs[0] : NULL;
+  df_ref defs = DF_INSN_INFO_DEFS (info);
+  return defs && !defs->base.next_loc ? defs : NULL;
 }
 
 /* If INSN uses exactly one register, return the associated reference,
@@ -1178,8 +1176,8 @@ df_single_def (const df_insn_info *info)
 static inline df_ref
 df_single_use (const df_insn_info *info)
 {
-  df_ref *uses = DF_INSN_INFO_USES (info);
-  return uses[0] && !uses[1] ? uses[0] : NULL;
+  df_ref uses = DF_INSN_INFO_USES (info);
+  return uses && !uses->base.next_loc ? uses : NULL;
 }
 
 /* web */
Index: gcc/df-core.c
===================================================================
--- gcc/df-core.c	2014-06-14 20:08:33.448584144 +0100
+++ gcc/df-core.c	2014-06-14 20:16:25.450761175 +0100
@@ -2319,16 +2319,14 @@ df_ref_dump (df_ref ref, FILE *file)
 }
 
 void
-df_refs_chain_dump (df_ref *ref_rec, bool follow_chain, FILE *file)
+df_refs_chain_dump (df_ref ref, bool follow_chain, FILE *file)
 {
   fprintf (file, "{ ");
-  while (*ref_rec)
+  for (; ref; ref = ref->base.next_loc)
     {
-      df_ref ref = *ref_rec;
       df_ref_dump (ref, file);
       if (follow_chain)
 	df_chain_dump (DF_REF_CHAIN (ref), file);
-      ref_rec++;
     }
   fprintf (file, "}");
 }
@@ -2350,15 +2348,12 @@ df_regs_chain_dump (df_ref ref,  FILE *f
 
 
 static void
-df_mws_dump (struct df_mw_hardreg **mws, FILE *file)
+df_mws_dump (struct df_mw_hardreg *mws, FILE *file)
 {
-  while (*mws)
-    {
-      fprintf (file, "mw %c r[%d..%d]\n",
-	       (DF_MWS_REG_DEF_P (*mws)) ? 'd' : 'u',
-	       (*mws)->start_regno, (*mws)->end_regno);
-      mws++;
-    }
+  for (; mws; mws = mws->next)
+    fprintf (file, "mw %c r[%d..%d]\n",
+	     DF_MWS_REG_DEF_P (mws) ? 'd' : 'u',
+	     mws->start_regno, mws->end_regno);
 }
 
 
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2014-06-14 20:09:37.811177069 +0100
+++ gcc/df-problems.c	2014-06-14 20:16:25.449761166 +0100
@@ -291,12 +291,11 @@ df_rd_simulate_one_insn (basic_block bb
 
 static void
 df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info,
-				    df_ref *def_rec,
+				    df_ref def,
 				    int top_flag)
 {
-  while (*def_rec)
+  for (; def; def = def->base.next_loc)
     {
-      df_ref def = *def_rec;
       if (top_flag == (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
 	{
 	  unsigned int regno = DF_REF_REGNO (def);
@@ -339,7 +338,6 @@ df_rd_bb_local_compute_process_def (stru
 		}
 	    }
 	}
-      def_rec++;
     }
 }
 
@@ -2022,15 +2020,14 @@ df_chain_reset (bitmap blocks_to_clear A
 
 static void
 df_chain_create_bb_process_use (bitmap local_rd,
-				df_ref *use_rec,
+				df_ref use,
 				int top_flag)
 {
   bitmap_iterator bi;
   unsigned int def_index;
 
-  while (*use_rec)
+  for (; use; use = use->base.next_loc)
     {
-      df_ref use = *use_rec;
       unsigned int uregno = DF_REF_REGNO (use);
       if ((!(df->changeable_flags & DF_NO_HARD_REGS))
 	  || (uregno >= FIRST_PSEUDO_REGISTER))
@@ -2059,8 +2056,6 @@ df_chain_create_bb_process_use (bitmap l
 		}
 	    }
 	}
-
-      use_rec++;
     }
 }
 
@@ -4077,13 +4072,12 @@ df_md_simulate_one_insn (basic_block bb
 
 static void
 df_md_bb_local_compute_process_def (struct df_md_bb_info *bb_info,
-                                    df_ref *def_rec,
+                                    df_ref def,
                                     int top_flag)
 {
-  df_ref def;
   bitmap_clear (&seen_in_insn);
 
-  while ((def = *def_rec++) != NULL)
+  for (; def; def = def->base.next_loc)
     {
       unsigned int dregno = DF_REF_REGNO (def);
       if (((!(df->changeable_flags & DF_NO_HARD_REGS))
Index: gcc/fwprop.c
===================================================================
--- gcc/fwprop.c	2014-06-14 20:08:33.442584088 +0100
+++ gcc/fwprop.c	2014-06-14 20:16:25.449761166 +0100
@@ -146,10 +146,9 @@ #define DF_MD_GEN_FLAGS \
 	(DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER)
 
 static void
-process_defs (df_ref *def_rec, int top_flag)
+process_defs (df_ref def, int top_flag)
 {
-  df_ref def;
-  while ((def = *def_rec++) != NULL)
+  for (; def; def = def->base.next_loc)
     {
       df_ref curr_def = reg_defs[DF_REF_REGNO (def)];
       unsigned int dregno;
@@ -191,10 +190,9 @@ process_defs (df_ref *def_rec, int top_f
    is an artificial use vector.  */
 
 static void
-process_uses (df_ref *use_rec, int top_flag)
+process_uses (df_ref use, int top_flag)
 {
-  df_ref use;
-  while ((use = *use_rec++) != NULL)
+  for (; use; use = use->base.next_loc)
     if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == top_flag)
       {
         unsigned int uregno = DF_REF_REGNO (use);
@@ -849,11 +847,10 @@ all_uses_available_at (rtx def_insn, rtx
    too, for checking purposes.  */
 
 static void
-register_active_defs (df_ref *use_rec)
+register_active_defs (df_ref use)
 {
-  while (*use_rec)
+  for (; use; use = use->base.next_loc)
     {
-      df_ref use = *use_rec++;
       df_ref def = get_def_for_use (use);
       int regno = DF_REF_REGNO (use);
 
@@ -887,11 +884,10 @@ update_df_init (rtx def_insn, rtx insn)
    in the ACTIVE_DEFS array to match pseudos to their def. */
 
 static inline void
-update_uses (df_ref *use_rec)
+update_uses (df_ref use)
 {
-  while (*use_rec)
+  for (; use; use = use->base.next_loc)
     {
-      df_ref use = *use_rec++;
       int regno = DF_REF_REGNO (use);
 
       /* Set up the use-def chain.  */
@@ -1135,7 +1131,7 @@ forward_propagate_asm (df_ref use, rtx d
 {
   rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc;
   int speed_p, i;
-  df_ref *use_vec;
+  df_ref uses;
 
   gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0);
 
@@ -1144,8 +1140,8 @@ forward_propagate_asm (df_ref use, rtx d
 
   /* In __asm don't replace if src might need more registers than
      reg, as that could increase register pressure on the __asm.  */
-  use_vec = DF_INSN_USES (def_insn);
-  if (use_vec[0] && use_vec[1])
+  uses = DF_INSN_USES (def_insn);
+  if (uses && uses->base.next_loc)
     return false;
 
   update_df_init (def_insn, use_insn);
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2014-06-14 20:16:24.996757215 +0100
+++ gcc/df-scan.c	2014-06-14 20:19:41.889474415 +0100
@@ -62,21 +62,6 @@ #define HAVE_sibcall_epilogue 0
 #define EPILOGUE_USES(REGNO)  0
 #endif
 
-/* The following two macros free the vecs that hold either the refs or
-   the mw refs.  They are a little tricky because the vec has 0
-   elements is special and is not to be freed.  */
-#define df_scan_free_ref_vec(V) \
-  do { \
-    if (V && *V) \
-      free (V);  \
-  } while (0)
-
-#define df_scan_free_mws_vec(V) \
-  do { \
-    if (V && *V) \
-      free (V);  \
-  } while (0)
-
 /* The set of hard registers in eliminables[i].from. */
 
 static HARD_REG_SET elim_reg_set;
@@ -92,9 +77,6 @@ struct df_collection_rec
   auto_vec<df_mw_hardreg_ptr, 32> mw_vec;
 };
 
-static df_ref df_null_ref_rec[1];
-static struct df_mw_hardreg * df_null_mw_rec[1];
-
 static void df_ref_record (enum df_ref_class, struct df_collection_rec *,
 			   rtx, rtx *,
 			   basic_block, struct df_insn_info *,
@@ -123,8 +105,8 @@ static void df_record_exit_block_uses (b
 static void df_get_exit_block_use_set (bitmap);
 static void df_get_entry_block_def_set (bitmap);
 static void df_grow_ref_info (struct df_ref_info *, unsigned int);
-static void df_ref_chain_delete_du_chain (df_ref *);
-static void df_ref_chain_delete (df_ref *);
+static void df_ref_chain_delete_du_chain (df_ref);
+static void df_ref_chain_delete (df_ref);
 
 static void df_refs_add_to_chains (struct df_collection_rec *,
 				   basic_block, rtx, unsigned int);
@@ -135,8 +117,10 @@ static void df_exit_block_uses_collect (
 static void df_install_ref (df_ref, struct df_reg_info *,
 			    struct df_ref_info *, bool);
 
-static int df_ref_compare (const void *, const void *);
-static int df_mw_compare (const void *, const void *);
+static int df_ref_compare (df_ref, df_ref);
+static int df_ref_ptr_compare (const void *, const void *);
+static int df_mw_compare (const df_mw_hardreg *, const df_mw_hardreg *);
+static int df_mw_ptr_compare (const void *, const void *);
 
 static void df_insn_info_delete (unsigned int);
 
@@ -189,36 +173,6 @@ df_scan_free_internal (void)
 {
   struct df_scan_problem_data *problem_data
     = (struct df_scan_problem_data *) df_scan->problem_data;
-  unsigned int i;
-  basic_block bb;
-
-  /* The vectors that hold the refs are not pool allocated because
-     they come in many sizes.  This makes them impossible to delete
-     all at once.  */
-  for (i = 0; i < DF_INSN_SIZE (); i++)
-    {
-      struct df_insn_info *insn_info = DF_INSN_UID_GET (i);
-      /* Skip the insns that have no insn_info or have been
-	 deleted.  */
-      if (insn_info)
-	{
-	  df_scan_free_ref_vec (insn_info->defs);
-	  df_scan_free_ref_vec (insn_info->uses);
-	  df_scan_free_ref_vec (insn_info->eq_uses);
-	  df_scan_free_mws_vec (insn_info->mw_hardregs);
-	}
-    }
-
-  FOR_ALL_BB_FN (bb, cfun)
-    {
-      unsigned int bb_index = bb->index;
-      struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb_index);
-      if (bb_info)
-	{
-	  df_scan_free_ref_vec (bb_info->artificial_defs);
-	  df_scan_free_ref_vec (bb_info->artificial_uses);
-	}
-    }
 
   free (df->def_info.refs);
   free (df->def_info.begin);
@@ -275,31 +229,22 @@ df_scan_free_bb_info (basic_block bb, vo
 {
   struct df_scan_bb_info *bb_info = (struct df_scan_bb_info *) vbb_info;
   unsigned int bb_index = bb->index;
+  rtx insn;
 
-  /* See if bb_info is initialized.  */
-  if (bb_info->artificial_defs)
-    {
-      rtx insn;
-      FOR_BB_INSNS (bb, insn)
-	{
-	  if (INSN_P (insn))
-	    df_insn_info_delete (INSN_UID (insn));
-	}
+  FOR_BB_INSNS (bb, insn)
+    if (INSN_P (insn))
+      df_insn_info_delete (INSN_UID (insn));
 
-      if (bb_index < df_scan->block_info_size)
-	bb_info = df_scan_get_bb_info (bb_index);
+  if (bb_index < df_scan->block_info_size)
+    bb_info = df_scan_get_bb_info (bb_index);
 
-      /* Get rid of any artificial uses or defs.  */
-      if (bb_info->artificial_defs)
-	{
-	  df_ref_chain_delete_du_chain (bb_info->artificial_defs);
-	  df_ref_chain_delete_du_chain (bb_info->artificial_uses);
-	  df_ref_chain_delete (bb_info->artificial_defs);
-	  df_ref_chain_delete (bb_info->artificial_uses);
-	  bb_info->artificial_defs = NULL;
-	  bb_info->artificial_uses = NULL;
-	}
-    }
+  /* Get rid of any artificial uses or defs.  */
+  df_ref_chain_delete_du_chain (bb_info->artificial_defs);
+  df_ref_chain_delete_du_chain (bb_info->artificial_uses);
+  df_ref_chain_delete (bb_info->artificial_defs);
+  df_ref_chain_delete (bb_info->artificial_uses);
+  bb_info->artificial_defs = NULL;
+  bb_info->artificial_uses = NULL;
 }
 
 
@@ -695,9 +640,7 @@ df_install_ref_incremental (df_ref ref)
 {
   struct df_reg_info **reg_info;
   struct df_ref_info *ref_info;
-  df_ref *ref_rec;
-  df_ref **ref_rec_ptr;
-  unsigned int count = 0;
+  df_ref *ref_ptr;
   bool add_to_table;
 
   rtx insn = DF_REF_INSN (ref);
@@ -707,14 +650,14 @@ df_install_ref_incremental (df_ref ref)
     {
       reg_info = df->def_regs;
       ref_info = &df->def_info;
-      ref_rec_ptr = &DF_INSN_DEFS (insn);
+      ref_ptr = &DF_INSN_DEFS (insn);
       add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE;
     }
   else if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE)
     {
       reg_info = df->eq_use_regs;
       ref_info = &df->use_info;
-      ref_rec_ptr = &DF_INSN_EQ_USES (insn);
+      ref_ptr = &DF_INSN_EQ_USES (insn);
       switch (ref_info->ref_order)
 	{
 	case DF_REF_ORDER_UNORDERED_WITH_NOTES:
@@ -731,7 +674,7 @@ df_install_ref_incremental (df_ref ref)
     {
       reg_info = df->use_regs;
       ref_info = &df->use_info;
-      ref_rec_ptr = &DF_INSN_USES (insn);
+      ref_ptr = &DF_INSN_USES (insn);
       add_to_table = ref_info->ref_order != DF_REF_ORDER_NO_TABLE;
     }
 
@@ -754,29 +697,11 @@ df_install_ref_incremental (df_ref ref)
 	break;
       }
 
-  ref_rec = *ref_rec_ptr;
-  while (*ref_rec)
-    {
-      count++;
-      ref_rec++;
-    }
+  while (*ref_ptr && df_ref_compare (*ref_ptr, ref) < 0)
+    ref_ptr = &(*ref_ptr)->base.next_loc;
 
-  ref_rec = *ref_rec_ptr;
-  if (count)
-    {
-      ref_rec = XRESIZEVEC (df_ref, ref_rec, count+2);
-      *ref_rec_ptr = ref_rec;
-      ref_rec[count] = ref;
-      ref_rec[count+1] = NULL;
-      qsort (ref_rec, count + 1, sizeof (df_ref), df_ref_compare);
-    }
-  else
-    {
-      df_ref *ref_rec = XNEWVEC (df_ref, 2);
-      ref_rec[0] = ref;
-      ref_rec[1] = NULL;
-      *ref_rec_ptr = ref_rec;
-    }
+  ref->base.next_loc = *ref_ptr;
+  *ref_ptr = ref;
 
 #if 0
   if (dump_file)
@@ -930,55 +855,43 @@ df_insn_create_insn_record (rtx insn)
 /* Delete all du chain (DF_REF_CHAIN()) of all refs in the ref chain.  */
 
 static void
-df_ref_chain_delete_du_chain (df_ref *ref_rec)
+df_ref_chain_delete_du_chain (df_ref ref)
 {
-  while (*ref_rec)
-    {
-      df_ref ref = *ref_rec;
-      /* CHAIN is allocated by DF_CHAIN. So make sure to
-         pass df_scan instance for the problem.  */
-      if (DF_REF_CHAIN (ref))
-        df_chain_unlink (ref);
-      ref_rec++;
-    }
+  for (; ref; ref = ref->base.next_loc)
+    /* CHAIN is allocated by DF_CHAIN. So make sure to
+       pass df_scan instance for the problem.  */
+    if (DF_REF_CHAIN (ref))
+      df_chain_unlink (ref);
 }
 
 
 /* Delete all refs in the ref chain.  */
 
 static void
-df_ref_chain_delete (df_ref *ref_rec)
+df_ref_chain_delete (df_ref ref)
 {
-  df_ref *start = ref_rec;
-  while (*ref_rec)
+  df_ref next;
+  for (; ref; ref = next)
     {
-      df_reg_chain_unlink (*ref_rec);
-      ref_rec++;
+      next = ref->base.next_loc;
+      df_reg_chain_unlink (ref);
     }
-
-  /* If the list is empty, it has a special shared element that is not
-     to be deleted.  */
-  if (*start)
-    free (start);
 }
 
 
 /* Delete the hardreg chain.  */
 
 static void
-df_mw_hardreg_chain_delete (struct df_mw_hardreg **hardregs)
+df_mw_hardreg_chain_delete (struct df_mw_hardreg *hardregs)
 {
-  struct df_scan_problem_data *problem_data;
-
-  if (!hardregs)
-    return;
-
-  problem_data = (struct df_scan_problem_data *) df_scan->problem_data;
+  struct df_scan_problem_data *problem_data
+    = (struct df_scan_problem_data *) df_scan->problem_data;
+  df_mw_hardreg *next;
 
-  while (*hardregs)
+  for (; hardregs; hardregs = next)
     {
-      pool_free (problem_data->mw_reg_pool, *hardregs);
-      hardregs++;
+      next = hardregs->next;
+      pool_free (problem_data->mw_reg_pool, hardregs);
     }
 }
 
@@ -1006,22 +919,19 @@ df_insn_info_delete (unsigned int uid)
 	 to notes.  How clever.  So we cannot just check if it is a
 	 valid insn before short circuiting this code, we need to see
 	 if we actually initialized it.  */
-      if (insn_info->defs)
+      df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
+
+      if (df_chain)
 	{
-	  df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
+	  df_ref_chain_delete_du_chain (insn_info->defs);
+	  df_ref_chain_delete_du_chain (insn_info->uses);
+	  df_ref_chain_delete_du_chain (insn_info->eq_uses);
+	}
 
-	  if (df_chain)
-	    {
-	      df_ref_chain_delete_du_chain (insn_info->defs);
-	      df_ref_chain_delete_du_chain (insn_info->uses);
-	      df_ref_chain_delete_du_chain (insn_info->eq_uses);
-	    }
+      df_ref_chain_delete (insn_info->defs);
+      df_ref_chain_delete (insn_info->uses);
+      df_ref_chain_delete (insn_info->eq_uses);
 
-	  df_ref_chain_delete (insn_info->defs);
-	  df_ref_chain_delete (insn_info->uses);
-	  df_ref_chain_delete (insn_info->eq_uses);
-	  df_scan_free_mws_vec (insn_info->mw_hardregs);
-	}
       pool_free (problem_data->insn_pool, insn_info);
       DF_INSN_UID_SET (uid, NULL);
     }
@@ -1149,10 +1059,10 @@ df_insn_rescan (rtx insn)
       if (!insn_info)
 	{
 	  insn_info = df_insn_create_insn_record (insn);
-	  insn_info->defs = df_null_ref_rec;
-	  insn_info->uses = df_null_ref_rec;
-	  insn_info->eq_uses = df_null_ref_rec;
-	  insn_info->mw_hardregs = df_null_mw_rec;
+	  insn_info->defs = 0;
+	  insn_info->uses = 0;
+	  insn_info->eq_uses = 0;
+	  insn_info->mw_hardregs = 0;
 	}
       if (dump_file)
 	fprintf (dump_file, "deferring rescan insn with uid = %d.\n", uid);
@@ -1229,13 +1139,10 @@ df_insn_rescan_debug_internal (rtx insn)
   bitmap_clear_bit (&df->insns_to_rescan, uid);
   bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
 
-  if (!insn_info->defs)
-    return false;
-
-  if (insn_info->defs == df_null_ref_rec
-      && insn_info->uses == df_null_ref_rec
-      && insn_info->eq_uses == df_null_ref_rec
-      && insn_info->mw_hardregs == df_null_mw_rec)
+  if (insn_info->defs == 0
+      && insn_info->uses == 0
+      && insn_info->eq_uses == 0
+      && insn_info->mw_hardregs == 0)
     return false;
 
   df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
@@ -1250,12 +1157,11 @@ df_insn_rescan_debug_internal (rtx insn)
   df_ref_chain_delete (insn_info->defs);
   df_ref_chain_delete (insn_info->uses);
   df_ref_chain_delete (insn_info->eq_uses);
-  df_scan_free_mws_vec (insn_info->mw_hardregs);
 
-  insn_info->defs = df_null_ref_rec;
-  insn_info->uses = df_null_ref_rec;
-  insn_info->eq_uses = df_null_ref_rec;
-  insn_info->mw_hardregs = df_null_mw_rec;
+  insn_info->defs = 0;
+  insn_info->uses = 0;
+  insn_info->eq_uses = 0;
+  insn_info->mw_hardregs = 0;
 
   return true;
 }
@@ -1682,19 +1588,15 @@ df_reorganize_refs_by_reg (struct df_ref
 static unsigned int
 df_add_refs_to_table (unsigned int offset,
 		      struct df_ref_info *ref_info,
-		      df_ref *ref_vec)
+		      df_ref ref)
 {
-  while (*ref_vec)
-    {
-      df_ref ref = *ref_vec;
-      if ((!(df->changeable_flags & DF_NO_HARD_REGS))
-	  || (DF_REF_REGNO (ref) >= FIRST_PSEUDO_REGISTER))
-	{
-	  ref_info->refs[offset] = ref;
-	  DF_REF_ID (*ref_vec) = offset++;
-	}
-      ref_vec++;
-    }
+  for (; ref; ref = ref->base.next_loc)
+    if (!(df->changeable_flags & DF_NO_HARD_REGS)
+	|| (DF_REF_REGNO (ref) >= FIRST_PSEUDO_REGISTER))
+      {
+	ref_info->refs[offset] = ref;
+	DF_REF_ID (ref) = offset++;
+      }
   return offset;
 }
 
@@ -1921,9 +1823,8 @@ df_ref_change_reg_with_loc_1 (struct df_
 	{
 	  df_ref next_ref = DF_REF_NEXT_REG (the_ref);
 	  df_ref prev_ref = DF_REF_PREV_REG (the_ref);
-	  df_ref *ref_vec, *ref_vec_t;
+	  df_ref *ref_ptr;
 	  struct df_insn_info *insn_info = DF_REF_INSN_INFO (the_ref);
-	  unsigned int count = 0;
 
 	  DF_REF_REGNO (the_ref) = new_regno;
 	  DF_REF_REG (the_ref) = regno_reg_rtx[new_regno];
@@ -1950,23 +1851,42 @@ df_ref_change_reg_with_loc_1 (struct df_
 	  /* Need to sort the record again that the ref was in because
 	     the regno is a sorting key.  First, find the right
 	     record.  */
-	  if (DF_REF_FLAGS (the_ref) & DF_REF_IN_NOTE)
-	    ref_vec = insn_info->eq_uses;
+	  if (DF_REF_REG_DEF_P (the_ref))
+	    ref_ptr = &insn_info->defs;
+	  else if (DF_REF_FLAGS (the_ref) & DF_REF_IN_NOTE)
+	    ref_ptr = &insn_info->eq_uses;
 	  else
-	    ref_vec = insn_info->uses;
+	    ref_ptr = &insn_info->uses;
 	  if (dump_file)
 	    fprintf (dump_file, "changing reg in insn %d\n",
 		     DF_REF_INSN_UID (the_ref));
 
-	  ref_vec_t = ref_vec;
-
-	  /* Find the length.  */
-	  while (*ref_vec_t)
+	  /* Stop if we find the current reference or where the reference
+	     needs to be.  */
+	  while (*ref_ptr != the_ref && df_ref_compare (*ref_ptr, the_ref) < 0)
+	    ref_ptr = &(*ref_ptr)->base.next_loc;
+	  if (*ref_ptr != the_ref)
 	    {
-	      count++;
-	      ref_vec_t++;
+	      /* The reference needs to be promoted up the list.  */
+	      df_ref next = the_ref->base.next_loc;
+	      the_ref->base.next_loc = *ref_ptr;
+	      *ref_ptr = the_ref;
+	      do
+		ref_ptr = &(*ref_ptr)->base.next_loc;
+	      while (*ref_ptr != the_ref);
+	      *ref_ptr = next;
+	    }
+	  else if (the_ref->base.next_loc
+		   && df_ref_compare (the_ref, the_ref->base.next_loc) > 0)
+	    {
+	      /* The reference needs to be demoted down the list.  */
+	      *ref_ptr = the_ref->base.next_loc;
+	      do
+		ref_ptr = &(*ref_ptr)->base.next_loc;
+	      while (*ref_ptr && df_ref_compare (the_ref, *ref_ptr) > 0);
+	      the_ref->base.next_loc = *ref_ptr;
+	      *ref_ptr = the_ref;
 	    }
-	  qsort (ref_vec, count, sizeof (df_ref ), df_ref_compare);
 
 	  the_ref = next_ref;
 	}
@@ -2000,51 +1920,24 @@ df_ref_change_reg_with_loc (int old_regn
 
 /* Delete the mw_hardregs that point into the eq_notes.  */
 
-static unsigned int
+static void
 df_mw_hardreg_chain_delete_eq_uses (struct df_insn_info *insn_info)
 {
-  struct df_mw_hardreg **mw_vec = insn_info->mw_hardregs;
-  unsigned int deleted = 0;
-  unsigned int count = 0;
+  struct df_mw_hardreg **mw_ptr = &insn_info->mw_hardregs;
   struct df_scan_problem_data *problem_data
     = (struct df_scan_problem_data *) df_scan->problem_data;
 
-  if (!*mw_vec)
-    return 0;
-
-  while (*mw_vec)
+  while (*mw_ptr)
     {
-      if ((*mw_vec)->flags & DF_REF_IN_NOTE)
+      df_mw_hardreg *mw = *mw_ptr;
+      if (mw->flags & DF_REF_IN_NOTE)
 	{
-	  struct df_mw_hardreg **temp_vec = mw_vec;
-
-	  pool_free (problem_data->mw_reg_pool, *mw_vec);
-	  temp_vec = mw_vec;
-	  /* Shove the remaining ones down one to fill the gap.  While
-	     this looks n**2, it is highly unusual to have any mw regs
-	     in eq_notes and the chances of more than one are almost
-	     non existent.  */
-	  while (*temp_vec)
-	    {
-	      *temp_vec = *(temp_vec + 1);
-	      temp_vec++;
-	    }
-	  deleted++;
+	  *mw_ptr = mw->next;
+	  pool_free (problem_data->mw_reg_pool, mw);
 	}
       else
-	{
-	  mw_vec++;
-	  count++;
-	}
-    }
-
-  if (count == 0)
-    {
-      df_scan_free_mws_vec (insn_info->mw_hardregs);
-      insn_info->mw_hardregs = df_null_mw_rec;
-      return 0;
+	mw_ptr = &mw->next;
     }
-  return deleted;
 }
 
 
@@ -2078,10 +1971,10 @@ df_notes_rescan (rtx insn)
       if (!insn_info)
 	{
 	  insn_info = df_insn_create_insn_record (insn);
-	  insn_info->defs = df_null_ref_rec;
-	  insn_info->uses = df_null_ref_rec;
-	  insn_info->eq_uses = df_null_ref_rec;
-	  insn_info->mw_hardregs = df_null_mw_rec;
+	  insn_info->defs = 0;
+	  insn_info->uses = 0;
+	  insn_info->eq_uses = 0;
+	  insn_info->mw_hardregs = 0;
 	}
 
       bitmap_clear_bit (&df->insns_to_delete, uid);
@@ -2100,10 +1993,9 @@ df_notes_rescan (rtx insn)
       basic_block bb = BLOCK_FOR_INSN (insn);
       rtx note;
       struct df_collection_rec collection_rec;
-      unsigned int num_deleted;
-      unsigned int mw_len;
+      unsigned int i;
 
-      num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info);
+      df_mw_hardreg_chain_delete_eq_uses (insn_info);
       df_ref_chain_delete (insn_info->eq_uses);
       insn_info->eq_uses = NULL;
 
@@ -2125,45 +2017,14 @@ df_notes_rescan (rtx insn)
 
       /* Find some place to put any new mw_hardregs.  */
       df_canonize_collection_rec (&collection_rec);
-      mw_len = collection_rec.mw_vec.length ();
-      if (mw_len)
+      struct df_mw_hardreg **mw_ptr = &insn_info->mw_hardregs, *mw;
+      FOR_EACH_VEC_ELT (collection_rec.mw_vec, i, mw)
 	{
-	  unsigned int count = 0;
-	  struct df_mw_hardreg **mw_rec = insn_info->mw_hardregs;
-	  while (*mw_rec)
-	    {
-	      count++;
-	      mw_rec++;
-	    }
-
-	  if (count)
-	    {
-	      /* Append to the end of the existing record after
-		 expanding it if necessary.  */
-	      if (mw_len > num_deleted)
-		{
-		  insn_info->mw_hardregs =
-		    XRESIZEVEC (struct df_mw_hardreg *,
-				insn_info->mw_hardregs,
-				count + 1 + mw_len);
-		}
-	      memcpy (&insn_info->mw_hardregs[count],
-		      collection_rec.mw_vec.address (),
-		      mw_len * sizeof (struct df_mw_hardreg *));
-	      insn_info->mw_hardregs[count + mw_len] = NULL;
-	      qsort (insn_info->mw_hardregs, count + mw_len,
-		     sizeof (struct df_mw_hardreg *), df_mw_compare);
-	    }
-	  else
-	    {
-	      /* No vector there. */
-	      insn_info->mw_hardregs
-		= XNEWVEC (struct df_mw_hardreg*, 1 + mw_len);
-	      memcpy (insn_info->mw_hardregs,
-		      collection_rec.mw_vec.address (),
-		      mw_len * sizeof (struct df_mw_hardreg *));
-	      insn_info->mw_hardregs[mw_len] = NULL;
-	    }
+	  while (*mw_ptr && df_mw_compare (*mw_ptr, mw) < 0)
+	    mw_ptr = &(*mw_ptr)->next;
+	  mw->next = *mw_ptr;
+	  *mw_ptr = mw;
+	  mw_ptr = &mw->next;
 	}
       df_refs_add_to_chains (&collection_rec, bb, insn, copy_eq_uses);
     }
@@ -2222,14 +2083,8 @@ df_ref_equal_p (df_ref ref1, df_ref ref2
    have the same bb.  So these fields are not checked.  */
 
 static int
-df_ref_compare (const void *r1, const void *r2)
+df_ref_compare (df_ref ref1, df_ref ref2)
 {
-  const df_ref ref1 = *(const df_ref *)r1;
-  const df_ref ref2 = *(const df_ref *)r2;
-
-  if (ref1 == ref2)
-    return 0;
-
   if (DF_REF_CLASS (ref1) != DF_REF_CLASS (ref2))
     return (int)DF_REF_CLASS (ref1) - (int)DF_REF_CLASS (ref2);
 
@@ -2264,6 +2119,14 @@ df_ref_compare (const void *r1, const vo
   return (int)DF_REF_ORDER (ref1) - (int)DF_REF_ORDER (ref2);
 }
 
+/* Like df_ref_compare, but compare two df_ref* pointers R1 and R2.  */
+
+static int
+df_ref_ptr_compare (const void *r1, const void *r2)
+{
+  return df_ref_compare (*(const df_ref *) r1, *(const df_ref *) r2);
+}
+
 static void
 df_swap_refs (vec<df_ref, va_heap> *ref_vec, int i, int j)
 {
@@ -2290,7 +2153,7 @@ df_sort_and_compress_refs (vec<df_ref, v
     {
       df_ref r0 = (*ref_vec)[0];
       df_ref r1 = (*ref_vec)[1];
-      if (df_ref_compare (&r0, &r1) > 0)
+      if (df_ref_compare (r0, r1) > 0)
         df_swap_refs (ref_vec, 0, 1);
     }
   else
@@ -2299,7 +2162,7 @@ df_sort_and_compress_refs (vec<df_ref, v
 	{
 	  df_ref r0 = (*ref_vec)[i];
 	  df_ref r1 = (*ref_vec)[i + 1];
-	  if (df_ref_compare (&r0, &r1) >= 0)
+	  if (df_ref_compare (r0, r1) >= 0)
 	    break;
 	}
       /* If the array is already strictly ordered,
@@ -2311,7 +2174,7 @@ df_sort_and_compress_refs (vec<df_ref, v
          of DF_REF_COMPARE.  */
       if (i == count - 1)
         return;
-      ref_vec->qsort (df_ref_compare);
+      ref_vec->qsort (df_ref_ptr_compare);
     }
 
   for (i=0; i<count-dist; i++)
@@ -2354,14 +2217,8 @@ df_mw_equal_p (struct df_mw_hardreg *mw1
 /* Compare MW1 and MW2 for sorting.  */
 
 static int
-df_mw_compare (const void *m1, const void *m2)
+df_mw_compare (const df_mw_hardreg *mw1, const df_mw_hardreg *mw2)
 {
-  const struct df_mw_hardreg *const mw1 = *(const struct df_mw_hardreg *const*)m1;
-  const struct df_mw_hardreg *const mw2 = *(const struct df_mw_hardreg *const*)m2;
-
-  if (mw1 == mw2)
-    return 0;
-
   if (mw1->type != mw2->type)
     return mw1->type - mw2->type;
 
@@ -2380,6 +2237,14 @@ df_mw_compare (const void *m1, const voi
   return 0;
 }
 
+/* Like df_mw_compare, but compare two df_mw_hardreg** pointers R1 and R2.  */
+
+static int
+df_mw_ptr_compare (const void *m1, const void *m2)
+{
+  return df_mw_compare (*(const df_mw_hardreg *const *) m1,
+			*(const df_mw_hardreg *const *) m2);
+}
 
 /* Sort and compress a set of refs.  */
 
@@ -2399,7 +2264,7 @@ df_sort_and_compress_mws (vec<df_mw_hard
     {
       struct df_mw_hardreg *m0 = (*mw_vec)[0];
       struct df_mw_hardreg *m1 = (*mw_vec)[1];
-      if (df_mw_compare (&m0, &m1) > 0)
+      if (df_mw_compare (m0, m1) > 0)
         {
           struct df_mw_hardreg *tmp = (*mw_vec)[0];
 	  (*mw_vec)[0] = (*mw_vec)[1];
@@ -2407,7 +2272,7 @@ df_sort_and_compress_mws (vec<df_mw_hard
         }
     }
   else
-    mw_vec->qsort (df_mw_compare);
+    mw_vec->qsort (df_mw_ptr_compare);
 
   for (i=0; i<count-dist; i++)
     {
@@ -2493,7 +2358,7 @@ df_install_ref (df_ref this_ref,
    eq_uses) and installs the entire group into the insn.  It also adds
    each of these refs into the appropriate chains.  */
 
-static df_ref *
+static df_ref
 df_install_refs (basic_block bb,
 		 const vec<df_ref, va_heap> *old_vec,
 		 struct df_reg_info **reg_info,
@@ -2503,7 +2368,6 @@ df_install_refs (basic_block bb,
   unsigned int count = old_vec->length ();
   if (count)
     {
-      df_ref *new_vec = XNEWVEC (df_ref, count + 1);
       bool add_to_table;
       df_ref this_ref;
       unsigned int ix;
@@ -2533,37 +2397,35 @@ df_install_refs (basic_block bb,
 
       FOR_EACH_VEC_ELT (*old_vec, ix, this_ref)
 	{
-	  new_vec[ix] = this_ref;
+	  this_ref->base.next_loc = (ix + 1 < old_vec->length ()
+				     ? (*old_vec)[ix + 1]
+				     : NULL);
 	  df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)],
 			  ref_info, add_to_table);
 	}
-
-      new_vec[count] = NULL;
-      return new_vec;
+      return (*old_vec)[0];
     }
   else
-    return df_null_ref_rec;
+    return 0;
 }
 
 
 /* This function takes the mws installs the entire group into the
    insn.  */
 
-static struct df_mw_hardreg **
+static struct df_mw_hardreg *
 df_install_mws (const vec<df_mw_hardreg_ptr, va_heap> *old_vec)
 {
   unsigned int count = old_vec->length ();
   if (count)
     {
-      struct df_mw_hardreg **new_vec
-	= XNEWVEC (struct df_mw_hardreg*, count + 1);
-      memcpy (new_vec, old_vec->address (),
-	      sizeof (struct df_mw_hardreg*) * count);
-      new_vec[count] = NULL;
-      return new_vec;
+      for (unsigned int i = 0; i < count - 1; i++)
+	(*old_vec)[i]->next = (*old_vec)[i + 1];
+      (*old_vec)[count - 1]->next = 0;
+      return (*old_vec)[0];
     }
   else
-    return df_null_mw_rec;
+    return 0;
 }
 
 
@@ -2582,7 +2444,7 @@ df_refs_add_to_chains (struct df_collect
 	 chain specially.  */
       if (flags & copy_defs)
 	{
-	  df_scan_free_ref_vec (insn_rec->defs);
+	  gcc_checking_assert (!insn_rec->defs);
 	  insn_rec->defs
 	    = df_install_refs (bb, &collection_rec->def_vec,
 			       df->def_regs,
@@ -2590,7 +2452,7 @@ df_refs_add_to_chains (struct df_collect
 	}
       if (flags & copy_uses)
 	{
-	  df_scan_free_ref_vec (insn_rec->uses);
+	  gcc_checking_assert (!insn_rec->uses);
 	  insn_rec->uses
 	    = df_install_refs (bb, &collection_rec->use_vec,
 			       df->use_regs,
@@ -2598,7 +2460,7 @@ df_refs_add_to_chains (struct df_collect
 	}
       if (flags & copy_eq_uses)
 	{
-	  df_scan_free_ref_vec (insn_rec->eq_uses);
+	  gcc_checking_assert (!insn_rec->eq_uses);
 	  insn_rec->eq_uses
 	    = df_install_refs (bb, &collection_rec->eq_use_vec,
 			       df->eq_use_regs,
@@ -2606,7 +2468,7 @@ df_refs_add_to_chains (struct df_collect
 	}
       if (flags & copy_mw)
 	{
-	  df_scan_free_mws_vec (insn_rec->mw_hardregs);
+	  gcc_checking_assert (!insn_rec->mw_hardregs);
 	  insn_rec->mw_hardregs
 	    = df_install_mws (&collection_rec->mw_vec);
 	}
@@ -2615,12 +2477,12 @@ df_refs_add_to_chains (struct df_collect
     {
       struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index);
 
-      df_scan_free_ref_vec (bb_info->artificial_defs);
+      gcc_checking_assert (!bb_info->artificial_defs);
       bb_info->artificial_defs
 	= df_install_refs (bb, &collection_rec->def_vec,
 			   df->def_regs,
 			   &df->def_info, false);
-      df_scan_free_ref_vec (bb_info->artificial_uses);
+      gcc_checking_assert (!bb_info->artificial_uses);
       bb_info->artificial_uses
 	= df_install_refs (bb, &collection_rec->use_vec,
 			   df->use_regs,
@@ -4194,7 +4056,7 @@ df_reg_chain_verify_unmarked (df_ref ref
 /* Verify that NEW_REC and OLD_REC have exactly the same members. */
 
 static bool
-df_refs_verify (const vec<df_ref, va_heap> *new_rec, df_ref *old_rec,
+df_refs_verify (const vec<df_ref, va_heap> *new_rec, df_ref old_rec,
 		bool abort_if_fail)
 {
   unsigned int ix;
@@ -4202,7 +4064,7 @@ df_refs_verify (const vec<df_ref, va_hea
 
   FOR_EACH_VEC_ELT (*new_rec, ix, new_ref)
     {
-      if (*old_rec == NULL || !df_ref_equal_p (new_ref, *old_rec))
+      if (old_rec == NULL || !df_ref_equal_p (new_ref, old_rec))
 	{
 	  if (abort_if_fail)
 	    gcc_assert (0);
@@ -4214,17 +4076,17 @@ df_refs_verify (const vec<df_ref, va_hea
 	 that is the context, mark this reg as being seem.  */
       if (abort_if_fail)
 	{
-	  gcc_assert (DF_REF_IS_REG_MARKED (*old_rec));
-	  DF_REF_REG_UNMARK (*old_rec);
+	  gcc_assert (DF_REF_IS_REG_MARKED (old_rec));
+	  DF_REF_REG_UNMARK (old_rec);
 	}
 
-      old_rec++;
+      old_rec = old_rec->base.next_loc;
     }
 
   if (abort_if_fail)
-    gcc_assert (*old_rec == NULL);
+    gcc_assert (old_rec == NULL);
   else
-    return *old_rec == NULL;
+    return old_rec == NULL;
   return false;
 }
 
@@ -4233,7 +4095,7 @@ df_refs_verify (const vec<df_ref, va_hea
 
 static bool
 df_mws_verify (const vec<df_mw_hardreg_ptr, va_heap> *new_rec,
-	       struct df_mw_hardreg **old_rec,
+	       struct df_mw_hardreg *old_rec,
 	       bool abort_if_fail)
 {
   unsigned int ix;
@@ -4241,20 +4103,20 @@ df_mws_verify (const vec<df_mw_hardreg_p
 
   FOR_EACH_VEC_ELT (*new_rec, ix, new_reg)
     {
-      if (*old_rec == NULL || !df_mw_equal_p (new_reg, *old_rec))
+      if (old_rec == NULL || !df_mw_equal_p (new_reg, old_rec))
 	{
 	  if (abort_if_fail)
 	    gcc_assert (0);
 	  else
 	    return false;
 	}
-      old_rec++;
+      old_rec = old_rec->next;
     }
 
   if (abort_if_fail)
-    gcc_assert (*old_rec == NULL);
+    gcc_assert (old_rec == NULL);
   else
-    return *old_rec == NULL;
+    return old_rec == NULL;
   return false;
 }
 
@@ -4282,15 +4144,6 @@ df_insn_refs_verify (struct df_collectio
 
   df_insn_refs_collect (collection_rec, bb, insn_info);
 
-  if (!DF_INSN_UID_DEFS (uid))
-    {
-      /* The insn_rec was created but it was never filled out.  */
-      if (abort_if_fail)
-	gcc_assert (0);
-      else
-	return false;
-    }
-
   /* Unfortunately we cannot opt out early if one of these is not
      right because the marks will not get cleared.  */
   ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid),
Index: gcc/web.c
===================================================================
--- gcc/web.c	2014-06-14 20:08:33.448584144 +0100
+++ gcc/web.c	2014-06-14 20:16:25.450761175 +0100
@@ -93,8 +93,8 @@ union_match_dups (rtx insn, struct web_e
 		  bool (*fun) (struct web_entry *, struct web_entry *))
 {
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-  df_ref *use_link = DF_INSN_INFO_USES (insn_info);
-  df_ref *def_link = DF_INSN_INFO_DEFS (insn_info);
+  df_ref use_link = DF_INSN_INFO_USES (insn_info);
+  df_ref def_link = DF_INSN_INFO_DEFS (insn_info);
   struct web_entry *dup_entry;
   int i;
 
@@ -104,18 +104,19 @@ union_match_dups (rtx insn, struct web_e
     {
       int op = recog_data.dup_num[i];
       enum op_type type = recog_data.operand_type[op];
-      df_ref *ref, *dupref;
+      df_ref ref, dupref;
       struct web_entry *entry;
 
-      for (dup_entry = use_entry, dupref = use_link; *dupref; dupref++)
-	if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
+      dup_entry = use_entry;
+      for (dupref = use_link; dupref; dupref = dupref->base.next_loc)
+	if (DF_REF_LOC (dupref) == recog_data.dup_loc[i])
 	  break;
 
-      if (*dupref == NULL && type == OP_INOUT)
+      if (dupref == NULL && type == OP_INOUT)
 	{
-
-	  for (dup_entry = def_entry, dupref = def_link; *dupref; dupref++)
-	    if (DF_REF_LOC (*dupref) == recog_data.dup_loc[i])
+	  dup_entry = def_entry;
+	  for (dupref = def_link; dupref; dupref = dupref->base.next_loc)
+	    if (DF_REF_LOC (dupref) == recog_data.dup_loc[i])
 	      break;
 	}
       /* ??? *DUPREF can still be zero, because when an operand matches
@@ -125,35 +126,36 @@ union_match_dups (rtx insn, struct web_e
          even though it is there.
          Example: i686-pc-linux-gnu gcc.c-torture/compile/950607-1.c
 		  -O3 -fomit-frame-pointer -funroll-loops  */
-      if (*dupref == NULL
-	  || DF_REF_REGNO (*dupref) < FIRST_PSEUDO_REGISTER)
+      if (dupref == NULL
+	  || DF_REF_REGNO (dupref) < FIRST_PSEUDO_REGISTER)
 	continue;
 
       ref = type == OP_IN ? use_link : def_link;
       entry = type == OP_IN ? use_entry : def_entry;
-      for (; *ref; ref++)
+      for (; ref; ref = ref->base.next_loc)
 	{
-	  rtx *l = DF_REF_LOC (*ref);
+	  rtx *l = DF_REF_LOC (ref);
 	  if (l == recog_data.operand_loc[op])
 	    break;
-	  if (l && DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op])
+	  if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op])
 	    break;
 	}
 
-      if (!*ref && type == OP_INOUT)
+      if (!ref && type == OP_INOUT)
 	{
-	  for (ref = use_link, entry = use_entry; *ref; ref++)
+	  entry = use_entry;
+	  for (ref = use_link; ref; ref = ref->base.next_loc)
 	    {
-	      rtx *l = DF_REF_LOC (*ref);
+	      rtx *l = DF_REF_LOC (ref);
 	      if (l == recog_data.operand_loc[op])
 		break;
-	      if (l && DF_REF_REAL_LOC (*ref) == recog_data.operand_loc[op])
+	      if (l && DF_REF_REAL_LOC (ref) == recog_data.operand_loc[op])
 		break;
 	    }
 	}
 
-      gcc_assert (*ref);
-      (*fun) (dup_entry + DF_REF_ID (*dupref), entry + DF_REF_ID (*ref));
+      gcc_assert (ref);
+      (*fun) (dup_entry + DF_REF_ID (dupref), entry + DF_REF_ID (ref));
     }
 }
 



More information about the Gcc-patches mailing list