public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Make df_ref representation more efficient
@ 2014-06-14 19:36 Richard Sandiford
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
                   ` (5 more replies)
  0 siblings, 6 replies; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:36 UTC (permalink / raw)
  To: gcc-patches

Walks of things like DF_REF_INSN_USES were showing up high in the profile
of a fold-const.ii compilation.  These reference lists are represented
as pointers to null-terminated lists of pointers, and since there's
little locality when walking all insns, each loop over the uses or defs
generally has two major cache misses before it can do anything
(or one major cache miss before doing nothing), on top of accessing
the underlying df_insn_info.  Also, for -O0, the overhead of mallocing
lots of small arrays is itself noticeable.

I don't think there's any real need for this representation.  Each
df_ref belongs to exactly one of these null-terminated pointer arrays,
so using a normal linked list would be more efficient memory-wise
(because we'd save on the null terminator and separate malloced memory).

The idea might have been to allow the array to be sorted easily.
That doesn't really apply now though.  We collect the references in a
df_collection_rec and sort them there before populating the df_insn_info.
After that we just insert single elements or merge two sorted lists.
(Both of these are currently done as full qsorts, but don't need to be.)

Using a linked list gives a consistent 2% compile-time improvement for
fold-const.ii -O0 and ~1% for various -O2 compiles I tried.  The df
routines do still show up high on the profile though.

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
@ 2014-06-14 19:43 ` Richard Sandiford
  2014-06-14 19:45   ` [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW Richard Sandiford
                     ` (4 more replies)
  2014-06-14 19:44 ` [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE} Richard Sandiford
                   ` (4 subsequent siblings)
  5 siblings, 5 replies; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:43 UTC (permalink / raw)
  To: gcc-patches

To make the final representation change easier, this patch introduces
macros for iterating over lists of defs, uses and eq_uses.  At the
moment there are three possible keys when accessing df_ref lists:
the insn rtx (DF_INSN_*), the insn uid (DF_INSN_UID_*) and the
df_insn_info (DF_INSN_INFO_*).  I don't think it's worth adding
iterators for uids though.  Any code that's going to the trouble of
caching the uid might as well go the whole hog and cache the underlying
df_insn_info.

After the feedback to the BB iterator patch:

  https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00676.html

I've kept the iterator variable definitions outside the FOR_* macros
rather than make the FOR_* macros define the variables themselves.

Richard


gcc/
	* df.h (DF_INSN_INFO_MWS, FOR_EACH_INSN_INFO_DEF): New macros.
	(FOR_EACH_INSN_INFO_USE, FOR_EACH_INSN_INFO_EQ_USE): Likewise.
	(FOR_EACH_INSN_DEF, FOR_EACH_INSN_USE, FOR_EACH_INSN_EQ_USE): Likewise.
	* auto-inc-dec.c (find_inc, merge_in_block): Use them.
	* combine.c (create_log_links): Likewise.
	* compare-elim.c (find_flags_uses_in_insn): Likewise.
	(try_eliminate_compare): Likewise.
	* cprop.c (make_set_regs_unavailable, mark_oprs_set): Likewise.
	* dce.c (deletable_insn_p, find_call_stack_args): Likewise.
	(remove_reg_equal_equiv_notes_for_defs): Likewise.
	(reset_unmarked_insns_debug_uses, mark_reg_dependencies): Likewise.
	(word_dce_process_block, dce_process_block): Likewise.
	* ddg.c (def_has_ccmode_p): Likewise.
	* df-core.c (df_bb_regno_first_def_find): Likewise.
	(df_bb_regno_last_def_find, df_find_def, df_find_use): Likewise.
	* df-problems.c (df_rd_simulate_one_insn): Likewise.
	(df_lr_bb_local_compute, df_live_bb_local_compute): Likewise.
	(df_chain_remove_problem, df_chain_insn_top_dump): Likewise.
	(df_chain_insn_bottom_dump, df_word_lr_bb_local_compute): Likewise.
	(df_word_lr_simulate_defs, df_word_lr_simulate_uses): Likewise.
	(df_remove_dead_eq_notes, df_note_bb_compute): Likewise.
	(df_simulate_find_defs, df_simulate_find_uses): Likewise.
	(df_simulate_find_noclobber_defs, df_simulate_defs): Likewise.
	(df_simulate_uses, df_md_simulate_one_insn): Likewise.
	* df-scan.c (df_reorganize_refs_by_reg_by_insn): Likewise.
	* fwprop.c (local_ref_killed_between_p): Likewise.
	(all_uses_available_at, free_load_extend): Likewise.
	* gcse.c (update_bb_reg_pressure, calculate_bb_reg_pressure): Likewise.
	* hw-doloop.c (scan_loop): Likewise.
	* ifcvt.c (dead_or_predicable): Likewise.
	* init-regs.c (initialize_uninitialized_regs): Likewise.
	* ira-lives.c (mark_hard_reg_early_clobbers): Likewise.
	(process_bb_node_lives): Likewise.
	* ira.c (compute_regs_asm_clobbered, build_insn_chain): Likewise.
	(find_moveable_pseudos): Likewise.
	* loop-invariant.c (check_dependencies, record_uses): Likewise.
	* recog.c (peep2_find_free_register): Likewise.
	* ree.c (get_defs): Likewise.
	* regstat.c (regstat_bb_compute_ri): Likewise.
	(regstat_bb_compute_calls_crossed): Likewise.
	* sched-deps.c (find_inc, find_mem): Likewise.
	* sel-sched-ir.c (maybe_downgrade_id_to_use): Likewise.
	(maybe_downgrade_id_to_use, setup_id_reg_sets): Likewise.
	* shrink-wrap.c (requires_stack_frame_p): Likewise.
	(prepare_shrink_wrap): Likewise.
	* store-motion.c (compute_store_table, build_store_vectors): Likewise.
	* web.c (union_defs, pass_web::execute): Likewise.
	* config/i386/i386.c (increase_distance, insn_defines_reg): Likewise.
	(insn_uses_reg_mem, ix86_ok_to_clobber_flags): Likewise.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-14 20:08:31.421565177 +0100
+++ gcc/df.h	2014-06-14 20:08:33.442584088 +0100
@@ -736,6 +736,7 @@ #define DF_INSN_INFO_LUID(II) ((II)->lui
 #define DF_INSN_INFO_DEFS(II) ((II)->defs)
 #define DF_INSN_INFO_USES(II) ((II)->uses)
 #define DF_INSN_INFO_EQ_USES(II) ((II)->eq_uses)
+#define DF_INSN_INFO_MWS(II) ((II)->mw_hardregs)
 
 #define DF_INSN_LUID(INSN) (DF_INSN_INFO_LUID (DF_INSN_INFO_GET (INSN)))
 #define DF_INSN_DEFS(INSN) (DF_INSN_INFO_DEFS (DF_INSN_INFO_GET (INSN)))
@@ -753,6 +754,27 @@ #define DF_INSN_UID_USES(INSN) (DF_INSN_
 #define DF_INSN_UID_EQ_USES(INSN) (DF_INSN_UID_GET (INSN)->eq_uses)
 #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##_)
+
+#define FOR_EACH_INSN_INFO_USE(ITER, INSN) \
+  for (df_ref *ITER##_ = DF_INSN_INFO_USES (INSN); (ITER = *ITER##_); \
+       ++ITER##_)
+
+#define FOR_EACH_INSN_INFO_EQ_USE(ITER, INSN) \
+  for (df_ref *ITER##_ = DF_INSN_INFO_EQ_USES (INSN); (ITER = *ITER##_); \
+       ++ITER##_)
+
+#define FOR_EACH_INSN_DEF(ITER, INSN) \
+  FOR_EACH_INSN_INFO_DEF(ITER, DF_INSN_INFO_GET (INSN))
+
+#define FOR_EACH_INSN_USE(ITER, INSN) \
+  FOR_EACH_INSN_INFO_USE(ITER, DF_INSN_INFO_GET (INSN))
+
+#define FOR_EACH_INSN_EQ_USE(ITER, INSN) \
+  FOR_EACH_INSN_INFO_EQ_USE(ITER, DF_INSN_INFO_GET (INSN))
+
 /* An obstack for bitmap not related to specific dataflow problems.
    This obstack should e.g. be used for bitmaps with a short life time
    such as temporary bitmaps.  This obstack is declared in df-core.c.  */
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/auto-inc-dec.c	2014-06-14 20:08:33.433584004 +0100
@@ -969,7 +969,7 @@ find_inc (bool first_try)
   rtx insn;
   basic_block bb = BLOCK_FOR_INSN (mem_insn.insn);
   rtx other_insn;
-  df_ref *def_rec;
+  df_ref def;
 
   /* Make sure this reg appears only once in this insn.  */
   if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
@@ -1013,9 +1013,8 @@ find_inc (bool first_try)
 
   /* Need to assure that none of the operands of the inc instruction are
      assigned to by the mem insn.  */
-  for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
+  FOR_EACH_INSN_DEF (def, mem_insn.insn)
     {
-      df_ref def = *def_rec;
       unsigned int regno = DF_REF_REGNO (def);
       if ((regno == REGNO (inc_insn.reg0))
 	  || (regno == REGNO (inc_insn.reg_res)))
@@ -1342,7 +1341,7 @@ merge_in_block (int max_reg, basic_block
 
   FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
     {
-      unsigned int uid = INSN_UID (insn);
+      df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       bool insn_is_add_or_inc = true;
 
       if (!NONDEBUG_INSN_P (insn))
@@ -1418,22 +1417,20 @@ merge_in_block (int max_reg, basic_block
 
       /* If the inc insn was merged with a mem, the inc insn is gone
 	 and there is noting to update.  */
-      if (DF_INSN_UID_GET (uid))
+      if (insn_info)
 	{
-	  df_ref *def_rec;
-	  df_ref *use_rec;
+	  df_ref def, use;
+
 	  /* Need to update next use.  */
-	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+	  FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	    {
-	      df_ref def = *def_rec;
 	      reg_next_use[DF_REF_REGNO (def)] = NULL;
 	      reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
 	      reg_next_def[DF_REF_REGNO (def)] = insn;
 	    }
 
-	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+	  FOR_EACH_INSN_INFO_USE (use, insn_info)
 	    {
-	      df_ref use = *use_rec;
 	      reg_next_use[DF_REF_REGNO (use)] = insn;
 	      if (insn_is_add_or_inc)
 		reg_next_inc_use[DF_REF_REGNO (use)] = insn;
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/combine.c	2014-06-14 20:08:33.434584013 +0100
@@ -985,7 +985,7 @@ create_log_links (void)
 {
   basic_block bb;
   rtx *next_use, insn;
-  df_ref *def_vec, *use_vec;
+  df_ref def, use;
 
   next_use = XCNEWVEC (rtx, max_reg_num ());
 
@@ -1008,9 +1008,8 @@ create_log_links (void)
 	  /* Log links are created only once.  */
 	  gcc_assert (!LOG_LINKS (insn));
 
-          for (def_vec = DF_INSN_DEFS (insn); *def_vec; def_vec++)
+	  FOR_EACH_INSN_DEF (def, insn)
             {
-	      df_ref def = *def_vec;
               int regno = DF_REF_REGNO (def);
               rtx use_insn;
 
@@ -1061,9 +1060,8 @@ create_log_links (void)
               next_use[regno] = NULL_RTX;
             }
 
-          for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
+	  FOR_EACH_INSN_USE (use, insn)
             {
-	      df_ref use = *use_vec;
 	      int regno = DF_REF_REGNO (use);
 
               /* Do not consider the usage of the stack pointer
Index: gcc/compare-elim.c
===================================================================
--- gcc/compare-elim.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/compare-elim.c	2014-06-14 20:08:33.435584023 +0100
@@ -193,14 +193,14 @@ arithmetic_flags_clobber_p (rtx insn)
 static void
 find_flags_uses_in_insn (struct comparison *cmp, rtx insn)
 {
-  df_ref *use_rec, use;
+  df_ref use;
 
   /* If we've already lost track of uses, don't bother collecting more.  */
   if (cmp->missing_uses)
     return;
 
   /* Find a USE of the flags register.  */
-  for (use_rec = DF_INSN_USES (insn); (use = *use_rec) != NULL; use_rec++)
+  FOR_EACH_INSN_USE (use, insn)
     if (DF_REF_REGNO (use) == targetm.flags_regnum)
       {
 	rtx x, *loc;
@@ -522,7 +522,7 @@ try_eliminate_compare (struct comparison
 	   | DF_REF_MUST_CLOBBER | DF_REF_SIGN_EXTRACT
 	   | DF_REF_ZERO_EXTRACT | DF_REF_STRICT_LOW_PART
 	   | DF_REF_PRE_POST_MODIFY);
-      df_ref *def_rec, def;
+      df_ref def;
 
       /* Note that the BB_HEAD is always either a note or a label, but in
 	 any case it means that IN_A is defined outside the block.  */
@@ -532,7 +532,7 @@ try_eliminate_compare (struct comparison
 	continue;
 
       /* Find a possible def of IN_A in INSN.  */
-      for (def_rec = DF_INSN_DEFS (insn); (def = *def_rec) != NULL; def_rec++)
+      FOR_EACH_INSN_DEF (def, insn)
 	if (DF_REF_REGNO (def) == REGNO (in_a))
 	  break;
 
Index: gcc/cprop.c
===================================================================
--- gcc/cprop.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/cprop.c	2014-06-14 20:08:33.449584153 +0100
@@ -374,11 +374,10 @@ dump_hash_table (FILE *file, const char
 static void
 make_set_regs_unavailable (rtx insn)
 {
-  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
-    SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
+  FOR_EACH_INSN_DEF (def, insn)
+    SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
 }
 
 /* Top level function to create an assignment hash table.
@@ -533,11 +532,10 @@ reg_not_set_p (const_rtx x, const_rtx in
 static void
 mark_oprs_set (rtx insn)
 {
-  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
-    SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
+  FOR_EACH_INSN_DEF (def, insn)
+    SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (def));
 }
 \f
 /* Compute copy/constant propagation working variables.  */
Index: gcc/dce.c
===================================================================
--- gcc/dce.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/dce.c	2014-06-14 20:08:33.441584079 +0100
@@ -96,6 +96,7 @@ deletable_insn_p (rtx insn, bool fast, b
 {
   rtx body, x;
   int i;
+  df_ref def;
 
   if (CALL_P (insn)
       /* We cannot delete calls inside of the recursive dce because
@@ -121,9 +122,9 @@ deletable_insn_p (rtx insn, bool fast, b
     return false;
 
   /* If INSN sets a global_reg, leave it untouched.  */
-  for (df_ref *def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-    if (HARD_REGISTER_NUM_P (DF_REF_REGNO (*def_rec))
-	&& global_regs[DF_REF_REGNO (*def_rec)])
+  FOR_EACH_INSN_DEF (def, insn)
+    if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def))
+	&& global_regs[DF_REF_REGNO (def)])
       return false;
 
   body = PATTERN (insn);
@@ -305,18 +306,18 @@ find_call_stack_args (rtx call_insn, boo
 	       sp + offset.  */
 	    if (!fast)
 	      {
-		df_ref *use_rec;
+		df_ref use;
 		struct df_link *defs;
 		rtx set;
 
-		for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++)
-		  if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
+		FOR_EACH_INSN_USE (use, call_insn)
+		  if (rtx_equal_p (addr, DF_REF_REG (use)))
 		    break;
 
-		if (*use_rec == NULL)
+		if (use == NULL)
 		  return false;
 
-		for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
+		for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
 		  if (! DF_REF_IS_ARTIFICIAL (defs->ref))
 		    break;
 
@@ -364,15 +365,15 @@ find_call_stack_args (rtx call_insn, boo
 	  }
 	if (addr != stack_pointer_rtx)
 	  {
-	    df_ref *use_rec;
+	    df_ref use;
 	    struct df_link *defs;
 	    rtx set;
 
-	    for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++)
-	      if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
+	    FOR_EACH_INSN_USE (use, call_insn)
+	      if (rtx_equal_p (addr, DF_REF_REG (use)))
 		break;
 
-	    for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
+	    for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
 	      if (! DF_REF_IS_ARTIFICIAL (defs->ref))
 		break;
 
@@ -429,18 +430,18 @@ find_call_stack_args (rtx call_insn, boo
 	    break;
 	  if (!fast)
 	    {
-	      df_ref *use_rec;
+	      df_ref use;
 	      struct df_link *defs;
 	      rtx set;
 
-	      for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
-		if (rtx_equal_p (addr, DF_REF_REG (*use_rec)))
+	      FOR_EACH_INSN_USE (use, insn)
+		if (rtx_equal_p (addr, DF_REF_REG (use)))
 		  break;
 
-	      if (*use_rec == NULL)
+	      if (use == NULL)
 		break;
 
-	      for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
+	      for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
 		if (! DF_REF_IS_ARTIFICIAL (defs->ref))
 		  break;
 
@@ -496,10 +497,10 @@ find_call_stack_args (rtx call_insn, boo
 static void
 remove_reg_equal_equiv_notes_for_defs (rtx insn)
 {
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-    remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (*def_rec));
+  FOR_EACH_INSN_DEF (def, insn)
+    remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (def));
 }
 
 /* Scan all BBs for debug insns and reset those that reference values
@@ -515,11 +516,10 @@ reset_unmarked_insns_debug_uses (void)
     FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
       if (DEBUG_INSN_P (insn))
 	{
-	  df_ref *use_rec;
+	  df_ref use;
 
-	  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+	  FOR_EACH_INSN_USE (use, insn)
 	    {
-	      df_ref use = *use_rec;
 	      struct df_link *defs;
 	      for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
 		{
@@ -680,14 +680,13 @@ mark_artificial_uses (void)
 mark_reg_dependencies (rtx insn)
 {
   struct df_link *defs;
-  df_ref *use_rec;
+  df_ref use;
 
   if (DEBUG_INSN_P (insn))
     return;
 
-  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+  FOR_EACH_INSN_USE (use, insn)
     {
-      df_ref use = *use_rec;
       if (dump_file)
 	{
 	  fprintf (dump_file, "Processing use of ");
@@ -868,14 +867,14 @@ word_dce_process_block (basic_block bb,
   FOR_BB_INSNS_REVERSE (bb, insn)
     if (DEBUG_INSN_P (insn))
       {
-	df_ref *use_rec;
-	for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
-	  if (DF_REF_REGNO (*use_rec) >= FIRST_PSEUDO_REGISTER
-	      && (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (*use_rec)))
+	df_ref use;
+	FOR_EACH_INSN_USE (use, insn)
+	  if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER
+	      && (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (use)))
 		  == 2 * UNITS_PER_WORD)
-	      && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec))
-	      && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (*use_rec) + 1))
-	    dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec));
+	      && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use))
+	      && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use) + 1))
+	    dead_debug_add (&debug, use, DF_REF_REGNO (use));
       }
     else if (INSN_P (insn))
       {
@@ -898,10 +897,10 @@ word_dce_process_block (basic_block bb,
 	   death.  */
 	if (debug.used && !bitmap_empty_p (debug.used))
 	  {
-	    df_ref *def_rec;
+	    df_ref def;
 
-	    for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	      dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
+	    FOR_EACH_INSN_DEF (def, insn)
+	      dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn,
 				      marked_insn_p (insn)
 				      && !control_flow_insn_p (insn)
 				      ? DEBUG_TEMP_AFTER_WITH_REG_FORCE
@@ -939,7 +938,7 @@ dce_process_block (basic_block bb, bool
   bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
   rtx insn;
   bool block_changed;
-  df_ref *def_rec;
+  df_ref def;
   struct dead_debug_local debug;
 
   if (redo_out)
@@ -969,11 +968,11 @@ dce_process_block (basic_block bb, bool
   FOR_BB_INSNS_REVERSE (bb, insn)
     if (DEBUG_INSN_P (insn))
       {
-	df_ref *use_rec;
-	for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
-	  if (!bitmap_bit_p (local_live, DF_REF_REGNO (*use_rec))
-	      && !bitmap_bit_p (au, DF_REF_REGNO (*use_rec)))
-	    dead_debug_add (&debug, *use_rec, DF_REF_REGNO (*use_rec));
+	df_ref use;
+	FOR_EACH_INSN_USE (use, insn)
+	  if (!bitmap_bit_p (local_live, DF_REF_REGNO (use))
+	      && !bitmap_bit_p (au, DF_REF_REGNO (use)))
+	    dead_debug_add (&debug, use, DF_REF_REGNO (use));
       }
     else if (INSN_P (insn))
       {
@@ -981,9 +980,9 @@ dce_process_block (basic_block bb, bool
 
 	/* The insn is needed if there is someone who uses the output.  */
 	if (!needed)
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
-		|| bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
+	  FOR_EACH_INSN_DEF (def, insn)
+	    if (bitmap_bit_p (local_live, DF_REF_REGNO (def))
+		|| bitmap_bit_p (au, DF_REF_REGNO (def)))
 	      {
 		needed = true;
 		mark_insn (insn, true);
@@ -1004,8 +1003,8 @@ dce_process_block (basic_block bb, bool
 	   was marked, in case the debug use was after the point of
 	   death.  */
 	if (debug.used && !bitmap_empty_p (debug.used))
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
+	  FOR_EACH_INSN_DEF (def, insn)
+	    dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn,
 				    needed && !control_flow_insn_p (insn)
 				    ? DEBUG_TEMP_AFTER_WITH_REG_FORCE
 				    : DEBUG_TEMP_BEFORE_WITH_VALUE);
Index: gcc/ddg.c
===================================================================
--- gcc/ddg.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/ddg.c	2014-06-14 20:08:33.441584079 +0100
@@ -169,11 +169,11 @@ autoinc_var_is_used_p (rtx def_insn, rtx
 static bool
 def_has_ccmode_p (rtx insn)
 {
-  df_ref *def;
+  df_ref def;
 
-  for (def = DF_INSN_DEFS (insn); *def; def++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      enum machine_mode mode = GET_MODE (DF_REF_REG (*def));
+      enum machine_mode mode = GET_MODE (DF_REF_REG (def));
 
       if (GET_MODE_CLASS (mode) == MODE_CC)
 	return true;
Index: gcc/df-core.c
===================================================================
--- gcc/df-core.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/df-core.c	2014-06-14 20:08:33.448584144 +0100
@@ -1947,21 +1947,16 @@ df_set_clean_cfg (void)
 df_bb_regno_first_def_find (basic_block bb, unsigned int regno)
 {
   rtx insn;
-  df_ref *def_rec;
-  unsigned int uid;
+  df_ref def;
 
   FOR_BB_INSNS (bb, insn)
     {
       if (!INSN_P (insn))
 	continue;
 
-      uid = INSN_UID (insn);
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-	{
-	  df_ref def = *def_rec;
-	  if (DF_REF_REGNO (def) == regno)
-	    return def;
-	}
+      FOR_EACH_INSN_DEF (def, insn)
+	if (DF_REF_REGNO (def) == regno)
+	  return def;
     }
   return NULL;
 }
@@ -1973,21 +1968,16 @@ df_bb_regno_first_def_find (basic_block
 df_bb_regno_last_def_find (basic_block bb, unsigned int regno)
 {
   rtx insn;
-  df_ref *def_rec;
-  unsigned int uid;
+  df_ref def;
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
       if (!INSN_P (insn))
 	continue;
 
-      uid = INSN_UID (insn);
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-	{
-	  df_ref def = *def_rec;
-	  if (DF_REF_REGNO (def) == regno)
-	    return def;
-	}
+      FOR_EACH_INSN_DEF (def, insn)
+	if (DF_REF_REGNO (def) == regno)
+	  return def;
     }
 
   return NULL;
@@ -1999,20 +1989,15 @@ df_bb_regno_last_def_find (basic_block b
 df_ref
 df_find_def (rtx insn, rtx reg)
 {
-  unsigned int uid;
-  df_ref *def_rec;
+  df_ref def;
 
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
   gcc_assert (REG_P (reg));
 
-  uid = INSN_UID (insn);
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_REGNO (def) == REGNO (reg))
-	return def;
-    }
+  FOR_EACH_INSN_DEF (def, insn)
+    if (DF_REF_REGNO (def) == REGNO (reg))
+      return def;
 
   return NULL;
 }
@@ -2033,27 +2018,20 @@ df_reg_defined (rtx insn, rtx reg)
 df_ref
 df_find_use (rtx insn, rtx reg)
 {
-  unsigned int uid;
-  df_ref *use_rec;
+  df_ref use;
 
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
   gcc_assert (REG_P (reg));
 
-  uid = INSN_UID (insn);
-  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
+  df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+  FOR_EACH_INSN_INFO_USE (use, insn_info)
+    if (DF_REF_REGNO (use) == REGNO (reg))
+      return use;
+  if (df->changeable_flags & DF_EQ_NOTES)
+    FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
       if (DF_REF_REGNO (use) == REGNO (reg))
 	return use;
-    }
-  if (df->changeable_flags & DF_EQ_NOTES)
-    for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
-      {
-	df_ref use = *use_rec;
-	if (DF_REF_REGNO (use) == REGNO (reg))
-	  return use;
-      }
   return NULL;
 }
 
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/df-problems.c	2014-06-14 20:08:33.442584088 +0100
@@ -268,12 +268,10 @@ df_rd_simulate_artificial_defs_at_top (b
 df_rd_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx insn,
 			 bitmap local_rd)
 {
-  unsigned uid = INSN_UID (insn);
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      df_ref def = *def_rec;
       unsigned int dregno = DF_REF_REGNO (def);
       if ((!(df->changeable_flags & DF_NO_HARD_REGS))
           || (dregno >= FIRST_PSEUDO_REGISTER))
@@ -838,6 +836,7 @@ df_lr_bb_local_compute (unsigned int bb_
   rtx insn;
   df_ref *def_rec;
   df_ref *use_rec;
+  df_ref def, use;
 
   /* Process the registers set in an exception handler.  */
   for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
@@ -862,30 +861,23 @@ df_lr_bb_local_compute (unsigned int bb_
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
-
       if (!NONDEBUG_INSN_P (insn))
 	continue;
 
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-	{
-	  df_ref def = *def_rec;
-	  /* If the def is to only part of the reg, it does
-	     not kill the other defs that reach here.  */
-	  if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
-	    {
-	      unsigned int dregno = DF_REF_REGNO (def);
-	      bitmap_set_bit (&bb_info->def, dregno);
-	      bitmap_clear_bit (&bb_info->use, dregno);
-	    }
-	}
+      df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	/* If the def is to only part of the reg, it does
+	   not kill the other defs that reach here.  */
+	if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
+	  {
+	    unsigned int dregno = DF_REF_REGNO (def);
+	    bitmap_set_bit (&bb_info->def, dregno);
+	    bitmap_clear_bit (&bb_info->use, dregno);
+	  }
 
-      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	{
-	  df_ref use = *use_rec;
-	  /* Add use to set of uses in this BB.  */
-	  bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
-	}
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
+	/* Add use to set of uses in this BB.  */
+	bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
     }
 
   /* Process the registers set in an exception handler or the hard
@@ -1463,7 +1455,7 @@ df_live_bb_local_compute (unsigned int b
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index);
   rtx insn;
-  df_ref *def_rec;
+  df_ref def, *def_rec;
   int luid = 0;
 
   FOR_BB_INSNS (bb, insn)
@@ -1484,9 +1476,8 @@ df_live_bb_local_compute (unsigned int b
 	continue;
 
       luid++;
-      for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	{
-	  df_ref def = *def_rec;
 	  unsigned int regno = DF_REF_REGNO (def);
 
 	  if (DF_REF_FLAGS_IS_SET (def,
@@ -1985,6 +1976,7 @@ df_chain_remove_problem (void)
       rtx insn;
       df_ref *def_rec;
       df_ref *use_rec;
+      df_ref def, use;
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
 
       if (df_chain_problem_p (DF_DU_CHAIN))
@@ -1995,23 +1987,20 @@ df_chain_remove_problem (void)
 	  DF_REF_CHAIN (*use_rec) = NULL;
 
       FOR_BB_INSNS (bb, insn)
-	{
-	  unsigned int uid = INSN_UID (insn);
-
-	  if (INSN_P (insn))
-	    {
-	      if (df_chain_problem_p (DF_DU_CHAIN))
-		for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-		  DF_REF_CHAIN (*def_rec) = NULL;
-	      if (df_chain_problem_p (DF_UD_CHAIN))
-		{
-		  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-		    DF_REF_CHAIN (*use_rec) = NULL;
-		  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
-		    DF_REF_CHAIN (*use_rec) = NULL;
-		}
-	    }
-	}
+	if (INSN_P (insn))
+	  {
+	    df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+	    if (df_chain_problem_p (DF_DU_CHAIN))
+	      FOR_EACH_INSN_INFO_DEF (def, insn_info)
+		DF_REF_CHAIN (def) = NULL;
+	    if (df_chain_problem_p (DF_UD_CHAIN))
+	      {
+		FOR_EACH_INSN_INFO_USE (use, insn_info)
+		  DF_REF_CHAIN (use) = NULL;
+		FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+		  DF_REF_CHAIN (use) = NULL;
+	      }
+	  }
     }
 
   bitmap_clear (df_chain->out_of_date_transfer_functions);
@@ -2254,39 +2243,28 @@ df_chain_insn_top_dump (const_rtx insn,
   if (df_chain_problem_p (DF_UD_CHAIN) && INSN_P (insn))
     {
       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-      df_ref *use_rec = DF_INSN_INFO_USES (insn_info);
-      df_ref *eq_use_rec = DF_INSN_INFO_EQ_USES (insn_info);
+      df_ref use;
+
       fprintf (file, ";;   UD chains for insn luid %d uid %d\n",
 	       DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
-      if (*use_rec || *eq_use_rec)
-	{
-	  while (*use_rec)
-	    {
-	      df_ref use = *use_rec;
-	      if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
-		  || !(df->changeable_flags & DF_NO_HARD_REGS))
-		{
-		  fprintf (file, ";;      reg %d ", DF_REF_REGNO (use));
-		  if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
-		    fprintf (file, "read/write ");
-		  df_chain_dump (DF_REF_CHAIN (use), file);
-		  fprintf (file, "\n");
-		}
-	      use_rec++;
-	    }
-	  while (*eq_use_rec)
-	    {
-	      df_ref use = *eq_use_rec;
-	      if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
-		  || !(df->changeable_flags & DF_NO_HARD_REGS))
-		{
-		  fprintf (file, ";;   eq_note reg %d ", DF_REF_REGNO (use));
-		  df_chain_dump (DF_REF_CHAIN (use), file);
-		  fprintf (file, "\n");
-		}
-	      eq_use_rec++;
-	    }
-	}
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
+	if (!HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
+	    || !(df->changeable_flags & DF_NO_HARD_REGS))
+	  {
+	    fprintf (file, ";;      reg %d ", DF_REF_REGNO (use));
+	    if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
+	      fprintf (file, "read/write ");
+	    df_chain_dump (DF_REF_CHAIN (use), file);
+	    fprintf (file, "\n");
+	  }
+      FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+	if (!HARD_REGISTER_NUM_P (DF_REF_REGNO (use))
+	    || !(df->changeable_flags & DF_NO_HARD_REGS))
+	  {
+	    fprintf (file, ";;   eq_note reg %d ", DF_REF_REGNO (use));
+	    df_chain_dump (DF_REF_CHAIN (use), file);
+	    fprintf (file, "\n");
+	  }
     }
 }
 
@@ -2296,26 +2274,19 @@ df_chain_insn_bottom_dump (const_rtx ins
   if (df_chain_problem_p (DF_DU_CHAIN) && INSN_P (insn))
     {
       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-      df_ref *def_rec = DF_INSN_INFO_DEFS (insn_info);
+      df_ref def;
       fprintf (file, ";;   DU chains for insn luid %d uid %d\n",
 	       DF_INSN_INFO_LUID (insn_info), INSN_UID (insn));
-      if (*def_rec)
-	{
-	  while (*def_rec)
-	    {
-	      df_ref def = *def_rec;
-	      if (! HARD_REGISTER_NUM_P (DF_REF_REGNO (def))
-		  || !(df->changeable_flags & DF_NO_HARD_REGS))
-		{
-		  fprintf (file, ";;      reg %d ", DF_REF_REGNO (def));
-		  if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
-		    fprintf (file, "read/write ");
-		  df_chain_dump (DF_REF_CHAIN (def), file);
-		  fprintf (file, "\n");
-		}
-	      def_rec++;
-	    }
-	}
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	if (!HARD_REGISTER_NUM_P (DF_REF_REGNO (def))
+	    || !(df->changeable_flags & DF_NO_HARD_REGS))
+	  {
+	    fprintf (file, ";;      reg %d ", DF_REF_REGNO (def));
+	    if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
+	      fprintf (file, "read/write ");
+	    df_chain_dump (DF_REF_CHAIN (def), file);
+	    fprintf (file, "\n");
+	  }
       fprintf (file, "\n");
     }
 }
@@ -2534,6 +2505,7 @@ df_word_lr_bb_local_compute (unsigned in
   rtx insn;
   df_ref *def_rec;
   df_ref *use_rec;
+  df_ref def, use;
 
   /* Ensure that artificial refs don't contain references to pseudos.  */
   for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
@@ -2550,26 +2522,20 @@ df_word_lr_bb_local_compute (unsigned in
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
-
       if (!NONDEBUG_INSN_P (insn))
 	continue;
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-	{
-	  df_ref def = *def_rec;
-	  /* If the def is to only part of the reg, it does
-	     not kill the other defs that reach here.  */
-	  if (!(DF_REF_FLAGS (def) & (DF_REF_CONDITIONAL)))
-	    {
-	      df_word_lr_mark_ref (def, true, &bb_info->def);
-	      df_word_lr_mark_ref (def, false, &bb_info->use);
-	    }
-	}
-      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	{
-	  df_ref use = *use_rec;
-	  df_word_lr_mark_ref (use, true, &bb_info->use);
-	}
+
+      df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	/* If the def is to only part of the reg, it does
+	   not kill the other defs that reach here.  */
+	if (!(DF_REF_FLAGS (def) & (DF_REF_CONDITIONAL)))
+	  {
+	    df_word_lr_mark_ref (def, true, &bb_info->def);
+	    df_word_lr_mark_ref (def, false, &bb_info->use);
+	  }
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
+	df_word_lr_mark_ref (use, true, &bb_info->use);
     }
 }
 
@@ -2753,17 +2719,13 @@ df_word_lr_add_problem (void)
 df_word_lr_simulate_defs (rtx insn, bitmap live)
 {
   bool changed = false;
-  df_ref *def_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_CONDITIONAL)
-	changed = true;
-      else
-	changed |= df_word_lr_mark_ref (*def_rec, false, live);
-    }
+  FOR_EACH_INSN_DEF (def, insn)
+    if (DF_REF_FLAGS (def) & DF_REF_CONDITIONAL)
+      changed = true;
+    else
+      changed |= df_word_lr_mark_ref (def, false, live);
   return changed;
 }
 
@@ -2773,11 +2735,10 @@ df_word_lr_simulate_defs (rtx insn, bitm
 void
 df_word_lr_simulate_uses (rtx insn, bitmap live)
 {
-  df_ref *use_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref use;
 
-  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-    df_word_lr_mark_ref (*use_rec, true, live);
+  FOR_EACH_INSN_USE (use, insn)
+    df_word_lr_mark_ref (use, true, live);
 }
 \f
 /*----------------------------------------------------------------------------
@@ -2899,22 +2860,19 @@ df_remove_dead_eq_notes (rtx insn, bitma
 	       one REG_EQUAL/EQUIV note, all of EQ_USES will refer to this note
 	       so we need to purge the complete EQ_USES vector when removing
 	       the note using df_notes_rescan.  */
-	    df_ref *use_rec;
+	    df_ref use;
 	    bool deleted = false;
 
-	    for (use_rec = DF_INSN_EQ_USES (insn); *use_rec; use_rec++)
-	      {
-		df_ref use = *use_rec;
-		if (DF_REF_REGNO (use) > FIRST_PSEUDO_REGISTER
-		    && DF_REF_LOC (use)
-		    && (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
-		    && ! bitmap_bit_p (live, DF_REF_REGNO (use))
-		    && loc_mentioned_in_p (DF_REF_LOC (use), XEXP (link, 0)))
-		  {
-		    deleted = true;
-		    break;
-		  }
-	      }
+	    FOR_EACH_INSN_EQ_USE (use, insn)
+	      if (DF_REF_REGNO (use) > FIRST_PSEUDO_REGISTER
+		  && DF_REF_LOC (use)
+		  && (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
+		  && !bitmap_bit_p (live, DF_REF_REGNO (use))
+		  && loc_mentioned_in_p (DF_REF_LOC (use), XEXP (link, 0)))
+		{
+		  deleted = true;
+		  break;
+		}
 	    if (deleted)
 	      {
 		rtx next;
@@ -3156,6 +3114,7 @@ df_note_bb_compute (unsigned int bb_inde
   rtx insn;
   df_ref *def_rec;
   df_ref *use_rec;
+  df_ref def, use;
   struct dead_debug_local debug;
 
   dead_debug_local_init (&debug, NULL, NULL);
@@ -3204,7 +3163,7 @@ df_note_bb_compute (unsigned int bb_inde
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
+      df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       struct df_mw_hardreg **mws_rec;
       int debug_insn;
 
@@ -3221,13 +3180,14 @@ df_note_bb_compute (unsigned int bb_inde
 	{
 	  if (REG_DEAD_DEBUGGING && dump_file)
 	    {
-	      fprintf (dump_file, "processing call %d\n  live =", INSN_UID (insn));
+	      fprintf (dump_file, "processing call %d\n  live =",
+		       INSN_UID (insn));
 	      df_print_regset (dump_file, live);
 	    }
 
 	  /* We only care about real sets for calls.  Clobbers cannot
 	     be depended on to really die.  */
-	  mws_rec = DF_INSN_UID_MWS (uid);
+	  mws_rec = DF_INSN_INFO_MWS (insn_info);
 	  while (*mws_rec)
 	    {
 	      struct df_mw_hardreg *mws = *mws_rec;
@@ -3241,9 +3201,8 @@ df_note_bb_compute (unsigned int bb_inde
 
 	  /* All of the defs except the return value are some sort of
 	     clobber.  This code is for the return.  */
-	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+	  FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	    {
-	      df_ref def = *def_rec;
 	      unsigned int dregno = DF_REF_REGNO (def);
 	      if (!DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
 		{
@@ -3259,7 +3218,7 @@ df_note_bb_compute (unsigned int bb_inde
       else
 	{
 	  /* Regular insn.  */
-	  mws_rec = DF_INSN_UID_MWS (uid);
+	  mws_rec = DF_INSN_INFO_MWS (insn_info);
 	  while (*mws_rec)
 	    {
 	      struct df_mw_hardreg *mws = *mws_rec;
@@ -3270,9 +3229,8 @@ df_note_bb_compute (unsigned int bb_inde
 	      mws_rec++;
 	    }
 
-	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+	  FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	    {
-	      df_ref def = *def_rec;
 	      unsigned int dregno = DF_REF_REGNO (def);
 	      df_create_unused_note (insn,
 				     def, live, artificial_uses, &debug);
@@ -3286,7 +3244,7 @@ df_note_bb_compute (unsigned int bb_inde
 	}
 
       /* Process the uses.  */
-      mws_rec = DF_INSN_UID_MWS (uid);
+      mws_rec = DF_INSN_INFO_MWS (insn_info);
       while (*mws_rec)
 	{
 	  struct df_mw_hardreg *mws = *mws_rec;
@@ -3306,9 +3264,8 @@ df_note_bb_compute (unsigned int bb_inde
 	  mws_rec++;
 	}
 
-      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
 	{
-	  df_ref use = *use_rec;
 	  unsigned int uregno = DF_REF_REGNO (use);
 
 	  if (REG_DEAD_DEBUGGING && dump_file && !debug_insn)
@@ -3475,14 +3432,10 @@ df_note_add_problem (void)
 void
 df_simulate_find_defs (rtx insn, bitmap defs)
 {
-  df_ref *def_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      bitmap_set_bit (defs, DF_REF_REGNO (def));
-    }
+  FOR_EACH_INSN_DEF (def, insn)
+    bitmap_set_bit (defs, DF_REF_REGNO (def));
 }
 
 /* Find the set of uses for INSN.  This includes partial defs.  */
@@ -3490,20 +3443,14 @@ df_simulate_find_defs (rtx insn, bitmap
 static void
 df_simulate_find_uses (rtx insn, bitmap uses)
 {
-  df_ref *rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref def, use;
+  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
 
-  for (rec = DF_INSN_UID_DEFS (uid); *rec; rec++)
-    {
-      df_ref def = *rec;
-      if (DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))
-	bitmap_set_bit (uses, DF_REF_REGNO (def));
-    }
-  for (rec = DF_INSN_UID_USES (uid); *rec; rec++)
-    {
-      df_ref use = *rec;
-      bitmap_set_bit (uses, DF_REF_REGNO (use));
-    }
+  FOR_EACH_INSN_INFO_DEF (def, insn_info)
+    if (DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))
+      bitmap_set_bit (uses, DF_REF_REGNO (def));
+  FOR_EACH_INSN_INFO_USE (use, insn_info)
+    bitmap_set_bit (uses, DF_REF_REGNO (use));
 }
 
 /* Find the set of real DEFs, which are not clobbers, for INSN.  */
@@ -3511,15 +3458,11 @@ df_simulate_find_uses (rtx insn, bitmap
 void
 df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
 {
-  df_ref *def_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
-	bitmap_set_bit (defs, DF_REF_REGNO (def));
-    }
+  FOR_EACH_INSN_DEF (def, insn)
+    if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
+      bitmap_set_bit (defs, DF_REF_REGNO (def));
 }
 
 
@@ -3528,12 +3471,10 @@ df_simulate_find_noclobber_defs (rtx ins
 void
 df_simulate_defs (rtx insn, bitmap live)
 {
-  df_ref *def_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      df_ref def = *def_rec;
       unsigned int dregno = DF_REF_REGNO (def);
 
       /* If the def is to only part of the reg, it does
@@ -3549,18 +3490,14 @@ df_simulate_defs (rtx insn, bitmap live)
 void
 df_simulate_uses (rtx insn, bitmap live)
 {
-  df_ref *use_rec;
-  unsigned int uid = INSN_UID (insn);
+  df_ref use;
 
   if (DEBUG_INSN_P (insn))
     return;
 
-  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      /* Add use to set of uses in this BB.  */
-      bitmap_set_bit (live, DF_REF_REGNO (use));
-    }
+  FOR_EACH_INSN_USE (use, insn)
+    /* Add use to set of uses in this BB.  */
+    bitmap_set_bit (live, DF_REF_REGNO (use));
 }
 
 
@@ -4206,14 +4143,12 @@ df_md_simulate_artificial_defs_at_top (b
 
 void
 df_md_simulate_one_insn (basic_block bb ATTRIBUTE_UNUSED, rtx insn,
-                        bitmap local_md)
+			 bitmap local_md)
 {
-  unsigned uid = INSN_UID (insn);
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      df_ref def = *def_rec;
       unsigned int dregno = DF_REF_REGNO (def);
       if ((!(df->changeable_flags & DF_NO_HARD_REGS))
           || (dregno >= FIRST_PSEUDO_REGISTER))
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/df-scan.c	2014-06-14 20:08:33.449584153 +0100
@@ -1640,6 +1640,7 @@ df_reorganize_refs_by_reg_by_insn (struc
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
       rtx insn;
       df_ref *ref_rec;
+      df_ref def, use;
 
       if (include_defs)
 	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
@@ -1658,24 +1659,24 @@ df_reorganize_refs_by_reg_by_insn (struc
 	{
 	  if (INSN_P (insn))
 	    {
-	      unsigned int uid = INSN_UID (insn);
+	      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
 
 	      if (include_defs)
-		for (ref_rec = DF_INSN_UID_DEFS (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_DEF (def, insn_info)
 		  {
-		    unsigned int regno = DF_REF_REGNO (*ref_rec);
+		    unsigned int regno = DF_REF_REGNO (def);
 		    ref_info->count[regno]++;
 		  }
 	      if (include_uses)
-		for (ref_rec = DF_INSN_UID_USES (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_USE (use, insn_info)
 		  {
-		    unsigned int regno = DF_REF_REGNO (*ref_rec);
+		    unsigned int regno = DF_REF_REGNO (use);
 		    ref_info->count[regno]++;
 		  }
 	      if (include_eq_uses)
-		for (ref_rec = DF_INSN_UID_EQ_USES (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
 		  {
-		    unsigned int regno = DF_REF_REGNO (*ref_rec);
+		    unsigned int regno = DF_REF_REGNO (use);
 		    ref_info->count[regno]++;
 		  }
 	    }
@@ -1694,6 +1695,7 @@ df_reorganize_refs_by_reg_by_insn (struc
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
       rtx insn;
       df_ref *ref_rec;
+      df_ref def, use;
 
       if (include_defs)
 	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
@@ -1726,45 +1728,42 @@ df_reorganize_refs_by_reg_by_insn (struc
 	{
 	  if (INSN_P (insn))
 	    {
-	      unsigned int uid = INSN_UID (insn);
+	      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
 
 	      if (include_defs)
-		for (ref_rec = DF_INSN_UID_DEFS (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_DEF (def, insn_info)
 		  {
-		    df_ref ref = *ref_rec;
-		    unsigned int regno = DF_REF_REGNO (ref);
+		    unsigned int regno = DF_REF_REGNO (def);
 		    if (regno >= start)
 		      {
 			unsigned int id
 			  = ref_info->begin[regno] + ref_info->count[regno]++;
-			DF_REF_ID (ref) = id;
-			ref_info->refs[id] = ref;
+			DF_REF_ID (def) = id;
+			ref_info->refs[id] = def;
 		      }
 		  }
 	      if (include_uses)
-		for (ref_rec = DF_INSN_UID_USES (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_USE (use, insn_info)
 		  {
-		    df_ref ref = *ref_rec;
-		    unsigned int regno = DF_REF_REGNO (ref);
+		    unsigned int regno = DF_REF_REGNO (use);
 		    if (regno >= start)
 		      {
 			unsigned int id
 			  = ref_info->begin[regno] + ref_info->count[regno]++;
-			DF_REF_ID (ref) = id;
-			ref_info->refs[id] = ref;
+			DF_REF_ID (use) = id;
+			ref_info->refs[id] = use;
 		      }
 		  }
 	      if (include_eq_uses)
-		for (ref_rec = DF_INSN_UID_EQ_USES (uid); *ref_rec; ref_rec++)
+		FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
 		  {
-		    df_ref ref = *ref_rec;
-		    unsigned int regno = DF_REF_REGNO (ref);
+		    unsigned int regno = DF_REF_REGNO (use);
 		    if (regno >= start)
 		      {
 			unsigned int id
 			  = ref_info->begin[regno] + ref_info->count[regno]++;
-			DF_REF_ID (ref) = id;
-			ref_info->refs[id] = ref;
+			DF_REF_ID (use) = id;
+			ref_info->refs[id] = use;
 		      }
 		  }
 	    }
Index: gcc/fwprop.c
===================================================================
--- gcc/fwprop.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/fwprop.c	2014-06-14 20:08:33.442584088 +0100
@@ -700,16 +700,13 @@ local_ref_killed_between_p (df_ref ref,
 
   for (insn = from; insn != to; insn = NEXT_INSN (insn))
     {
-      df_ref *def_rec;
+      df_ref def;
       if (!INSN_P (insn))
 	continue;
 
-      for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	{
-	  df_ref def = *def_rec;
-	  if (DF_REF_REGNO (ref) == DF_REF_REGNO (def))
-	    return true;
-	}
+      FOR_EACH_INSN_DEF (def, insn)
+	if (DF_REF_REGNO (ref) == DF_REF_REGNO (def))
+	  return true;
     }
   return false;
 }
@@ -790,7 +787,7 @@ use_killed_between (df_ref use, rtx def_
 static bool
 all_uses_available_at (rtx def_insn, rtx target_insn)
 {
-  df_ref *use_rec;
+  df_ref use;
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
   rtx def_set = single_set (def_insn);
   rtx next;
@@ -809,18 +806,12 @@ all_uses_available_at (rtx def_insn, rtx
 
       /* If the insn uses the reg that it defines, the substitution is
          invalid.  */
-      for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
-	{
-	  df_ref use = *use_rec;
-	  if (rtx_equal_p (DF_REF_REG (use), def_reg))
-	    return false;
-	}
-      for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
-	{
-	  df_ref use = *use_rec;
-	  if (rtx_equal_p (DF_REF_REG (use), def_reg))
-	    return false;
-	}
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
+	if (rtx_equal_p (DF_REF_REG (use), def_reg))
+	  return false;
+      FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+	if (rtx_equal_p (DF_REF_REG (use), def_reg))
+	  return false;
     }
   else
     {
@@ -828,17 +819,15 @@ all_uses_available_at (rtx def_insn, rtx
 
       /* Look at all the uses of DEF_INSN, and see if they are not
 	 killed between DEF_INSN and TARGET_INSN.  */
-      for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
 	{
-	  df_ref use = *use_rec;
 	  if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
 	    return false;
 	  if (use_killed_between (use, def_insn, target_insn))
 	    return false;
 	}
-      for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
+      FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
 	{
-	  df_ref use = *use_rec;
 	  if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
 	    return false;
 	  if (use_killed_between (use, def_insn, target_insn))
@@ -1034,8 +1023,7 @@ try_fwprop_subst (df_ref use, rtx *loc,
 free_load_extend (rtx src, rtx insn)
 {
   rtx reg;
-  df_ref *use_vec;
-  df_ref use = 0, def;
+  df_ref def, use;
 
   reg = XEXP (src, 0);
 #ifdef LOAD_EXTEND_OP
@@ -1043,15 +1031,11 @@ free_load_extend (rtx src, rtx insn)
 #endif
     return false;
 
-  for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
-    {
-      use = *use_vec;
-
-      if (!DF_REF_IS_ARTIFICIAL (use)
-	  && DF_REF_TYPE (use) == DF_REF_REG_USE
-	  && DF_REF_REG (use) == reg)
-	break;
-    }
+  FOR_EACH_INSN_USE (use, insn)
+    if (!DF_REF_IS_ARTIFICIAL (use)
+	&& DF_REF_TYPE (use) == DF_REF_REG_USE
+	&& DF_REF_REG (use) == reg)
+      break;
   if (!use)
     return false;
 
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/gcse.c	2014-06-14 20:08:33.443584097 +0100
@@ -2961,16 +2961,16 @@ update_bb_reg_pressure (basic_block bb,
 {
   rtx dreg, insn;
   basic_block succ_bb;
-  df_ref *op, op_ref;
+  df_ref use, op_ref;
   edge succ;
   edge_iterator ei;
   int decreased_pressure = 0;
   int nregs;
   enum reg_class pressure_class;
-  
-  for (op = DF_INSN_USES (from); *op; op++)
+
+  FOR_EACH_INSN_USE (use, from)
     {
-      dreg = DF_REF_REAL_REG (*op);
+      dreg = DF_REF_REAL_REG (use);
       /* The live range of register is shrunk only if it isn't:
 	 1. referred on any path from the end of this block to EXIT, or
 	 2. referred by insns other than FROM in this block.  */
@@ -3593,17 +3593,17 @@ calculate_bb_reg_pressure (void)
 	{
 	  rtx dreg;
 	  int regno;
-	  df_ref *def_rec, *use_rec;
+	  df_ref def, use;
 
 	  if (! NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	  FOR_EACH_INSN_DEF (def, insn)
 	    {
-	      dreg = DF_REF_REAL_REG (*def_rec);
+	      dreg = DF_REF_REAL_REG (def);
 	      gcc_assert (REG_P (dreg));
 	      regno = REGNO (dreg);
-	      if (!(DF_REF_FLAGS (*def_rec) 
+	      if (!(DF_REF_FLAGS (def)
 		    & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
 		{
 		  if (bitmap_clear_bit (curr_regs_live, regno))
@@ -3611,9 +3611,9 @@ calculate_bb_reg_pressure (void)
 		}
 	    }
 
-	  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+	  FOR_EACH_INSN_USE (use, insn)
 	    {
-	      dreg = DF_REF_REAL_REG (*use_rec);
+	      dreg = DF_REF_REAL_REG (use);
 	      gcc_assert (REG_P (dreg));
 	      regno = REGNO (dreg);
 	      if (bitmap_set_bit (curr_regs_live, regno))
Index: gcc/hw-doloop.c
===================================================================
--- gcc/hw-doloop.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/hw-doloop.c	2014-06-14 20:08:33.443584097 +0100
@@ -119,7 +119,7 @@ scan_loop (hwloop_info loop)
 	   insn != NEXT_INSN (BB_END (bb));
 	   insn = NEXT_INSN (insn))
 	{
-	  df_ref *def_rec;
+	  df_ref def;
 	  HARD_REG_SET set_this_insn;
 
 	  if (!NONDEBUG_INSN_P (insn))
@@ -131,9 +131,9 @@ scan_loop (hwloop_info loop)
 	    loop->has_asm = true;
 
 	  CLEAR_HARD_REG_SET (set_this_insn);
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	  FOR_EACH_INSN_DEF (def, insn)
 	    {
-	      rtx dreg = DF_REF_REG (*def_rec);
+	      rtx dreg = DF_REF_REG (def);
 
 	      if (!REG_P (dreg))
 		continue;
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/ifcvt.c	2014-06-14 20:08:33.447584135 +0100
@@ -4279,22 +4279,16 @@ dead_or_predicable (basic_block test_bb,
 	      FOR_BB_INSNS_REVERSE (new_dest, insn)
 		if (NONDEBUG_INSN_P (insn))
 		  {
-		    df_ref *def_rec;
-		    unsigned int uid = INSN_UID (insn);
+		    df_ref def;
 
-		    /* If this insn sets any reg in return_regs..  */
-		    for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-		      {
-			df_ref def = *def_rec;
-			unsigned r = DF_REF_REGNO (def);
-
-			if (bitmap_bit_p (return_regs, r))
+		    /* If this insn sets any reg in return_regs, add all
+		       reg uses to the set of regs we're interested in.  */
+		    FOR_EACH_INSN_DEF (def, insn)
+		      if (bitmap_bit_p (return_regs, DF_REF_REGNO (def)))
+			{
+			  df_simulate_uses (insn, return_regs);
 			  break;
-		      }
-		    /* ..then add all reg uses to the set of regs
-		       we're interested in.  */
-		    if (*def_rec)
-		      df_simulate_uses (insn, return_regs);
+			}
 		  }
 	      if (bitmap_intersect_p (merge_set, return_regs))
 		{
Index: gcc/init-regs.c
===================================================================
--- gcc/init-regs.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/init-regs.c	2014-06-14 20:08:33.449584153 +0100
@@ -68,14 +68,12 @@ initialize_uninitialized_regs (void)
 
       FOR_BB_INSNS (bb, insn)
 	{
-	  unsigned int uid = INSN_UID (insn);
-	  df_ref *use_rec;
+	  df_ref use;
 	  if (!NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+	  FOR_EACH_INSN_USE (use, insn)
 	    {
-	      df_ref use = *use_rec;
 	      unsigned int regno = DF_REF_REGNO (use);
 
 	      /* Only do this for the pseudos.  */
@@ -109,7 +107,8 @@ initialize_uninitialized_regs (void)
 		  if (dump_file)
 		    fprintf (dump_file,
 			     "adding initialization in %s of reg %d at in block %d for insn %d.\n",
-			     current_function_name (), regno, bb->index, uid);
+			     current_function_name (), regno, bb->index,
+			     INSN_UID (insn));
 		}
 	    }
 	}
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/ira-lives.c	2014-06-14 20:08:33.444584106 +0100
@@ -725,13 +725,13 @@ make_early_clobber_and_input_conflicts (
 static bool
 mark_hard_reg_early_clobbers (rtx insn, bool live_p)
 {
-  df_ref *def_rec;
+  df_ref def;
   bool set_p = false;
 
-  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-    if (DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MUST_CLOBBER))
+  FOR_EACH_INSN_DEF (def, insn)
+    if (DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER))
       {
-	rtx dreg = DF_REF_REG (*def_rec);
+	rtx dreg = DF_REF_REG (def);
 
 	if (GET_CODE (dreg) == SUBREG)
 	  dreg = SUBREG_REG (dreg);
@@ -742,9 +742,9 @@ mark_hard_reg_early_clobbers (rtx insn,
 	   because there is no way to say that non-operand hard
 	   register clobbers are not early ones.  */
 	if (live_p)
-	  mark_ref_live (*def_rec);
+	  mark_ref_live (def);
 	else
-	  mark_ref_dead (*def_rec);
+	  mark_ref_dead (def);
 	set_p = true;
       }
 
@@ -1114,7 +1114,7 @@ process_bb_node_lives (ira_loop_tree_nod
 	 pessimistic, but it probably doesn't matter much in practice.  */
       FOR_BB_INSNS_REVERSE (bb, insn)
 	{
-	  df_ref *def_rec, *use_rec;
+	  df_ref def, use;
 	  bool call_p;
 
 	  if (!NONDEBUG_INSN_P (insn))
@@ -1135,9 +1135,9 @@ process_bb_node_lives (ira_loop_tree_nod
 	     live would stop us from allocating it to a call-crossing
 	     allocno.  */
 	  call_p = CALL_P (insn);
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    if (!call_p || !DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MAY_CLOBBER))
-	      mark_ref_live (*def_rec);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    if (!call_p || !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
+	      mark_ref_live (def);
 
 	  /* If INSN has multiple outputs, then any value used in one
 	     of the outputs conflicts with the other outputs.  Model this
@@ -1151,12 +1151,12 @@ process_bb_node_lives (ira_loop_tree_nod
 	     to the same hard register as an unused output we could
 	     set the hard register before the output reload insn.  */
 	  if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn))
-	    for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+	    FOR_EACH_INSN_USE (use, insn)
 	      {
 		int i;
 		rtx reg;
 
-		reg = DF_REF_REG (*use_rec);
+		reg = DF_REF_REG (use);
 		for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
 		  {
 		    rtx set;
@@ -1167,7 +1167,7 @@ process_bb_node_lives (ira_loop_tree_nod
 		      {
 			/* After the previous loop, this is a no-op if
 			   REG is contained within SET_DEST (SET).  */
-			mark_ref_live (*use_rec);
+			mark_ref_live (use);
 			break;
 		      }
 		  }
@@ -1178,9 +1178,9 @@ process_bb_node_lives (ira_loop_tree_nod
 	  process_single_reg_class_operands (false, freq);
 
 	  /* See which defined values die here.  */
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    if (!call_p || !DF_REF_FLAGS_IS_SET (*def_rec, DF_REF_MAY_CLOBBER))
-	      mark_ref_dead (*def_rec);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    if (!call_p || !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
+	      mark_ref_dead (def);
 
 	  if (call_p)
 	    {
@@ -1249,8 +1249,8 @@ process_bb_node_lives (ira_loop_tree_nod
 	  curr_point++;
 
 	  /* Mark each used value as live.  */
-	  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
-	    mark_ref_live (*use_rec);
+	  FOR_EACH_INSN_USE (use, insn)
+	    mark_ref_live (use);
 
 	  process_single_reg_class_operands (true, freq);
 
@@ -1263,16 +1263,16 @@ process_bb_node_lives (ira_loop_tree_nod
 	      /* Mark each hard reg as live again.  For example, a
 		 hard register can be in clobber and in an insn
 		 input.  */
-	      for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+	      FOR_EACH_INSN_USE (use, insn)
 		{
-		  rtx ureg = DF_REF_REG (*use_rec);
+		  rtx ureg = DF_REF_REG (use);
 
 		  if (GET_CODE (ureg) == SUBREG)
 		    ureg = SUBREG_REG (ureg);
 		  if (! REG_P (ureg) || REGNO (ureg) >= FIRST_PSEUDO_REGISTER)
 		    continue;
 
-		  mark_ref_live (*use_rec);
+		  mark_ref_live (use);
 		}
 	    }
 
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/ira.c	2014-06-14 20:09:16.532982828 +0100
@@ -2251,12 +2251,11 @@ compute_regs_asm_clobbered (void)
       rtx insn;
       FOR_BB_INSNS_REVERSE (bb, insn)
 	{
-	  df_ref *def_rec;
+	  df_ref def;
 
 	  if (insn_contains_asm (insn))
-	    for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	    FOR_EACH_INSN_DEF (def, insn)
 	      {
-		df_ref def = *def_rec;
 		unsigned int dregno = DF_REF_REGNO (def);
 		if (HARD_REGISTER_NUM_P (dregno))
 		  add_to_hard_reg_set (&crtl->asm_clobbers,
@@ -4041,9 +4040,8 @@ build_insn_chain (void)
 	{
 	  if (!NOTE_P (insn) && !BARRIER_P (insn))
 	    {
-	      unsigned int uid = INSN_UID (insn);
-	      df_ref *def_rec;
-	      df_ref *use_rec;
+	      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+	      df_ref def, use;
 
 	      c = new_insn_chain ();
 	      c->next = next;
@@ -4055,9 +4053,8 @@ build_insn_chain (void)
 	      c->block = bb->index;
 
 	      if (NONDEBUG_INSN_P (insn))
-		for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+		FOR_EACH_INSN_INFO_DEF (def, insn_info)
 		  {
-		    df_ref def = *def_rec;
 		    unsigned int regno = DF_REF_REGNO (def);
 
 		    /* Ignore may clobbers because these are generated
@@ -4146,9 +4143,8 @@ build_insn_chain (void)
 	      bitmap_copy (&c->live_throughout, live_relevant_regs);
 
 	      if (NONDEBUG_INSN_P (insn))
-		for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+		FOR_EACH_INSN_INFO_USE (use, insn_info)
 		  {
-		    df_ref use = *use_rec;
 		    unsigned int regno = DF_REF_REGNO (use);
 		    rtx reg = DF_REF_REG (use);
 
@@ -4440,12 +4436,14 @@ find_moveable_pseudos (void)
       FOR_BB_INSNS (bb, insn)
 	if (NONDEBUG_INSN_P (insn))
 	  {
+	    df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
 	    df_ref *u_rec, *d_rec;
+	    df_ref def, use;
 
 	    uid_luid[INSN_UID (insn)] = i++;
 	    
-	    u_rec = DF_INSN_USES (insn);
-	    d_rec = DF_INSN_DEFS (insn);
+	    u_rec = DF_INSN_INFO_USES (insn_info);
+	    d_rec = DF_INSN_INFO_DEFS (insn_info);
 	    if (d_rec[0] != NULL && d_rec[1] == NULL
 		&& u_rec[0] != NULL && u_rec[1] == NULL
 		&& DF_REF_REGNO (*u_rec) == DF_REF_REGNO (*d_rec)
@@ -4459,22 +4457,20 @@ find_moveable_pseudos (void)
 		bitmap_clear_bit (transp, regno);
 		continue;
 	      }
-	    while (*u_rec)
+	    FOR_EACH_INSN_INFO_USE (use, insn_info)
 	      {
-		unsigned regno = DF_REF_REGNO (*u_rec);
+		unsigned regno = DF_REF_REGNO (use);
 		bitmap_set_bit (&used, regno);
 		if (bitmap_clear_bit (moveable, regno))
 		  bitmap_clear_bit (transp, regno);
-		u_rec++;
 	      }
 
-	    while (*d_rec)
+	    FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	      {
-		unsigned regno = DF_REF_REGNO (*d_rec);
+		unsigned regno = DF_REF_REGNO (def);
 		bitmap_set_bit (&set, regno);
 		bitmap_clear_bit (transp, regno);
 		bitmap_clear_bit (moveable, regno);
-		d_rec++;
 	      }
 	  }
     }
@@ -4612,7 +4608,7 @@ find_moveable_pseudos (void)
       bitmap def_bb_transp = bb_transp_live + def_block->index;
       bool local_to_bb_p = bitmap_bit_p (def_bb_local, i);
       rtx use_insn = closest_uses[i];
-      df_ref *def_insn_use_rec = DF_INSN_USES (def_insn);
+      df_ref use;
       bool all_ok = true;
       bool all_transp = true;
 
@@ -4643,9 +4639,8 @@ find_moveable_pseudos (void)
       if (dump_file)
 	fprintf (dump_file, "Examining insn %d, def for %d\n",
 		 INSN_UID (def_insn), i);
-      while (*def_insn_use_rec != NULL)
+      FOR_EACH_INSN_USE (use, def_insn)
 	{
-	  df_ref use = *def_insn_use_rec;
 	  unsigned regno = DF_REF_REGNO (use);
 	  if (bitmap_bit_p (&unusable_as_input, regno))
 	    {
@@ -4688,8 +4683,6 @@ find_moveable_pseudos (void)
 	      else
 		all_transp = false;
 	    }
-
-	  def_insn_use_rec++;
 	}
       if (!all_ok)
 	continue;
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/loop-invariant.c	2014-06-14 20:08:33.450584163 +0100
@@ -826,14 +826,14 @@ check_dependency (basic_block bb, df_ref
 check_dependencies (rtx insn, bitmap depends_on)
 {
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-  df_ref *use_rec;
+  df_ref use;
   basic_block bb = BLOCK_FOR_INSN (insn);
 
-  for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
-    if (!check_dependency (bb, *use_rec, depends_on))
+  FOR_EACH_INSN_INFO_USE (use, insn_info)
+    if (!check_dependency (bb, use, depends_on))
       return false;
-  for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
-    if (!check_dependency (bb, *use_rec, depends_on))
+  FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+    if (!check_dependency (bb, use, depends_on))
       return false;
 
   return true;
@@ -909,19 +909,17 @@ find_invariant_insn (rtx insn, bool alwa
 record_uses (rtx insn)
 {
   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-  df_ref *use_rec;
+  df_ref use;
   struct invariant *inv;
 
-  for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
+  FOR_EACH_INSN_INFO_USE (use, insn_info)
     {
-      df_ref use = *use_rec;
       inv = invariant_for_use (use);
       if (inv)
 	record_use (inv->def, use);
     }
-  for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
+  FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
     {
-      df_ref use = *use_rec;
       inv = invariant_for_use (use);
       if (inv)
 	record_use (inv->def, use);
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/recog.c	2014-06-14 20:08:33.445584116 +0100
@@ -3024,7 +3024,7 @@ peep2_find_free_register (int from, int
 {
   enum reg_class cl;
   HARD_REG_SET live;
-  df_ref *def_rec;
+  df_ref def;
   int i;
 
   gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
@@ -3041,9 +3041,8 @@ peep2_find_free_register (int from, int
       gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
 
       /* Don't use registers set or clobbered by the insn.  */
-      for (def_rec = DF_INSN_DEFS (peep2_insn_data[from].insn);
-	   *def_rec; def_rec++)
-	SET_HARD_REG_BIT (live, DF_REF_REGNO (*def_rec));
+      FOR_EACH_INSN_DEF (def, peep2_insn_data[from].insn)
+	SET_HARD_REG_BIT (live, DF_REF_REGNO (def));
 
       from = peep2_buf_position (from + 1);
     }
Index: gcc/ree.c
===================================================================
--- gcc/ree.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/ree.c	2014-06-14 20:08:33.445584116 +0100
@@ -431,23 +431,20 @@ transform_ifelse (ext_cand *cand, rtx de
 static struct df_link *
 get_defs (rtx insn, rtx reg, vec<rtx> *dest)
 {
-  df_ref reg_info, *uses;
+  df_ref use;
   struct df_link *ref_chain, *ref_link;
 
-  reg_info = NULL;
-
-  for (uses = DF_INSN_USES (insn); *uses; uses++)
+  FOR_EACH_INSN_USE (use, insn)
     {
-      reg_info = *uses;
-      if (GET_CODE (DF_REF_REG (reg_info)) == SUBREG)
+      if (GET_CODE (DF_REF_REG (use)) == SUBREG)
         return NULL;
-      if (REGNO (DF_REF_REG (reg_info)) == REGNO (reg))
-        break;
+      if (REGNO (DF_REF_REG (use)) == REGNO (reg))
+	break;
     }
 
-  gcc_assert (reg_info != NULL && uses != NULL);
+  gcc_assert (use != NULL);
 
-  ref_chain = DF_REF_CHAIN (reg_info);
+  ref_chain = DF_REF_CHAIN (use);
 
   for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
     {
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/regstat.c	2014-06-14 20:08:33.449584153 +0100
@@ -124,6 +124,7 @@ regstat_bb_compute_ri (unsigned int bb_i
   rtx insn;
   df_ref *def_rec;
   df_ref *use_rec;
+  df_ref def, use;
   int luid = 0;
   bitmap_iterator bi;
   unsigned int regno;
@@ -158,7 +159,7 @@ regstat_bb_compute_ri (unsigned int bb_i
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
+      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       bitmap_iterator bi;
       struct df_mw_hardreg **mws_rec;
       rtx link;
@@ -209,7 +210,7 @@ regstat_bb_compute_ri (unsigned int bb_i
       /* We only care about real sets for calls.  Clobbers cannot
 	 be depended on.
 	 Only do this if the value is totally dead.  */
-      for (mws_rec = DF_INSN_UID_MWS (uid); *mws_rec; mws_rec++)
+      for (mws_rec = DF_INSN_INFO_MWS (insn_info); *mws_rec; mws_rec++)
 	{
 	  struct df_mw_hardreg *mws = *mws_rec;
 	  if (DF_MWS_REG_DEF_P (mws))
@@ -235,9 +236,8 @@ regstat_bb_compute_ri (unsigned int bb_i
 
       /* All of the defs except the return value are some sort of
 	 clobber.  This code is for the return.  */
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	{
-	  df_ref def = *def_rec;
 	  if ((!CALL_P (insn))
 	      || (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
 	    {
@@ -301,9 +301,8 @@ regstat_bb_compute_ri (unsigned int bb_i
 	    }
 	}
 
-      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
 	{
-	  df_ref use = *use_rec;
 	  unsigned int uregno = DF_REF_REGNO (use);
 
 	  if (uregno >= FIRST_PSEUDO_REGISTER)
@@ -444,6 +443,7 @@ regstat_bb_compute_calls_crossed (unsign
   rtx insn;
   df_ref *def_rec;
   df_ref *use_rec;
+  df_ref def, use;
 
   bitmap_copy (live, df_get_live_out (bb));
 
@@ -465,7 +465,7 @@ regstat_bb_compute_calls_crossed (unsign
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
+      struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       unsigned int regno;
 
       if (!INSN_P (insn))
@@ -486,9 +486,8 @@ regstat_bb_compute_calls_crossed (unsign
 
       /* All of the defs except the return value are some sort of
 	 clobber.  This code is for the return.  */
-      for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	{
-	  df_ref def = *def_rec;
 	  if ((!CALL_P (insn))
 	      || (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
 	    {
@@ -498,11 +497,8 @@ regstat_bb_compute_calls_crossed (unsign
 	    }
 	}
 
-      for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	{
-	  df_ref use = *use_rec;
-	  bitmap_set_bit (live, DF_REF_REGNO (use));
-	}
+      FOR_EACH_INSN_INFO_USE (use, insn_info)
+	bitmap_set_bit (live, DF_REF_REGNO (use));
     }
 }
 
Index: gcc/sched-deps.c
===================================================================
--- gcc/sched-deps.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/sched-deps.c	2014-06-14 20:08:33.446584126 +0100
@@ -4725,7 +4725,7 @@ find_inc (struct mem_inc_info *mii, bool
       if (parse_add_or_inc (mii, inc_cand, backwards))
 	{
 	  struct dep_replacement *desc;
-	  df_ref *def_rec;
+	  df_ref def;
 	  rtx newaddr, newmem;
 
 	  if (sched_verbose >= 5)
@@ -4734,18 +4734,15 @@ find_inc (struct mem_inc_info *mii, bool
 
 	  /* Need to assure that none of the operands of the inc
 	     instruction are assigned to by the mem insn.  */
-	  for (def_rec = DF_INSN_DEFS (mii->mem_insn); *def_rec; def_rec++)
-	    {
-	      df_ref def = *def_rec;
-	      if (reg_overlap_mentioned_p (DF_REF_REG (def), mii->inc_input)
-		  || reg_overlap_mentioned_p (DF_REF_REG (def), mii->mem_reg0))
-		{
-		  if (sched_verbose >= 5)
-		    fprintf (sched_dump,
-			     "inc conflicts with store failure.\n");
-		  goto next;
-		}
-	    }
+	  FOR_EACH_INSN_DEF (def, mii->mem_insn)
+	    if (reg_overlap_mentioned_p (DF_REF_REG (def), mii->inc_input)
+		|| reg_overlap_mentioned_p (DF_REF_REG (def), mii->mem_reg0))
+	      {
+		if (sched_verbose >= 5)
+		  fprintf (sched_dump,
+			   "inc conflicts with store failure.\n");
+		goto next;
+	      }
 	  newaddr = mii->inc_input;
 	  if (mii->mem_index != NULL_RTX)
 	    newaddr = gen_rtx_PLUS (GET_MODE (newaddr), newaddr,
@@ -4820,22 +4817,19 @@ find_mem (struct mem_inc_info *mii, rtx
 	}
       if (REG_P (reg0))
 	{
-	  df_ref *def_rec;
+	  df_ref use;
 	  int occurrences = 0;
 
 	  /* Make sure this reg appears only once in this insn.  Can't use
 	     count_occurrences since that only works for pseudos.  */
-	  for (def_rec = DF_INSN_USES (mii->mem_insn); *def_rec; def_rec++)
-	    {
-	      df_ref def = *def_rec;
-	      if (reg_overlap_mentioned_p (reg0, DF_REF_REG (def)))
-		if (++occurrences > 1)
-		  {
-		    if (sched_verbose >= 5)
-		      fprintf (sched_dump, "mem count failure\n");
-		    return false;
-		  }
-	    }
+	  FOR_EACH_INSN_USE (use, mii->mem_insn)
+	    if (reg_overlap_mentioned_p (reg0, DF_REF_REG (use)))
+	      if (++occurrences > 1)
+		{
+		  if (sched_verbose >= 5)
+		    fprintf (sched_dump, "mem count failure\n");
+		  return false;
+		}
 
 	  mii->mem_reg0 = reg0;
 	  return find_inc (mii, true) || find_inc (mii, false);
Index: gcc/sel-sched-ir.c
===================================================================
--- gcc/sel-sched-ir.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/sel-sched-ir.c	2014-06-14 20:08:33.447584135 +0100
@@ -2613,8 +2613,7 @@ setup_id_lhs_rhs (idata_t id, insn_t ins
 maybe_downgrade_id_to_use (idata_t id, insn_t insn)
 {
   bool must_be_use = false;
-  unsigned uid = INSN_UID (insn);
-  df_ref *rec;
+  df_ref def;
   rtx lhs = IDATA_LHS (id);
   rtx rhs = IDATA_RHS (id);
 
@@ -2628,10 +2627,8 @@ maybe_downgrade_id_to_use (idata_t id, i
       return;
     }
 
-  for (rec = DF_INSN_UID_DEFS (uid); *rec; rec++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      df_ref def = *rec;
-
       if (DF_REF_INSN (def)
           && DF_REF_FLAGS_IS_SET (def, DF_REF_PRE_POST_MODIFY)
           && loc_mentioned_in_p (DF_REF_LOC (def), IDATA_RHS (id)))
@@ -2659,13 +2656,12 @@ maybe_downgrade_id_to_use (idata_t id, i
 static void
 setup_id_reg_sets (idata_t id, insn_t insn)
 {
-  unsigned uid = INSN_UID (insn);
-  df_ref *rec;
+  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+  df_ref def, use;
   regset tmp = get_clear_regset_from_pool ();
 
-  for (rec = DF_INSN_UID_DEFS (uid); *rec; rec++)
+  FOR_EACH_INSN_INFO_DEF (def, insn_info)
     {
-      df_ref def = *rec;
       unsigned int regno = DF_REF_REGNO (def);
 
       /* Post modifies are treated like clobbers by sched-deps.c.  */
@@ -2689,9 +2685,8 @@ setup_id_reg_sets (idata_t id, insn_t in
         bitmap_set_bit (tmp, regno);
     }
 
-  for (rec = DF_INSN_UID_USES (uid); *rec; rec++)
+  FOR_EACH_INSN_INFO_USE (use, insn_info)
     {
-      df_ref use = *rec;
       unsigned int regno = DF_REF_REGNO (use);
 
       /* When these refs are met for the first time, skip them, as
Index: gcc/shrink-wrap.c
===================================================================
--- gcc/shrink-wrap.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/shrink-wrap.c	2014-06-14 20:08:33.446584126 +0100
@@ -64,7 +64,7 @@ Software Foundation; either version 3, o
 requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used,
 			HARD_REG_SET set_up_by_prologue)
 {
-  df_ref *df_rec;
+  df_ref def, use;
   HARD_REG_SET hardregs;
   unsigned regno;
 
@@ -76,9 +76,9 @@ requires_stack_frame_p (rtx insn, HARD_R
     return true;
 
   CLEAR_HARD_REG_SET (hardregs);
-  for (df_rec = DF_INSN_DEFS (insn); *df_rec; df_rec++)
+  FOR_EACH_INSN_DEF (def, insn)
     {
-      rtx dreg = DF_REF_REG (*df_rec);
+      rtx dreg = DF_REF_REG (def);
 
       if (!REG_P (dreg))
 	continue;
@@ -94,9 +94,9 @@ requires_stack_frame_p (rtx insn, HARD_R
 	&& df_regs_ever_live_p (regno))
       return true;
 
-  for (df_rec = DF_INSN_USES (insn); *df_rec; df_rec++)
+  FOR_EACH_INSN_USE (use, insn)
     {
-      rtx reg = DF_REF_REG (*df_rec);
+      rtx reg = DF_REF_REG (use);
 
       if (!REG_P (reg))
 	continue;
@@ -333,7 +333,7 @@ prepare_shrink_wrap (basic_block entry_b
 {
   rtx insn, curr, x;
   HARD_REG_SET uses, defs;
-  df_ref *ref;
+  df_ref def, use;
   bool split_p = false;
 
   if (JUMP_P (BB_END (entry_block)))
@@ -353,17 +353,17 @@ prepare_shrink_wrap (basic_block entry_b
 				       &split_p))
       {
 	/* Add all defined registers to DEFs.  */
-	for (ref = DF_INSN_DEFS (insn); *ref; ref++)
+	FOR_EACH_INSN_DEF (def, insn)
 	  {
-	    x = DF_REF_REG (*ref);
+	    x = DF_REF_REG (def);
 	    if (REG_P (x) && HARD_REGISTER_P (x))
 	      SET_HARD_REG_BIT (defs, REGNO (x));
 	  }
 
 	/* Add all used registers to USESs.  */
-	for (ref = DF_INSN_USES (insn); *ref; ref++)
+	FOR_EACH_INSN_USE (use, insn)
 	  {
-	    x = DF_REF_REG (*ref);
+	    x = DF_REF_REG (use);
 	    if (REG_P (x) && HARD_REGISTER_P (x))
 	      SET_HARD_REG_BIT (uses, REGNO (x));
 	  }
Index: gcc/store-motion.c
===================================================================
--- gcc/store-motion.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/store-motion.c	2014-06-14 20:08:33.446584126 +0100
@@ -645,7 +645,7 @@ compute_store_table (void)
   unsigned regno;
 #endif
   rtx insn, tmp;
-  df_ref *def_rec;
+  df_ref def;
   int *last_set_in, *already_set;
   struct st_expr * ptr, **prev_next_ptr_ptr;
   unsigned int max_gcse_regno = max_reg_num ();
@@ -665,8 +665,8 @@ compute_store_table (void)
 	  if (! NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    last_set_in[DF_REF_REGNO (*def_rec)] = INSN_UID (insn);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    last_set_in[DF_REF_REGNO (def)] = INSN_UID (insn);
 	}
 
       /* Now find the stores.  */
@@ -676,16 +676,16 @@ compute_store_table (void)
 	  if (! NONDEBUG_INSN_P (insn))
 	    continue;
 
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    already_set[DF_REF_REGNO (*def_rec)] = INSN_UID (insn);
+	  FOR_EACH_INSN_DEF (def, insn)
+	    already_set[DF_REF_REGNO (def)] = INSN_UID (insn);
 
 	  /* Now that we've marked regs, look for stores.  */
 	  find_moveable_store (insn, already_set, last_set_in);
 
 	  /* Unmark regs that are no longer set.  */
-	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-	    if (last_set_in[DF_REF_REGNO (*def_rec)] == INSN_UID (insn))
-	      last_set_in[DF_REF_REGNO (*def_rec)] = 0;
+	  FOR_EACH_INSN_DEF (def, insn)
+	    if (last_set_in[DF_REF_REGNO (def)] == INSN_UID (insn))
+	      last_set_in[DF_REF_REGNO (def)] = 0;
 	}
 
 #ifdef ENABLE_CHECKING
@@ -1068,12 +1068,12 @@ build_store_vectors (void)
       FOR_BB_INSNS (bb, insn)
 	if (NONDEBUG_INSN_P (insn))
 	  {
-	    df_ref *def_rec;
-	    for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	    df_ref def;
+	    FOR_EACH_INSN_DEF (def, insn)
 	      {
-		unsigned int ref_regno = DF_REF_REGNO (*def_rec);
+		unsigned int ref_regno = DF_REF_REGNO (def);
 		if (ref_regno < max_gcse_regno)
-		  regs_set_in_block[DF_REF_REGNO (*def_rec)] = 1;
+		  regs_set_in_block[DF_REF_REGNO (def)] = 1;
 	      }
 	  }
 
Index: gcc/web.c
===================================================================
--- gcc/web.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/web.c	2014-06-14 20:08:33.448584144 +0100
@@ -173,51 +173,34 @@ union_defs (df_ref use, struct web_entry
 {
   struct df_insn_info *insn_info = DF_REF_INSN_INFO (use);
   struct df_link *link = DF_REF_CHAIN (use);
-  df_ref *eq_use_link;
-  df_ref *def_link;
   rtx set;
 
   if (insn_info)
     {
-      rtx insn = insn_info->insn;
-      eq_use_link = DF_INSN_INFO_EQ_USES (insn_info);
-      def_link = DF_INSN_INFO_DEFS (insn_info);
-      set = single_set (insn);
+      df_ref eq_use;
+
+      set = single_set (insn_info->insn);
+      FOR_EACH_INSN_INFO_EQ_USE (eq_use, insn_info)
+	if (use != eq_use
+	    && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (eq_use))
+	  (*fun) (use_entry + DF_REF_ID (use), use_entry + DF_REF_ID (eq_use));
     }
   else
-    {
-      /* An artificial use.  It links up with nothing.  */
-      eq_use_link = NULL;
-      def_link = NULL;
-      set = NULL;
-    }
+    set = NULL;
 
   /* Union all occurrences of the same register in reg notes.  */
 
-  if (eq_use_link)
-    while (*eq_use_link)
-      {
-	if (use != *eq_use_link
-	    && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*eq_use_link))
-	  (*fun) (use_entry + DF_REF_ID (use),
-		  use_entry + DF_REF_ID (*eq_use_link));
-	eq_use_link++;
-    }
-
   /* Recognize trivial noop moves and attempt to keep them as noop.  */
 
   if (set
       && SET_SRC (set) == DF_REF_REG (use)
       && SET_SRC (set) == SET_DEST (set))
     {
-      if (def_link)
-	while (*def_link)
-	  {
-	    if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (*def_link))
-	      (*fun) (use_entry + DF_REF_ID (use),
-		      def_entry + DF_REF_ID (*def_link));
-	    def_link++;
-	  }
+      df_ref def;
+
+      FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def))
+	  (*fun) (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (def));
     }
 
   /* UD chains of uninitialized REGs are empty.  Keeping all uses of
@@ -248,23 +231,14 @@ union_defs (df_ref use, struct web_entry
   /* A READ_WRITE use requires the corresponding def to be in the same
      register.  Find it and union.  */
   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
-    {
-      df_ref *link;
-
-      if (insn_info)
-	link = DF_INSN_INFO_DEFS (insn_info);
-      else
-	link = NULL;
+    if (insn_info)
+      {
+	df_ref def;
 
-      if (link)
-	while (*link)
-	  {
-	    if (DF_REF_REAL_REG (*link) == DF_REF_REAL_REG (use))
-	      (*fun) (use_entry + DF_REF_ID (use),
-		      def_entry + DF_REF_ID (*link));
-	    link++;
-	  }
-    }
+	FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	  if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def))
+	    (*fun) (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (def));
+      }
 }
 
 /* Find the corresponding register for the given entry.  */
@@ -375,22 +349,16 @@ pass_web::execute (function *fun)
   FOR_ALL_BB_FN (bb, fun)
     FOR_BB_INSNS (bb, insn)
     {
-      unsigned int uid = INSN_UID (insn);
       if (NONDEBUG_INSN_P (insn))
 	{
-	  df_ref *use_rec;
-	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		DF_REF_ID (use) = uses_num++;
-	    }
-	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		DF_REF_ID (use) = uses_num++;
-	    }
+	  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+	  df_ref use;
+	  FOR_EACH_INSN_INFO_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      DF_REF_ID (use) = uses_num++;
+	  FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      DF_REF_ID (use) = uses_num++;
 	}
     }
 
@@ -402,34 +370,23 @@ pass_web::execute (function *fun)
   /* Produce the web.  */
   FOR_ALL_BB_FN (bb, fun)
     FOR_BB_INSNS (bb, insn)
-    {
-      unsigned int uid = INSN_UID (insn);
       if (NONDEBUG_INSN_P (insn))
 	{
-	  df_ref *use_rec;
+	  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+	  df_ref use;
 	  union_match_dups (insn, def_entry, use_entry, unionfind_union);
-	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		union_defs (use, def_entry, used, use_entry, unionfind_union);
-	    }
-	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		union_defs (use, def_entry, used, use_entry, unionfind_union);
-	    }
+	  FOR_EACH_INSN_INFO_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      union_defs (use, def_entry, used, use_entry, unionfind_union);
+	  FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      union_defs (use, def_entry, used, use_entry, unionfind_union);
 	}
-    }
 
   /* Update the instruction stream, allocating new registers for split pseudos
      in progress.  */
   FOR_ALL_BB_FN (bb, fun)
     FOR_BB_INSNS (bb, insn)
-    {
-      unsigned int uid = INSN_UID (insn);
-
       if (NONDEBUG_INSN_P (insn)
 	  /* Ignore naked clobber.  For example, reg 134 in the second insn
 	     of the following sequence will not be replaced.
@@ -441,28 +398,21 @@ pass_web::execute (function *fun)
 	     Thus the later passes can optimize them away.  */
 	  && GET_CODE (PATTERN (insn)) != CLOBBER)
 	{
-	  df_ref *use_rec;
-	  df_ref *def_rec;
-	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
-	    }
-	  for (use_rec = DF_INSN_UID_EQ_USES (uid); *use_rec; use_rec++)
-	    {
-	      df_ref use = *use_rec;
-	      if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
-		replace_ref (use, entry_register (use_entry + DF_REF_ID (use), use, used));
-	    }
-	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
-	    {
-	      df_ref def = *def_rec;
-	      if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
-		replace_ref (def, entry_register (def_entry + DF_REF_ID (def), def, used));
-	    }
+	  struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+	  df_ref def, use;
+	  FOR_EACH_INSN_INFO_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      replace_ref (use, entry_register (use_entry + DF_REF_ID (use),
+						use, used));
+	  FOR_EACH_INSN_INFO_EQ_USE (use, insn_info)
+	    if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER)
+	      replace_ref (use, entry_register (use_entry + DF_REF_ID (use),
+						use, used));
+	  FOR_EACH_INSN_INFO_DEF (def, insn_info)
+	    if (DF_REF_REGNO (def) >= FIRST_PSEUDO_REGISTER)
+	      replace_ref (def, entry_register (def_entry + DF_REF_ID (def),
+						def, used));
 	}
-    }
 
   free (def_entry);
   free (use_entry);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2014-06-14 20:08:31.421565177 +0100
+++ gcc/config/i386/i386.c	2014-06-14 20:08:33.440584069 +0100
@@ -17764,8 +17764,7 @@ #define LEA_SEARCH_THRESHOLD (LEA_MAX_ST
 static unsigned int
 increase_distance (rtx prev, rtx next, unsigned int distance)
 {
-  df_ref *use_rec;
-  df_ref *def_rec;
+  df_ref def, use;
 
   if (!prev || !next)
     return distance + (distance & 1) + 2;
@@ -17773,10 +17772,10 @@ increase_distance (rtx prev, rtx next, u
   if (!DF_INSN_USES (next) || !DF_INSN_DEFS (prev))
     return distance + 1;
 
-  for (use_rec = DF_INSN_USES (next); *use_rec; use_rec++)
-    for (def_rec = DF_INSN_DEFS (prev); *def_rec; def_rec++)
-      if (!DF_REF_IS_ARTIFICIAL (*def_rec)
-	  && DF_REF_REGNO (*use_rec) == DF_REF_REGNO (*def_rec))
+  FOR_EACH_INSN_USE (use, next)
+    FOR_EACH_INSN_DEF (def, prev)
+      if (!DF_REF_IS_ARTIFICIAL (def)
+	  && DF_REF_REGNO (use) == DF_REF_REGNO (def))
 	return distance + (distance & 1) + 2;
 
   return distance + 1;
@@ -17789,16 +17788,14 @@ increase_distance (rtx prev, rtx next, u
 insn_defines_reg (unsigned int regno1, unsigned int regno2,
 		  rtx insn)
 {
-  df_ref *def_rec;
+  df_ref def;
 
-  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
-    if (DF_REF_REG_DEF_P (*def_rec)
-	&& !DF_REF_IS_ARTIFICIAL (*def_rec)
-	&& (regno1 == DF_REF_REGNO (*def_rec)
-	    || regno2 == DF_REF_REGNO (*def_rec)))
-      {
-	return true;
-      }
+  FOR_EACH_INSN_DEF (def, insn)
+    if (DF_REF_REG_DEF_P (def)
+	&& !DF_REF_IS_ARTIFICIAL (def)
+	&& (regno1 == DF_REF_REGNO (def)
+	    || regno2 == DF_REF_REGNO (def)))
+      return true;
 
   return false;
 }
@@ -17809,10 +17806,10 @@ insn_defines_reg (unsigned int regno1, u
 static bool
 insn_uses_reg_mem (unsigned int regno, rtx insn)
 {
-  df_ref *use_rec;
+  df_ref use;
 
-  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
-    if (DF_REF_REG_MEM_P (*use_rec) && regno == DF_REF_REGNO (*use_rec))
+  FOR_EACH_INSN_USE (use, insn)
+    if (DF_REF_REG_MEM_P (use) && regno == DF_REF_REGNO (use))
       return true;
 
   return false;
@@ -18144,15 +18141,15 @@ ix86_lea_outperforms (rtx insn, unsigned
 ix86_ok_to_clobber_flags (rtx insn)
 {
   basic_block bb = BLOCK_FOR_INSN (insn);
-  df_ref *use;
+  df_ref use;
   bitmap live;
 
   while (insn)
     {
       if (NONDEBUG_INSN_P (insn))
 	{
-	  for (use = DF_INSN_USES (insn); *use; use++)
-	    if (DF_REF_REG_USE_P (*use) && DF_REF_REGNO (*use) == FLAGS_REG)
+	  FOR_EACH_INSN_USE (use, insn)
+	    if (DF_REF_REG_USE_P (use) && DF_REF_REGNO (use) == FLAGS_REG)
 	      return false;
 
 	  if (insn_defines_reg (FLAGS_REG, INVALID_REGNUM, insn))

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE}
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
@ 2014-06-14 19:44 ` Richard Sandiford
  2014-06-14 20:11   ` Steven Bosscher
  2014-06-14 19:48 ` [PATCH 5/6] Remove dead code Richard Sandiford
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:44 UTC (permalink / raw)
  To: gcc-patches

Similar to patch 1, but for artificial uses and defs.

Richard


gcc/
	* df.h (FOR_EACH_ARTIFICIAL_USE, FOR_EACH_ARTIFICIAL_DEF): New macros.
	* cse.c (cse_extended_basic_block): Use them.
	* dce.c (mark_artificial_use): Likewise.
	* df-problems.c (df_rd_simulate_artificial_defs_at_top): Likewise.
	(df_lr_bb_local_compute, df_live_bb_local_compute): Likewise.
	(df_chain_remove_problem, df_chain_bb_dump): Likewise.
	(df_word_lr_bb_local_compute, df_note_bb_compute): Likewise.
	(df_simulate_initialize_backwards): Likewise.
	(df_simulate_finalize_backwards): Likewise.
	(df_simulate_initialize_forwards): Likewise.
	(df_md_simulate_artificial_defs_at_top): Likewise.
	* df-scan.c (df_reorganize_refs_by_reg_by_insn): Likewise.
	* regrename.c (init_rename_info): Likewise.
	* regstat.c (regstat_bb_compute_ri): Likewise.
	(regstat_bb_compute_calls_crossed): Likewise.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-14 19:40:28.450704775 +0100
+++ gcc/df.h	2014-06-14 20:01:12.353400410 +0100
@@ -775,6 +775,14 @@ #define FOR_EACH_INSN_USE(ITER, INSN) \
 #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##_)
+
+#define FOR_EACH_ARTIFICIAL_DEF(ITER, BB_INDEX) \
+  for (df_ref *ITER##_ = df_get_artificial_defs (BB_INDEX); \
+       (ITER = *ITER##_); ++ITER##_)
+
 /* An obstack for bitmap not related to specific dataflow problems.
    This obstack should e.g. be used for bitmaps with a short life time
    such as temporary bitmaps.  This obstack is declared in df-core.c.  */
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	2014-06-14 19:40:26.919671918 +0100
+++ gcc/cse.c	2014-06-14 20:01:12.351400390 +0100
@@ -6406,14 +6406,11 @@ cse_extended_basic_block (struct cse_bas
 	 edge pointing to that bb.  */
       if (bb_has_eh_pred (bb))
 	{
-	  df_ref *def_rec;
+	  df_ref def;
 
-	  for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
-	    {
-	      df_ref def = *def_rec;
-	      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-		invalidate (DF_REF_REG (def), GET_MODE (DF_REF_REG (def)));
-	    }
+	  FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
+	    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+	      invalidate (DF_REF_REG (def), GET_MODE (DF_REF_REG (def)));
 	}
 
       optimize_this_for_speed_p = optimize_bb_for_speed_p (bb);
Index: gcc/dce.c
===================================================================
--- gcc/dce.c	2014-06-14 19:40:44.451212858 +0100
+++ gcc/dce.c	2014-06-14 20:01:23.401510789 +0100
@@ -661,16 +661,13 @@ mark_artificial_uses (void)
 {
   basic_block bb;
   struct df_link *defs;
-  df_ref *use_rec;
+  df_ref use;
 
   FOR_ALL_BB_FN (bb, cfun)
-    {
-      for (use_rec = df_get_artificial_uses (bb->index);
-	   *use_rec; use_rec++)
-	for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next)
-	  if (! DF_REF_IS_ARTIFICIAL (defs->ref))
-	    mark_insn (DF_REF_INSN (defs->ref), false);
-    }
+    FOR_EACH_ARTIFICIAL_USE (use, bb->index)
+      for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
+	if (!DF_REF_IS_ARTIFICIAL (defs->ref))
+	  mark_insn (DF_REF_INSN (defs->ref), false);
 }
 
 
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2014-06-14 19:47:23.317957520 +0100
+++ gcc/df-problems.c	2014-06-14 20:01:12.352400400 +0100
@@ -245,20 +245,17 @@ df_rd_alloc (bitmap all_blocks)
 df_rd_simulate_artificial_defs_at_top (basic_block bb, bitmap local_rd)
 {
   int bb_index = bb->index;
-  df_ref *def_rec;
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	{
-	  unsigned int dregno = DF_REF_REGNO (def);
-	  if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
-	    bitmap_clear_range (local_rd,
-				DF_DEFS_BEGIN (dregno),
-				DF_DEFS_COUNT (dregno));
-	  bitmap_set_bit (local_rd, DF_REF_ID (def));
-	}
-    }
+  df_ref def;
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      {
+	unsigned int dregno = DF_REF_REGNO (def);
+	if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
+	  bitmap_clear_range (local_rd,
+			      DF_DEFS_BEGIN (dregno),
+			      DF_DEFS_COUNT (dregno));
+	bitmap_set_bit (local_rd, DF_REF_ID (def));
+      }
 }
 
 /* Add the effect of the defs of INSN to the reaching definitions bitmap
@@ -834,30 +831,22 @@ df_lr_bb_local_compute (unsigned int bb_
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   struct df_lr_bb_info *bb_info = df_lr_get_bb_info (bb_index);
   rtx insn;
-  df_ref *def_rec;
-  df_ref *use_rec;
   df_ref def, use;
 
   /* Process the registers set in an exception handler.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
-	{
-	  unsigned int dregno = DF_REF_REGNO (def);
-	  bitmap_set_bit (&bb_info->def, dregno);
-	  bitmap_clear_bit (&bb_info->use, dregno);
-	}
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+      {
+	unsigned int dregno = DF_REF_REGNO (def);
+	bitmap_set_bit (&bb_info->def, dregno);
+	bitmap_clear_bit (&bb_info->use, dregno);
+      }
 
   /* Process the hardware registers that are always live.  */
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      /* Add use to set of uses in this BB.  */
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
-    }
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    /* Add use to set of uses in this BB.  */
+    if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+      bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
@@ -883,26 +872,20 @@ df_lr_bb_local_compute (unsigned int bb_
   /* Process the registers set in an exception handler or the hard
      frame pointer if this block is the target of a non local
      goto.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	{
-	  unsigned int dregno = DF_REF_REGNO (def);
-	  bitmap_set_bit (&bb_info->def, dregno);
-	  bitmap_clear_bit (&bb_info->use, dregno);
-	}
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      {
+	unsigned int dregno = DF_REF_REGNO (def);
+	bitmap_set_bit (&bb_info->def, dregno);
+	bitmap_clear_bit (&bb_info->use, dregno);
+      }
 
 #ifdef EH_USES
   /* Process the uses that are live into an exception handler.  */
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      /* Add use to set of uses in this BB.  */
-      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
-	bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
-    }
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    /* Add use to set of uses in this BB.  */
+    if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
+      bitmap_set_bit (&bb_info->use, DF_REF_REGNO (use));
 #endif
 
   /* If the df_live problem is not defined, such as at -O0 and -O1, we
@@ -1455,7 +1438,7 @@ df_live_bb_local_compute (unsigned int b
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   struct df_live_bb_info *bb_info = df_live_get_bb_info (bb_index);
   rtx insn;
-  df_ref def, *def_rec;
+  df_ref def;
   int luid = 0;
 
   FOR_BB_INSNS (bb, insn)
@@ -1494,11 +1477,8 @@ df_live_bb_local_compute (unsigned int b
 	}
     }
 
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      bitmap_set_bit (&bb_info->gen, DF_REF_REGNO (def));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    bitmap_set_bit (&bb_info->gen, DF_REF_REGNO (def));
 }
 
 
@@ -1974,17 +1954,15 @@ df_chain_remove_problem (void)
   EXECUTE_IF_SET_IN_BITMAP (df_chain->out_of_date_transfer_functions, 0, bb_index, bi)
     {
       rtx insn;
-      df_ref *def_rec;
-      df_ref *use_rec;
       df_ref def, use;
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
 
       if (df_chain_problem_p (DF_DU_CHAIN))
-	for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
-	  DF_REF_CHAIN (*def_rec) = NULL;
+	FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+	  DF_REF_CHAIN (def) = NULL;
       if (df_chain_problem_p (DF_UD_CHAIN))
-	for (use_rec = df_get_artificial_uses (bb->index); *use_rec; use_rec++)
-	  DF_REF_CHAIN (*use_rec) = NULL;
+	FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+	  DF_REF_CHAIN (use) = NULL;
 
       FOR_BB_INSNS (bb, insn)
 	if (INSN_P (insn))
@@ -2180,48 +2158,35 @@ df_chain_bb_dump (basic_block bb, FILE *
     return;
   if (df_chain_problem_p (DF_UD_CHAIN))
     {
+      df_ref use;
+
       fprintf (file,
 	       ";;  UD chains for artificial uses at %s\n",
 	       top ? "top" : "bottom");
-      df_ref *use_rec = df_get_artificial_uses (bb->index);
-      if (*use_rec)
-	{
-	  while (*use_rec)
-	    {
-	      df_ref use = *use_rec;
-	      if ((top && (DF_REF_FLAGS (use) & DF_REF_AT_TOP))
-		  || (!top && !(DF_REF_FLAGS (use) & DF_REF_AT_TOP)))
-		{
-		  fprintf (file, ";;   reg %d ", DF_REF_REGNO (use));
-		  df_chain_dump (DF_REF_CHAIN (use), file);
-		  fprintf (file, "\n");
-		}
-	      use_rec++;
-	    }
-	}
+      FOR_EACH_ARTIFICIAL_USE (use, bb->index)
+	if ((top && (DF_REF_FLAGS (use) & DF_REF_AT_TOP))
+	    || (!top && !(DF_REF_FLAGS (use) & DF_REF_AT_TOP)))
+	  {
+	    fprintf (file, ";;   reg %d ", DF_REF_REGNO (use));
+	    df_chain_dump (DF_REF_CHAIN (use), file);
+	    fprintf (file, "\n");
+	  }
     }
   if (df_chain_problem_p (DF_DU_CHAIN))
     {
+      df_ref def;
+
       fprintf (file,
 	       ";;  DU chains for artificial defs at %s\n",
 	       top ? "top" : "bottom");
-      df_ref *def_rec = df_get_artificial_defs (bb->index);
-      if (*def_rec)
-	{
-	  while (*def_rec)
-	    {
-	      df_ref def = *def_rec;
-
-	      if ((top && (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
-		  || (!top && !(DF_REF_FLAGS (def) & DF_REF_AT_TOP)))
-		{
-		  fprintf (file, ";;   reg %d ", DF_REF_REGNO (def));
-		  df_chain_dump (DF_REF_CHAIN (def), file);
-		  fprintf (file, "\n");
-		}
-	      def_rec++;
-	    }
-	}
+      FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
+	if ((top && (DF_REF_FLAGS (def) & DF_REF_AT_TOP))
+	    || (!top && !(DF_REF_FLAGS (def) & DF_REF_AT_TOP)))
+	  {
+	    fprintf (file, ";;   reg %d ", DF_REF_REGNO (def));
+	    df_chain_dump (DF_REF_CHAIN (def), file);
+	    fprintf (file, "\n");
+	  }
     }
 }
 
@@ -2503,22 +2468,14 @@ df_word_lr_bb_local_compute (unsigned in
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   struct df_word_lr_bb_info *bb_info = df_word_lr_get_bb_info (bb_index);
   rtx insn;
-  df_ref *def_rec;
-  df_ref *use_rec;
   df_ref def, use;
 
   /* Ensure that artificial refs don't contain references to pseudos.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      gcc_assert (DF_REF_REGNO (def) < FIRST_PSEUDO_REGISTER);
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    gcc_assert (DF_REF_REGNO (def) < FIRST_PSEUDO_REGISTER);
 
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      gcc_assert (DF_REF_REGNO (use) < FIRST_PSEUDO_REGISTER);
-    }
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    gcc_assert (DF_REF_REGNO (use) < FIRST_PSEUDO_REGISTER);
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
@@ -3112,8 +3069,6 @@ df_note_bb_compute (unsigned int bb_inde
 {
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   rtx insn;
-  df_ref *def_rec;
-  df_ref *use_rec;
   df_ref def, use;
   struct dead_debug_local debug;
 
@@ -3130,10 +3085,8 @@ df_note_bb_compute (unsigned int bb_inde
 
   /* Process the artificial defs and uses at the bottom of the block
      to begin processing.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
     {
-      df_ref def = *def_rec;
-
       if (REG_DEAD_DEBUGGING && dump_file)
 	fprintf (dump_file, "artificial def %d\n", DF_REF_REGNO (def));
 
@@ -3141,19 +3094,16 @@ df_note_bb_compute (unsigned int bb_inde
 	bitmap_clear_bit (live, DF_REF_REGNO (def));
     }
 
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	{
-	  unsigned int regno = DF_REF_REGNO (use);
-	  bitmap_set_bit (live, regno);
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+      {
+	unsigned int regno = DF_REF_REGNO (use);
+	bitmap_set_bit (live, regno);
 
-	  /* Notes are not generated for any of the artificial registers
-	     at the bottom of the block.  */
-	  bitmap_set_bit (artificial_uses, regno);
-	}
-    }
+	/* Notes are not generated for any of the artificial registers
+	   at the bottom of the block.  */
+	bitmap_set_bit (artificial_uses, regno);
+      }
 
   if (REG_DEAD_DEBUGGING && dump_file)
     {
@@ -3533,23 +3483,16 @@ df_simulate_fixup_sets (basic_block bb,
 void
 df_simulate_initialize_backwards (basic_block bb, bitmap live)
 {
-  df_ref *def_rec;
-  df_ref *use_rec;
+  df_ref def, use;
   int bb_index = bb->index;
 
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
-	bitmap_clear_bit (live, DF_REF_REGNO (def));
-    }
-
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	bitmap_set_bit (live, DF_REF_REGNO (use));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+      bitmap_clear_bit (live, DF_REF_REGNO (def));
+
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+      bitmap_set_bit (live, DF_REF_REGNO (use));
 }
 
 
@@ -3573,26 +3516,20 @@ df_simulate_one_insn_backwards (basic_bl
 void
 df_simulate_finalize_backwards (basic_block bb, bitmap live)
 {
-  df_ref *def_rec;
+  df_ref def;
 #ifdef EH_USES
-  df_ref *use_rec;
+  df_ref use;
 #endif
   int bb_index = bb->index;
 
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	bitmap_clear_bit (live, DF_REF_REGNO (def));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      bitmap_clear_bit (live, DF_REF_REGNO (def));
 
 #ifdef EH_USES
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
-	bitmap_set_bit (live, DF_REF_REGNO (use));
-    }
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    if (DF_REF_FLAGS (use) & DF_REF_AT_TOP)
+      bitmap_set_bit (live, DF_REF_REGNO (use));
 #endif
 }
 /*----------------------------------------------------------------------------
@@ -3614,15 +3551,12 @@ df_simulate_finalize_backwards (basic_bl
 void
 df_simulate_initialize_forwards (basic_block bb, bitmap live)
 {
-  df_ref *def_rec;
+  df_ref def;
   int bb_index = bb->index;
 
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	bitmap_set_bit (live, DF_REF_REGNO (def));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      bitmap_set_bit (live, DF_REF_REGNO (def));
 }
 
 /* Simulate the forwards effects of INSN on the bitmap LIVE.  */
@@ -4121,20 +4055,17 @@ df_md_alloc (bitmap all_blocks)
 df_md_simulate_artificial_defs_at_top (basic_block bb, bitmap local_md)
 {
   int bb_index = bb->index;
-  df_ref *def_rec;
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	{
-	  unsigned int dregno = DF_REF_REGNO (def);
-	  if (DF_REF_FLAGS (def)
-	      & (DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER))
-	    bitmap_set_bit (local_md, dregno);
-	  else
-	    bitmap_clear_bit (local_md, dregno);
-	}
-    }
+  df_ref def;
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      {
+	unsigned int dregno = DF_REF_REGNO (def);
+	if (DF_REF_FLAGS (def)
+	    & (DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER))
+	  bitmap_set_bit (local_md, dregno);
+	else
+	  bitmap_clear_bit (local_md, dregno);
+      }
 }
 
 
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2014-06-14 19:40:28.457704933 +0100
+++ gcc/df-scan.c	2014-06-14 20:01:12.353400410 +0100
@@ -1639,19 +1639,18 @@ df_reorganize_refs_by_reg_by_insn (struc
     {
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
       rtx insn;
-      df_ref *ref_rec;
       df_ref def, use;
 
       if (include_defs)
-	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
+	FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
 	  {
-	    unsigned int regno = DF_REF_REGNO (*ref_rec);
+	    unsigned int regno = DF_REF_REGNO (def);
 	    ref_info->count[regno]++;
 	  }
       if (include_uses)
-	for (ref_rec = df_get_artificial_uses (bb_index); *ref_rec; ref_rec++)
+	FOR_EACH_ARTIFICIAL_USE (use, bb_index)
 	  {
-	    unsigned int regno = DF_REF_REGNO (*ref_rec);
+	    unsigned int regno = DF_REF_REGNO (use);
 	    ref_info->count[regno]++;
 	  }
 
@@ -1694,33 +1693,30 @@ df_reorganize_refs_by_reg_by_insn (struc
     {
       basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
       rtx insn;
-      df_ref *ref_rec;
       df_ref def, use;
 
       if (include_defs)
-	for (ref_rec = df_get_artificial_defs (bb_index); *ref_rec; ref_rec++)
+	FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
 	  {
-	    df_ref ref = *ref_rec;
-	    unsigned int regno = DF_REF_REGNO (ref);
+	    unsigned int regno = DF_REF_REGNO (def);
 	    if (regno >= start)
 	      {
 		unsigned int id
 		  = ref_info->begin[regno] + ref_info->count[regno]++;
-		DF_REF_ID (ref) = id;
-		ref_info->refs[id] = ref;
+		DF_REF_ID (def) = id;
+		ref_info->refs[id] = def;
 	      }
 	  }
       if (include_uses)
-	for (ref_rec = df_get_artificial_uses (bb_index); *ref_rec; ref_rec++)
+	FOR_EACH_ARTIFICIAL_USE (use, bb_index)
 	  {
-	    df_ref ref = *ref_rec;
-	    unsigned int regno = DF_REF_REGNO (ref);
+	    unsigned int regno = DF_REF_REGNO (def);
 	    if (regno >= start)
 	      {
 		unsigned int id
 		  = ref_info->begin[regno] + ref_info->count[regno]++;
-		DF_REF_ID (ref) = id;
-		ref_info->refs[id] = ref;
+		DF_REF_ID (use) = id;
+		ref_info->refs[id] = use;
 	      }
 	  }
 
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	2014-06-14 19:40:26.919671918 +0100
+++ gcc/regrename.c	2014-06-14 20:01:12.353400410 +0100
@@ -533,7 +533,7 @@ struct bb_rename_info
 init_rename_info (struct bb_rename_info *p, basic_block bb)
 {
   int i;
-  df_ref *def_rec;
+  df_ref def;
   HARD_REG_SET start_chains_set;
 
   p->bb = bb;
@@ -545,12 +545,9 @@ init_rename_info (struct bb_rename_info
 
   CLEAR_HARD_REG_SET (live_in_chains);
   REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb));
-  for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
-	SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
+    if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
+      SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def));
 
   /* Open chains based on information from (at least one) predecessor
      block.  This gives us a chance later on to combine chains across
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c	2014-06-14 19:40:28.458704955 +0100
+++ gcc/regstat.c	2014-06-14 20:01:12.354400420 +0100
@@ -122,8 +122,6 @@ regstat_bb_compute_ri (unsigned int bb_i
 {
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   rtx insn;
-  df_ref *def_rec;
-  df_ref *use_rec;
   df_ref def, use;
   int luid = 0;
   bitmap_iterator bi;
@@ -139,23 +137,17 @@ regstat_bb_compute_ri (unsigned int bb_i
 
   /* Process the artificial defs and uses at the bottom of the block
      to begin processing.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
-	bitmap_clear_bit (live, DF_REF_REGNO (def));
-    }
-
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	{
-	  regno = DF_REF_REGNO (use);
-	  bitmap_set_bit (live, regno);
-	  bitmap_set_bit (artificial_uses, regno);
-	}
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+      bitmap_clear_bit (live, DF_REF_REGNO (def));
+
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+      {
+	regno = DF_REF_REGNO (use);
+	bitmap_set_bit (live, regno);
+	bitmap_set_bit (artificial_uses, regno);
+      }
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
@@ -441,27 +433,19 @@ regstat_bb_compute_calls_crossed (unsign
 {
   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
   rtx insn;
-  df_ref *def_rec;
-  df_ref *use_rec;
   df_ref def, use;
 
   bitmap_copy (live, df_get_live_out (bb));
 
   /* Process the artificial defs and uses at the bottom of the block
      to begin processing.  */
-  for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
-    {
-      df_ref def = *def_rec;
-      if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
-	bitmap_clear_bit (live, DF_REF_REGNO (def));
-    }
-
-  for (use_rec = df_get_artificial_uses (bb_index); *use_rec; use_rec++)
-    {
-      df_ref use = *use_rec;
-      if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
-	bitmap_set_bit (live, DF_REF_REGNO (use));
-    }
+  FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
+    if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
+      bitmap_clear_bit (live, DF_REF_REGNO (def));
+
+  FOR_EACH_ARTIFICIAL_USE (use, bb_index)
+    if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
+      bitmap_set_bit (live, DF_REF_REGNO (use));
 
   FOR_BB_INSNS_REVERSE (bb, insn)
     {

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
@ 2014-06-14 19:45   ` Richard Sandiford
  2014-06-14 20:12     ` Steven Bosscher
  2014-06-14 19:47   ` [PATCH 4/6] Add df_single_{def,use} helper functions Richard Sandiford
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:45 UTC (permalink / raw)
  To: gcc-patches

Similar to patch 1, but for df_mw_hardregs.  I think the "S" in "MWS"
is a plural, so I went for "mw" in the variable names for single entries.

Richard


gcc/
	* df.h (FOR_EACH_INSN_INFO_MW): New macro.
	* df-problems.c (df_note_bb_compute): Use it.
	* regstat.c (regstat_bb_compute_ri): Likewise.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-13 22:29:06.691558913 +0100
+++ gcc/df.h	2014-06-13 22:39:44.653179269 +0100
@@ -766,6 +766,10 @@ #define FOR_EACH_INSN_INFO_EQ_USE(ITER,
   for (df_ref *ITER##_ = DF_INSN_INFO_EQ_USES (INSN); (ITER = *ITER##_); \
        ++ITER##_)
 
+#define FOR_EACH_INSN_INFO_MW(ITER, INSN) \
+  for (df_mw_hardreg **ITER##_ = DF_INSN_INFO_MWS (INSN); (ITER = *ITER##_); \
+       ++ITER##_)
+
 #define FOR_EACH_INSN_DEF(ITER, INSN) \
   FOR_EACH_INSN_INFO_DEF(ITER, DF_INSN_INFO_GET (INSN))
 
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2014-06-13 22:29:06.690558904 +0100
+++ gcc/df-problems.c	2014-06-13 22:39:32.271064973 +0100
@@ -3114,7 +3114,7 @@ df_note_bb_compute (unsigned int bb_inde
   FOR_BB_INSNS_REVERSE (bb, insn)
     {
       df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-      struct df_mw_hardreg **mws_rec;
+      df_mw_hardreg *mw;
       int debug_insn;
 
       if (!INSN_P (insn))
@@ -3137,17 +3137,11 @@ df_note_bb_compute (unsigned int bb_inde
 
 	  /* We only care about real sets for calls.  Clobbers cannot
 	     be depended on to really die.  */
-	  mws_rec = DF_INSN_INFO_MWS (insn_info);
-	  while (*mws_rec)
-	    {
-	      struct df_mw_hardreg *mws = *mws_rec;
-	      if ((DF_MWS_REG_DEF_P (mws))
-		  && !df_ignore_stack_reg (mws->start_regno))
-	      df_set_unused_notes_for_mw (insn,
-					  mws, live, do_not_gen,
+	  FOR_EACH_INSN_INFO_MW (mw, insn_info)
+	    if ((DF_MWS_REG_DEF_P (mw))
+		&& !df_ignore_stack_reg (mw->start_regno))
+	      df_set_unused_notes_for_mw (insn, mw, live, do_not_gen,
 					  artificial_uses, &debug);
-	      mws_rec++;
-	    }
 
 	  /* All of the defs except the return value are some sort of
 	     clobber.  This code is for the return.  */
@@ -3168,16 +3162,10 @@ df_note_bb_compute (unsigned int bb_inde
       else
 	{
 	  /* Regular insn.  */
-	  mws_rec = DF_INSN_INFO_MWS (insn_info);
-	  while (*mws_rec)
-	    {
-	      struct df_mw_hardreg *mws = *mws_rec;
-	      if (DF_MWS_REG_DEF_P (mws))
-		df_set_unused_notes_for_mw (insn,
-					    mws, live, do_not_gen,
-					    artificial_uses, &debug);
-	      mws_rec++;
-	    }
+	  FOR_EACH_INSN_INFO_MW (mw, insn_info)
+	    if (DF_MWS_REG_DEF_P (mw))
+	      df_set_unused_notes_for_mw (insn, mw, live, do_not_gen,
+					  artificial_uses, &debug);
 
 	  FOR_EACH_INSN_INFO_DEF (def, insn_info)
 	    {
@@ -3194,25 +3182,19 @@ df_note_bb_compute (unsigned int bb_inde
 	}
 
       /* Process the uses.  */
-      mws_rec = DF_INSN_INFO_MWS (insn_info);
-      while (*mws_rec)
-	{
-	  struct df_mw_hardreg *mws = *mws_rec;
-	  if (DF_MWS_REG_USE_P (mws)
-	      && !df_ignore_stack_reg (mws->start_regno))
-	    {
-	      bool really_add_notes = debug_insn != 0;
-
-	      df_set_dead_notes_for_mw (insn,
-					mws, live, do_not_gen,
-					artificial_uses,
-					&really_add_notes);
-
-	      if (really_add_notes)
-		debug_insn = -1;
-	    }
-	  mws_rec++;
-	}
+      FOR_EACH_INSN_INFO_MW (mw, insn_info)
+	if (DF_MWS_REG_USE_P (mw)
+	    && !df_ignore_stack_reg (mw->start_regno))
+	  {
+	    bool really_add_notes = debug_insn != 0;
+
+	    df_set_dead_notes_for_mw (insn, mw, live, do_not_gen,
+				      artificial_uses,
+				      &really_add_notes);
+
+	    if (really_add_notes)
+	      debug_insn = -1;
+	  }
 
       FOR_EACH_INSN_INFO_USE (use, insn_info)
 	{
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c	2014-06-13 22:29:06.691558913 +0100
+++ gcc/regstat.c	2014-06-13 22:30:12.519134950 +0100
@@ -153,7 +153,7 @@ regstat_bb_compute_ri (unsigned int bb_i
     {
       struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       bitmap_iterator bi;
-      struct df_mw_hardreg **mws_rec;
+      df_mw_hardreg *mw;
       rtx link;
 
       if (!NONDEBUG_INSN_P (insn))
@@ -202,29 +202,26 @@ regstat_bb_compute_ri (unsigned int bb_i
       /* We only care about real sets for calls.  Clobbers cannot
 	 be depended on.
 	 Only do this if the value is totally dead.  */
-      for (mws_rec = DF_INSN_INFO_MWS (insn_info); *mws_rec; mws_rec++)
-	{
-	  struct df_mw_hardreg *mws = *mws_rec;
-	  if (DF_MWS_REG_DEF_P (mws))
-	    {
-	      bool all_dead = true;
-	      unsigned int r;
-
-	      for (r = mws->start_regno; r <= mws->end_regno; r++)
-		if (bitmap_bit_p (artificial_uses, r)
-		    || bitmap_bit_p (live, r))
-		  {
-		    all_dead = false;
-		    break;
-		  }
-
-	      if (all_dead)
+      FOR_EACH_INSN_INFO_MW (mw, insn_info)
+	if (DF_MWS_REG_DEF_P (mw))
+	  {
+	    bool all_dead = true;
+	    unsigned int r;
+
+	    for (r = mw->start_regno; r <= mw->end_regno; r++)
+	      if (bitmap_bit_p (artificial_uses, r)
+		  || bitmap_bit_p (live, r))
 		{
-		  regno = mws->start_regno;
-		  REG_LIVE_LENGTH (regno)++;
+		  all_dead = false;
+		  break;
 		}
-	    }
-	}
+
+	    if (all_dead)
+	      {
+		regno = mw->start_regno;
+		REG_LIVE_LENGTH (regno)++;
+	      }
+	  }
 
       /* All of the defs except the return value are some sort of
 	 clobber.  This code is for the return.  */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 4/6] Add df_single_{def,use} helper functions
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
  2014-06-14 19:45   ` [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW Richard Sandiford
@ 2014-06-14 19:47   ` Richard Sandiford
  2014-06-14 20:15     ` Steven Bosscher
  2014-06-14 20:10   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Steven Bosscher
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:47 UTC (permalink / raw)
  To: gcc-patches

IRA wants to know whether a particular insn has a single def or use.
That seems worth putting in a utility function, again to hide the
underlying representation a bit.

Richard


gcc/
	* df.h (df_single_def, df_single_use): New functions.
	* ira.c (find_moveable_pseudos): Use them.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-14 20:09:44.725239874 +0100
+++ gcc/df.h	2014-06-14 20:09:50.254289996 +0100
@@ -1165,6 +1165,25 @@ df_get_artificial_uses (unsigned int bb_
   return df_scan_get_bb_info (bb_index)->artificial_uses;
 }
 
+/* If INSN defines exactly one register, return the associated reference,
+   otherwise return null.  */
+
+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;
+}
+
+/* If INSN uses exactly one register, return the associated reference,
+   otherwise return null.  */
+
+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;
+}
 
 /* web */
 
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2014-06-14 20:09:44.726239882 +0100
+++ gcc/ira.c	2014-06-14 20:10:29.210640914 +0100
@@ -4437,20 +4437,19 @@ find_moveable_pseudos (void)
 	if (NONDEBUG_INSN_P (insn))
 	  {
 	    df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
-	    df_ref *u_rec, *d_rec;
 	    df_ref def, use;
 
 	    uid_luid[INSN_UID (insn)] = i++;
 	    
-	    u_rec = DF_INSN_INFO_USES (insn_info);
-	    d_rec = DF_INSN_INFO_DEFS (insn_info);
-	    if (d_rec[0] != NULL && d_rec[1] == NULL
-		&& u_rec[0] != NULL && u_rec[1] == NULL
-		&& DF_REF_REGNO (*u_rec) == DF_REF_REGNO (*d_rec)
-		&& !bitmap_bit_p (&set, DF_REF_REGNO (*u_rec))
+	    def = df_single_def (insn_info);
+	    use = df_single_use (insn_info);
+	    if (use
+		&& def
+		&& DF_REF_REGNO (use) == DF_REF_REGNO (def)
+		&& !bitmap_bit_p (&set, DF_REF_REGNO (use))
 		&& rtx_moveable_p (&PATTERN (insn), OP_IN))
 	      {
-		unsigned regno = DF_REF_REGNO (*u_rec);
+		unsigned regno = DF_REF_REGNO (use);
 		bitmap_set_bit (moveable, regno);
 		bitmap_set_bit (&set, regno);
 		bitmap_set_bit (&used, regno);
@@ -4487,16 +4486,16 @@ find_moveable_pseudos (void)
       FOR_BB_INSNS (bb, insn)
 	if (NONDEBUG_INSN_P (insn))
 	  {
+	    df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
 	    rtx def_insn, closest_use, note;
-	    df_ref *def_rec, def, use;
+	    df_ref def, use;
 	    unsigned regno;
 	    bool all_dominated, all_local;
 	    enum machine_mode mode;
 
-	    def_rec = DF_INSN_DEFS (insn);
+	    def = df_single_def (insn_info);
 	    /* There must be exactly one def in this insn.  */
-	    def = *def_rec;
-	    if (!def || def_rec[1] || !single_set (insn))
+	    if (!def || !single_set (insn))
 	      continue;
 	    /* This must be the only definition of the reg.  We also limit
 	       which modes we deal with so that we can assume we can generate

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 5/6] Remove dead code
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
  2014-06-14 19:44 ` [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE} Richard Sandiford
@ 2014-06-14 19:48 ` Richard Sandiford
  2014-06-14 20:17   ` Steven Bosscher
  2014-06-14 19:53 ` [PATCH 6/6] Use a linked list for insn defs and uses Richard Sandiford
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:48 UTC (permalink / raw)
  To: gcc-patches

This patch removes some dead code that would otherwise need to be
changed in the final patch.

Richard


gcc/
	* df.h (df_ref_create, df_ref_remove): Delete.
	* df-scan.c (df_ref_create, df_ref_compress_rec): Likewise.
	(df_ref_remove): Likewise.

Index: gcc/df.h
===================================================================
--- gcc/df.h	2014-06-13 22:36:35.314501770 +0100
+++ gcc/df.h	2014-06-13 22:36:39.482538550 +0100
@@ -1027,10 +1027,7 @@ extern void df_scan_add_problem (void);
 extern void df_grow_reg_info (void);
 extern void df_grow_insn_info (void);
 extern void df_scan_blocks (void);
-extern df_ref df_ref_create (rtx, rtx *, rtx,basic_block,
-			     enum df_ref_type, int ref_flags);
 extern void df_uses_create (rtx *, rtx, int);
-extern void df_ref_remove (df_ref);
 extern struct df_insn_info * df_insn_create_insn_record (rtx);
 extern void df_insn_delete (rtx);
 extern void df_bb_refs_record (int, bool);
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2014-06-13 22:36:23.478397337 +0100
+++ gcc/df-scan.c	2014-06-13 22:36:39.481538541 +0100
@@ -111,10 +111,6 @@ static void df_uses_record (struct df_co
 			    int ref_flags);
 
 static void df_install_ref_incremental (df_ref);
-static df_ref df_ref_create_structure (enum df_ref_class,
-				       struct df_collection_rec *, rtx, rtx *,
-				       basic_block, struct df_insn_info *,
-				       enum df_ref_type, int ref_flags);
 static void df_insn_refs_collect (struct df_collection_rec*,
 				  basic_block, struct df_insn_info *);
 static void df_canonize_collection_rec (struct df_collection_rec *);
@@ -694,32 +690,6 @@ df_uses_create (rtx *loc, rtx insn, int
                   ref_flags);
 }
 
-/* Create a new ref of type DF_REF_TYPE for register REG at address
-   LOC within INSN of BB.  This function is only used externally.  */
-
-df_ref
-df_ref_create (rtx reg, rtx *loc, rtx insn,
-	       basic_block bb,
-	       enum df_ref_type ref_type,
-	       int ref_flags)
-{
-  enum df_ref_class cl;
-
-  df_grow_reg_info ();
-
-  /* You cannot hack artificial refs.  */
-  gcc_assert (insn);
-
-  if (loc)
-    cl = DF_REF_REGULAR;
-  else
-    cl = DF_REF_BASE;
-
-  return df_ref_create_structure (cl, NULL, reg, loc, bb,
-                                  DF_INSN_INFO_GET (insn),
-                                  ref_type, ref_flags);
-}
-
 static void
 df_install_ref_incremental (df_ref ref)
 {
@@ -934,89 +904,6 @@ df_reg_chain_unlink (df_ref ref)
 }
 
 
-/* Remove REF from VEC.  */
-
-static void
-df_ref_compress_rec (df_ref **vec_ptr, df_ref ref)
-{
-  df_ref *vec = *vec_ptr;
-
-  if (vec[1])
-    {
-      while (*vec && *vec != ref)
-	vec++;
-
-      while (*vec)
-	{
-	  *vec = *(vec+1);
-	  vec++;
-	}
-    }
-  else
-    {
-      free (vec);
-      *vec_ptr = df_null_ref_rec;
-    }
-}
-
-
-/* Unlink REF from all def-use/use-def chains, etc.  */
-
-void
-df_ref_remove (df_ref ref)
-{
-#if 0
-  if (dump_file)
-    {
-      fprintf (dump_file, "removing ref ");
-      df_ref_debug (ref, dump_file);
-    }
-#endif
-
-  if (DF_REF_REG_DEF_P (ref))
-    {
-      if (DF_REF_IS_ARTIFICIAL (ref))
-	{
-	  struct df_scan_bb_info *bb_info
-	    = df_scan_get_bb_info (DF_REF_BBNO (ref));
-	  df_ref_compress_rec (&bb_info->artificial_defs, ref);
-	}
-      else
-	{
-	  unsigned int uid = DF_REF_INSN_UID (ref);
-	  struct df_insn_info *insn_rec = DF_INSN_UID_GET (uid);
-	  df_ref_compress_rec (&insn_rec->defs, ref);
-	}
-    }
-  else
-    {
-      if (DF_REF_IS_ARTIFICIAL (ref))
-	{
-	  struct df_scan_bb_info *bb_info
-	    = df_scan_get_bb_info (DF_REF_BBNO (ref));
-	  df_ref_compress_rec (&bb_info->artificial_uses, ref);
-	}
-      else
-	{
-	  unsigned int uid = DF_REF_INSN_UID (ref);
-	  struct df_insn_info *insn_rec = DF_INSN_UID_GET (uid);
-
-	  if (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE)
-	    df_ref_compress_rec (&insn_rec->eq_uses, ref);
-	  else
-	    df_ref_compress_rec (&insn_rec->uses, ref);
-	}
-    }
-
-  /* By deleting the ref directly, df_insn_rescan my not find any
-     differences even though the block will have changed.  So we need
-     to mark the block dirty ourselves.  */
-  if (!DEBUG_INSN_P (DF_REF_INSN (ref)))
-    df_set_bb_dirty (DF_REF_BB (ref));
-  df_reg_chain_unlink (ref);
-}
-
-
 /* Create the insn record for INSN.  If there was one there, zero it
    out.  */
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 6/6] Use a linked list for insn defs and uses
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
                   ` (2 preceding siblings ...)
  2014-06-14 19:48 ` [PATCH 5/6] Remove dead code Richard Sandiford
@ 2014-06-14 19:53 ` Richard Sandiford
  2014-06-14 20:24   ` Steven Bosscher
  2014-06-14 20:29 ` [PATCH 0/6] Make df_ref representation more efficient Steven Bosscher
  2014-06-15 19:35 ` Jan Hubicka
  5 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2014-06-14 19:53 UTC (permalink / raw)
  To: gcc-patches

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));
     }
 }
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
  2014-06-14 19:45   ` [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW Richard Sandiford
  2014-06-14 19:47   ` [PATCH 4/6] Add df_single_{def,use} helper functions Richard Sandiford
@ 2014-06-14 20:10   ` Steven Bosscher
  2014-06-15 11:27   ` breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}" Hans-Peter Nilsson
  2014-06-16  7:59   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Andreas Schwab
  4 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:10 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:43 PM, Richard Sandiford wrote:
> gcc/
>         * df.h (DF_INSN_INFO_MWS, FOR_EACH_INSN_INFO_DEF): New macros.
>         (FOR_EACH_INSN_INFO_USE, FOR_EACH_INSN_INFO_EQ_USE): Likewise.
>         (FOR_EACH_INSN_DEF, FOR_EACH_INSN_USE, FOR_EACH_INSN_EQ_USE): Likewise.
>         * auto-inc-dec.c (find_inc, merge_in_block): Use them.
>         * combine.c (create_log_links): Likewise.
>         * compare-elim.c (find_flags_uses_in_insn): Likewise.
>         (try_eliminate_compare): Likewise.
>         * cprop.c (make_set_regs_unavailable, mark_oprs_set): Likewise.
>         * dce.c (deletable_insn_p, find_call_stack_args): Likewise.
>         (remove_reg_equal_equiv_notes_for_defs): Likewise.
>         (reset_unmarked_insns_debug_uses, mark_reg_dependencies): Likewise.
>         (word_dce_process_block, dce_process_block): Likewise.
>         * ddg.c (def_has_ccmode_p): Likewise.
>         * df-core.c (df_bb_regno_first_def_find): Likewise.
>         (df_bb_regno_last_def_find, df_find_def, df_find_use): Likewise.
>         * df-problems.c (df_rd_simulate_one_insn): Likewise.
>         (df_lr_bb_local_compute, df_live_bb_local_compute): Likewise.
>         (df_chain_remove_problem, df_chain_insn_top_dump): Likewise.
>         (df_chain_insn_bottom_dump, df_word_lr_bb_local_compute): Likewise.
>         (df_word_lr_simulate_defs, df_word_lr_simulate_uses): Likewise.
>         (df_remove_dead_eq_notes, df_note_bb_compute): Likewise.
>         (df_simulate_find_defs, df_simulate_find_uses): Likewise.
>         (df_simulate_find_noclobber_defs, df_simulate_defs): Likewise.
>         (df_simulate_uses, df_md_simulate_one_insn): Likewise.
>         * df-scan.c (df_reorganize_refs_by_reg_by_insn): Likewise.
>         * fwprop.c (local_ref_killed_between_p): Likewise.
>         (all_uses_available_at, free_load_extend): Likewise.
>         * gcse.c (update_bb_reg_pressure, calculate_bb_reg_pressure): Likewise.
>         * hw-doloop.c (scan_loop): Likewise.
>         * ifcvt.c (dead_or_predicable): Likewise.
>         * init-regs.c (initialize_uninitialized_regs): Likewise.
>         * ira-lives.c (mark_hard_reg_early_clobbers): Likewise.
>         (process_bb_node_lives): Likewise.
>         * ira.c (compute_regs_asm_clobbered, build_insn_chain): Likewise.
>         (find_moveable_pseudos): Likewise.
>         * loop-invariant.c (check_dependencies, record_uses): Likewise.
>         * recog.c (peep2_find_free_register): Likewise.
>         * ree.c (get_defs): Likewise.
>         * regstat.c (regstat_bb_compute_ri): Likewise.
>         (regstat_bb_compute_calls_crossed): Likewise.
>         * sched-deps.c (find_inc, find_mem): Likewise.
>         * sel-sched-ir.c (maybe_downgrade_id_to_use): Likewise.
>         (maybe_downgrade_id_to_use, setup_id_reg_sets): Likewise.
>         * shrink-wrap.c (requires_stack_frame_p): Likewise.
>         (prepare_shrink_wrap): Likewise.
>         * store-motion.c (compute_store_table, build_store_vectors): Likewise.
>         * web.c (union_defs, pass_web::execute): Likewise.
>         * config/i386/i386.c (increase_distance, insn_defines_reg): Likewise.
>         (insn_uses_reg_mem, ix86_ok_to_clobber_flags): Likewise.

OK. Nice :-)

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE}
  2014-06-14 19:44 ` [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE} Richard Sandiford
@ 2014-06-14 20:11   ` Steven Bosscher
  0 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:11 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:44 PM, Richard Sandiford wrote:
> gcc/
>         * df.h (FOR_EACH_ARTIFICIAL_USE, FOR_EACH_ARTIFICIAL_DEF): New macros.
>         * cse.c (cse_extended_basic_block): Use them.
>         * dce.c (mark_artificial_use): Likewise.
>         * df-problems.c (df_rd_simulate_artificial_defs_at_top): Likewise.
>         (df_lr_bb_local_compute, df_live_bb_local_compute): Likewise.
>         (df_chain_remove_problem, df_chain_bb_dump): Likewise.
>         (df_word_lr_bb_local_compute, df_note_bb_compute): Likewise.
>         (df_simulate_initialize_backwards): Likewise.
>         (df_simulate_finalize_backwards): Likewise.
>         (df_simulate_initialize_forwards): Likewise.
>         (df_md_simulate_artificial_defs_at_top): Likewise.
>         * df-scan.c (df_reorganize_refs_by_reg_by_insn): Likewise.
>         * regrename.c (init_rename_info): Likewise.
>         * regstat.c (regstat_bb_compute_ri): Likewise.
>         (regstat_bb_compute_calls_crossed): Likewise.

OK.

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW
  2014-06-14 19:45   ` [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW Richard Sandiford
@ 2014-06-14 20:12     ` Steven Bosscher
  0 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:12 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:45 PM, Richard Sandiford wrote:
> gcc/
>         * df.h (FOR_EACH_INSN_INFO_MW): New macro.
>         * df-problems.c (df_note_bb_compute): Use it.
>         * regstat.c (regstat_bb_compute_ri): Likewise.

OK.

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/6] Add df_single_{def,use} helper functions
  2014-06-14 19:47   ` [PATCH 4/6] Add df_single_{def,use} helper functions Richard Sandiford
@ 2014-06-14 20:15     ` Steven Bosscher
  0 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:15 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:47 PM, Richard Sandiford wrote:
> IRA wants to know whether a particular insn has a single def or use.
> That seems worth putting in a utility function, again to hide the
> underlying representation a bit.

I would have sworn we already had functions for this, but apparently not...

>         * ira.c (find_moveable_pseudos): Use them.

OK.

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/6] Remove dead code
  2014-06-14 19:48 ` [PATCH 5/6] Remove dead code Richard Sandiford
@ 2014-06-14 20:17   ` Steven Bosscher
  0 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:17 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:48 PM, Richard Sandiford wrote:
> This patch removes some dead code that would otherwise need to be
> changed in the final patch.

These functions were intended to allow passes to update DF info
manually. That never was a very practical idea, apparently.

> gcc/
>         * df.h (df_ref_create, df_ref_remove): Delete.
>         * df-scan.c (df_ref_create, df_ref_compress_rec): Likewise.
>         (df_ref_remove): Likewise.

OK.

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 6/6] Use a linked list for insn defs and uses
  2014-06-14 19:53 ` [PATCH 6/6] Use a linked list for insn defs and uses Richard Sandiford
@ 2014-06-14 20:24   ` Steven Bosscher
  0 siblings, 0 replies; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:24 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:53 PM, Richard Sandiford wrote:
> 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.


I would prefer a macro for base.next_loc (DF_REF_NEXT_LOC?).

Other than that: OK.

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] Make df_ref representation more efficient
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
                   ` (3 preceding siblings ...)
  2014-06-14 19:53 ` [PATCH 6/6] Use a linked list for insn defs and uses Richard Sandiford
@ 2014-06-14 20:29 ` Steven Bosscher
  2014-06-15  7:31   ` Richard Sandiford
  2014-06-15 19:35 ` Jan Hubicka
  5 siblings, 1 reply; 27+ messages in thread
From: Steven Bosscher @ 2014-06-14 20:29 UTC (permalink / raw)
  To: GCC Patches, rdsandiford

On Sat, Jun 14, 2014 at 9:36 PM, Richard Sandiford wrote:
> Using a linked list gives a consistent 2% compile-time improvement for
> fold-const.ii -O0 and ~1% for various -O2 compiles I tried.  The df
> routines do still show up high on the profile though.

Can you explain a bit more about what shows up high?

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] Make df_ref representation more efficient
  2014-06-14 20:29 ` [PATCH 0/6] Make df_ref representation more efficient Steven Bosscher
@ 2014-06-15  7:31   ` Richard Sandiford
  0 siblings, 0 replies; 27+ messages in thread
From: Richard Sandiford @ 2014-06-15  7:31 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: GCC Patches

Steven Bosscher <stevenb.gcc@gmail.com> writes:
> On Sat, Jun 14, 2014 at 9:36 PM, Richard Sandiford wrote:
>> Using a linked list gives a consistent 2% compile-time improvement for
>> fold-const.ii -O0 and ~1% for various -O2 compiles I tried.  The df
>> routines do still show up high on the profile though.
>
> Can you explain a bit more about what shows up high?

For cc1plus -O0 on an oldish fold-const.ii I get:

     3.19%  cc1plus  cc1plus            [.] record_reg_classes(int, int, rtx_def**, machine_mode*, char const**, rtx_def*, reg_class*) [clone .constprop.5]
     2.91%  cc1plus  cc1plus            [.] cp_parser_skip_to_closing_parenthesis(cp_parser*, bool, bool, bool)
     1.42%  cc1plus  cc1plus            [.] cp_lexer_consume_token(cp_lexer*)
     1.42%  cc1plus  cc1plus            [.] df_ref_create_structure(df_ref_class, df_collection_rec*, rtx_def*, rtx_def**, basic_block_def*, df_insn_info*, df_ref_type, int)
     1.31%  cc1plus  cc1plus            [.] ggc_internal_alloc(unsigned long, void (*)(void*), unsigned long, unsigned long)
     1.10%  cc1plus  cc1plus            [.] df_ref_record(df_ref_class, df_collection_rec*, rtx_def*, rtx_def**, basic_block_def*, df_insn_info*, df_ref_type, int)
     0.89%  cc1plus  cc1plus            [.] find_costs_and_classes(_IO_FILE*)
     0.89%  cc1plus  cc1plus            [.] process_bb_node_lives(ira_loop_tree_node*)
     0.86%  cc1plus  cc1plus            [.] bitmap_set_bit(bitmap_head*, int)
     0.82%  cc1plus  cc1plus            [.] df_note_compute(bitmap_head*)
     0.77%  cc1plus  libc-2.18.so       [.] _int_malloc
     0.76%  cc1plus  cc1plus            [.] ix86_decompose_address(rtx_def*, ix86_address*)
     0.76%  cc1plus  cc1plus            [.] process_alt_operands(int)
     0.75%  cc1plus  cc1plus            [.] general_operand(rtx_def*, machine_mode)
     0.72%  cc1plus  cc1plus            [.] df_uses_record(df_collection_rec*, rtx_def**, df_ref_type, basic_block_def*, df_insn_info*, int)
     0.72%  cc1plus  cc1plus            [.] pool_alloc(alloc_pool_def*)
     0.72%  cc1plus  cc1plus            [.] lookup_name_real(tree_node*, int, int, bool, int, int)
     0.67%  cc1plus  cc1plus            [.] df_insn_refs_collect(df_collection_rec*, basic_block_def*, df_insn_info*)
     0.67%  cc1plus  cc1plus            [.] constrain_operands(int)
     0.66%  cc1plus  cc1plus            [.] for_each_rtx_1(rtx_def*, int, int (*)(rtx_def**, void*), void*)
     0.63%  cc1plus  cc1plus            [.] gimplify_expr(tree_node**, gimple_statement_base**, gimple_statement_base**, bool (*)(tree_node*), int)
     0.62%  cc1plus  cc1plus            [.] grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*, decl_context, int, tree_node**)
     0.62%  cc1plus  cc1plus            [.] walk_tree_1(tree_node**, tree_node* (*)(tree_node**, int*, void*), void*, pointer_set_t*, tree_node* (*)(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, pointer_set_t*))
     0.59%  cc1plus  cc1plus            [.] expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
     0.58%  cc1plus  cc1plus            [.] df_ref_equal_p(df_ref_d*, df_ref_d*)
     0.57%  cc1plus  cc1plus            [.] lra_create_live_ranges(bool)
     0.51%  cc1plus  cc1plus            [.] lra_eliminate(bool, bool)
     0.51%  cc1plus  cc1plus            [.] extract_insn(rtx_def*)
     0.51%  cc1plus  cc1plus            [.] ix86_legitimate_address_p(machine_mode, rtx_def*, bool)
     0.50%  cc1plus  libc-2.18.so       [.] _IO_putc
     0.49%  cc1plus  libc-2.18.so       [.] memset
     0.49%  cc1plus  cc1plus            [.] df_lr_bb_local_compute(unsigned int)
     0.47%  cc1plus  cc1plus            [.] regstat_compute_ri()
     0.47%  cc1plus  cc1plus            [.] _cpp_lex_direct
     0.46%  cc1plus  cc1plus            [.] cp_parser_postfix_expression(cp_parser*, bool, bool, bool, bool, cp_id_kind*)
     0.44%  cc1plus  cc1plus            [.] htab_find_slot_with_hash
     0.42%  cc1plus  libc-2.18.so       [.] malloc_consolidate
     0.42%  cc1plus  [kernel.kallsyms]  [k] clear_page_c_e
     0.41%  cc1plus  cc1plus            [.] copy_rtx_if_shared_1(rtx_def**)
     0.41%  cc1plus  cc1plus            [.] cleanup_cfg(int)

where df routines seem to be showing up a fair bit (3 in the top 10).
I realise that can be misleading since it might just be that the
df work is concentrated in a small number of functions.

This is after the patches.  malloc was in the top 5 before.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
                     ` (2 preceding siblings ...)
  2014-06-14 20:10   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Steven Bosscher
@ 2014-06-15 11:27   ` Hans-Peter Nilsson
  2014-06-15 16:21     ` Steven Bosscher
  2014-06-16  7:59   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Andreas Schwab
  4 siblings, 1 reply; 27+ messages in thread
From: Hans-Peter Nilsson @ 2014-06-15 11:27 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

On Sat, 14 Jun 2014, Richard Sandiford wrote:

> To make the final representation change easier, this patch introduces
> macros for iterating over lists of defs, uses and eq_uses.  At the
> moment there are three possible keys when accessing df_ref lists:
> the insn rtx (DF_INSN_*), the insn uid (DF_INSN_UID_*) and the
> df_insn_info (DF_INSN_INFO_*).  I don't think it's worth adding
> iterators for uids though.  Any code that's going to the trouble of
> caching the uid might as well go the whole hog and cache the underlying
> df_insn_info.
>
> After the feedback to the BB iterator patch:
>
>   https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00676.html
>
> I've kept the iterator variable definitions outside the FOR_* macros
> rather than make the FOR_* macros define the variables themselves.
>
> Richard
>
>
> gcc/
> 	* df.h (DF_INSN_INFO_MWS, FOR_EACH_INSN_INFO_DEF): New macros.
> 	(FOR_EACH_INSN_INFO_USE, FOR_EACH_INSN_INFO_EQ_USE): Likewise.
> 	(FOR_EACH_INSN_DEF, FOR_EACH_INSN_USE, FOR_EACH_INSN_EQ_USE): Likewise.
> 	* auto-inc-dec.c (find_inc, merge_in_block): Use them.


One of these patches (in 211677:211684) broke cris-elf:

g++ -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE
-fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall
\
-Wwrite-strings -Wcast-qual -Wmissing-format-attribute
-Woverloaded-virtual -pedantic -Wno-long-long
-Wno-variadic-macr\
os -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I.
-I/tmp/hpautotest-gcc0/gcc/gcc -I/tmp/hpautotest-gcc0/g\
cc/gcc/. -I/tmp/hpautotest-gcc0/gcc/gcc/../include
-I/tmp/hpautotest-gcc0/gcc/gcc/../libcpp/include
-I/tmp/hpautotest-g\
cc0/cris-elf/gccobj/./gmp -I/tmp/hpautotest-gcc0/gcc/gmp
-I/tmp/hpautotest-gcc0/cris-elf/gccobj/./mpfr -I/tmp/hpautotes\
t-gcc0/gcc/mpfr -I/tmp/hpautotest-gcc0/gcc/mpc/src
-I/tmp/hpautotest-gcc0/gcc/gcc/../libdecnumber
-I/tmp/hpautotest-gc\
c0/gcc/gcc/../libdecnumber/dpd -I../libdecnumber
-I/tmp/hpautotest-gcc0/gcc/gcc/../libbacktrace    -o
auto-inc-dec.o -M\
T auto-inc-dec.o -MMD -MP -MF ./.deps/auto-inc-dec.TPo
/tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c
/tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c: In function 'void
merge_in_block(int, basic_block_def*)':
/tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c:1442: error: 'uid'
was not declared in this scope
make[2]: *** [auto-inc-dec.o] Error 1

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 11:27   ` breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}" Hans-Peter Nilsson
@ 2014-06-15 16:21     ` Steven Bosscher
  2014-06-15 22:37       ` Hans-Peter Nilsson
  0 siblings, 1 reply; 27+ messages in thread
From: Steven Bosscher @ 2014-06-15 16:21 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Richard Sandiford, GCC Patches

On Sun, Jun 15, 2014 at 1:27 PM, Hans-Peter Nilsson wrote:
> On Sat, 14 Jun 2014, Richard Sandiford wrote:
>
>> To make the final representation change easier, this patch introduces
>> macros for iterating over lists of defs, uses and eq_uses.  At the
>> moment there are three possible keys when accessing df_ref lists:
>> the insn rtx (DF_INSN_*), the insn uid (DF_INSN_UID_*) and the
>> df_insn_info (DF_INSN_INFO_*).  I don't think it's worth adding
>> iterators for uids though.  Any code that's going to the trouble of
>> caching the uid might as well go the whole hog and cache the underlying
>> df_insn_info.
>>
>> After the feedback to the BB iterator patch:
>>
>>   https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00676.html
>>
>> I've kept the iterator variable definitions outside the FOR_* macros
>> rather than make the FOR_* macros define the variables themselves.
>>
>> Richard
>>
>>
>> gcc/
>>       * df.h (DF_INSN_INFO_MWS, FOR_EACH_INSN_INFO_DEF): New macros.
>>       (FOR_EACH_INSN_INFO_USE, FOR_EACH_INSN_INFO_EQ_USE): Likewise.
>>       (FOR_EACH_INSN_DEF, FOR_EACH_INSN_USE, FOR_EACH_INSN_EQ_USE): Likewise.
>>       * auto-inc-dec.c (find_inc, merge_in_block): Use them.
>
>
> One of these patches (in 211677:211684) broke cris-elf:
>
> g++ -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE
> -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall
> \
> -Wwrite-strings -Wcast-qual -Wmissing-format-attribute
> -Woverloaded-virtual -pedantic -Wno-long-long
> -Wno-variadic-macr\
> os -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I.
> -I/tmp/hpautotest-gcc0/gcc/gcc -I/tmp/hpautotest-gcc0/g\
> cc/gcc/. -I/tmp/hpautotest-gcc0/gcc/gcc/../include
> -I/tmp/hpautotest-gcc0/gcc/gcc/../libcpp/include
> -I/tmp/hpautotest-g\
> cc0/cris-elf/gccobj/./gmp -I/tmp/hpautotest-gcc0/gcc/gmp
> -I/tmp/hpautotest-gcc0/cris-elf/gccobj/./mpfr -I/tmp/hpautotes\
> t-gcc0/gcc/mpfr -I/tmp/hpautotest-gcc0/gcc/mpc/src
> -I/tmp/hpautotest-gcc0/gcc/gcc/../libdecnumber
> -I/tmp/hpautotest-gc\
> c0/gcc/gcc/../libdecnumber/dpd -I../libdecnumber
> -I/tmp/hpautotest-gcc0/gcc/gcc/../libbacktrace    -o
> auto-inc-dec.o -M\
> T auto-inc-dec.o -MMD -MP -MF ./.deps/auto-inc-dec.TPo
> /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c
> /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c: In function 'void
> merge_in_block(int, basic_block_def*)':
> /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c:1442: error: 'uid'
> was not declared in this scope
> make[2]: *** [auto-inc-dec.o] Error 1
>
> brgds, H-P


Bah, this is why I just *hate* all the gcc code that's only compiled
if certain #defines are set...

Can you please try:

Index: auto-inc-dec.c
===================================================================
--- auto-inc-dec.c      (revision 211685)
+++ auto-inc-dec.c      (working copy)
@@ -1439,7 +1439,8 @@ merge_in_block (int max_reg, basic_block bb)
            }
        }
       else if (dump_file)
-       fprintf (dump_file, "skipping update of deleted insn %d\n", uid);
+       fprintf (dump_file, "skipping update of deleted insn %d\n",
+                INSN_UID (insn));
     }

   /* If we were successful, try again.  There may have been several

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] Make df_ref representation more efficient
  2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
                   ` (4 preceding siblings ...)
  2014-06-14 20:29 ` [PATCH 0/6] Make df_ref representation more efficient Steven Bosscher
@ 2014-06-15 19:35 ` Jan Hubicka
  2014-06-15 20:46   ` Jan Hubicka
  5 siblings, 1 reply; 27+ messages in thread
From: Jan Hubicka @ 2014-06-15 19:35 UTC (permalink / raw)
  To: gcc-patches, rdsandiford

> Walks of things like DF_REF_INSN_USES were showing up high in the profile
> of a fold-const.ii compilation.  These reference lists are represented
> as pointers to null-terminated lists of pointers, and since there's
> little locality when walking all insns, each loop over the uses or defs
> generally has two major cache misses before it can do anything
> (or one major cache miss before doing nothing), on top of accessing
> the underlying df_insn_info.  Also, for -O0, the overhead of mallocing
> lots of small arrays is itself noticeable.
> 
> I don't think there's any real need for this representation.  Each
> df_ref belongs to exactly one of these null-terminated pointer arrays,
> so using a normal linked list would be more efficient memory-wise
> (because we'd save on the null terminator and separate malloced memory).

I think situation here is simliar to ipa-ref.  Here I have two arrays 
in ipa_ref_list:
  /* Store actual references in references vector.  */
  vec<ipa_ref_t, va_gc> *references;
  /* Referring is vector of pointers to references.  It must not live in GGC space
     or GGC will try to mark middle of references vectors.  */
  vec<ipa_ref_ptr>  GTY((skip)) referring;

So all references are stored in an array, while all referring are stored
as array of pointers to references within the arrays of refering nodes.

On resize of references array I need to check if all references has moved &
update referring arrays accordingly, but that is not so big deal. Also users
needs to be aware of fact that refernces do not have stable addresses.

Perhaps this representation would make sense for df? Especially when references
are collected for given function and thus we know the size of references array
in advance?

Honza
> 
> The idea might have been to allow the array to be sorted easily.
> That doesn't really apply now though.  We collect the references in a
> df_collection_rec and sort them there before populating the df_insn_info.
> After that we just insert single elements or merge two sorted lists.
> (Both of these are currently done as full qsorts, but don't need to be.)
> 
> Using a linked list gives a consistent 2% compile-time improvement for
> fold-const.ii -O0 and ~1% for various -O2 compiles I tried.  The df
> routines do still show up high on the profile though.
> 
> Tested on x86_64-linux-gnu.  OK to install?
> 
> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] Make df_ref representation more efficient
  2014-06-15 19:35 ` Jan Hubicka
@ 2014-06-15 20:46   ` Jan Hubicka
  0 siblings, 0 replies; 27+ messages in thread
From: Jan Hubicka @ 2014-06-15 20:46 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc-patches, rdsandiford

> > Walks of things like DF_REF_INSN_USES were showing up high in the profile
> > of a fold-const.ii compilation.  These reference lists are represented
> > as pointers to null-terminated lists of pointers, and since there's
> > little locality when walking all insns, each loop over the uses or defs
> > generally has two major cache misses before it can do anything
> > (or one major cache miss before doing nothing), on top of accessing
> > the underlying df_insn_info.  Also, for -O0, the overhead of mallocing
> > lots of small arrays is itself noticeable.
> > 
> > I don't think there's any real need for this representation.  Each
> > df_ref belongs to exactly one of these null-terminated pointer arrays,
> > so using a normal linked list would be more efficient memory-wise
> > (because we'd save on the null terminator and separate malloced memory).
> 
> I think situation here is simliar to ipa-ref.  Here I have two arrays 
> in ipa_ref_list:
>   /* Store actual references in references vector.  */
>   vec<ipa_ref_t, va_gc> *references;
>   /* Referring is vector of pointers to references.  It must not live in GGC space
>      or GGC will try to mark middle of references vectors.  */
>   vec<ipa_ref_ptr>  GTY((skip)) referring;
> 
> So all references are stored in an array, while all referring are stored
> as array of pointers to references within the arrays of refering nodes.
> 
> On resize of references array I need to check if all references has moved &
> update referring arrays accordingly, but that is not so big deal. Also users
> needs to be aware of fact that refernces do not have stable addresses.
> 
> Perhaps this representation would make sense for df? Especially when references
> are collected for given function and thus we know the size of references array
			  ^^^^^^^^
			  instruction

Basically I think that most of time we can allocate the array only after we know the
size.

Honza
> in advance?
> 
> Honza
> > 
> > The idea might have been to allow the array to be sorted easily.
> > That doesn't really apply now though.  We collect the references in a
> > df_collection_rec and sort them there before populating the df_insn_info.
> > After that we just insert single elements or merge two sorted lists.
> > (Both of these are currently done as full qsorts, but don't need to be.)
> > 
> > Using a linked list gives a consistent 2% compile-time improvement for
> > fold-const.ii -O0 and ~1% for various -O2 compiles I tried.  The df
> > routines do still show up high on the profile though.
> > 
> > Tested on x86_64-linux-gnu.  OK to install?
> > 
> > Thanks,
> > Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 16:21     ` Steven Bosscher
@ 2014-06-15 22:37       ` Hans-Peter Nilsson
  2014-06-15 22:53         ` Hans-Peter Nilsson
  2014-06-16  8:30         ` Steven Bosscher
  0 siblings, 2 replies; 27+ messages in thread
From: Hans-Peter Nilsson @ 2014-06-15 22:37 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: Richard Sandiford, GCC Patches

On Sun, 15 Jun 2014, Steven Bosscher wrote:
> On Sun, Jun 15, 2014 at 1:27 PM, Hans-Peter Nilsson wrote:
> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c: In function 'void
> > merge_in_block(int, basic_block_def*)':
> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c:1442: error: 'uid'
> > was not declared in this scope
> > make[2]: *** [auto-inc-dec.o] Error 1
> >
> > brgds, H-P
>
>
> Bah, this is why I just *hate* all the gcc code that's only compiled
> if certain #defines are set...

I couldn't agree more.  Might not have been obvious when writing
the mosly-mechanical patch, still the auto-inc-dec.c name should
have been a red flag that a representative target should have
been tested (i.e. not x86_64 and i686).

>
> Can you please try:
>
> [...]

Thanks.  Looks pretty obvious.  I was heading for the door with
just enough time to report the issue, so I didn't actually look
at the code before.  I'll commit this on your behalf once build
has passed the point of failure.

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 22:37       ` Hans-Peter Nilsson
@ 2014-06-15 22:53         ` Hans-Peter Nilsson
  2014-06-15 23:39           ` Hans-Peter Nilsson
  2014-06-16  8:30         ` Steven Bosscher
  1 sibling, 1 reply; 27+ messages in thread
From: Hans-Peter Nilsson @ 2014-06-15 22:53 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: Richard Sandiford, GCC Patches

On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
> On Sun, 15 Jun 2014, Steven Bosscher wrote:
> > Can you please try:
> >
> > [...]
>
> Thanks.  Looks pretty obvious.  I was heading for the door with
> just enough time to report the issue, so I didn't actually look
> at the code before.  I'll commit this on your behalf once build
> has passed the point of failure.

...which includes not just compiling auto-inc-dec.c but also
compiling e.g. libgcc with the compiled compiler.  No such luck,
segv in that function (must be from Richard's code, not from the
patch as no dumps are output at that time).  Bah.

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 22:53         ` Hans-Peter Nilsson
@ 2014-06-15 23:39           ` Hans-Peter Nilsson
  2014-06-16  8:04             ` Andreas Schwab
  0 siblings, 1 reply; 27+ messages in thread
From: Hans-Peter Nilsson @ 2014-06-15 23:39 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: Richard Sandiford, GCC Patches

On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:

> On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
> > On Sun, 15 Jun 2014, Steven Bosscher wrote:
> > > Can you please try:
> > >
> > > [...]
> >
> > Thanks.  Looks pretty obvious.  I was heading for the door with
> > just enough time to report the issue, so I didn't actually look
> > at the code before.  I'll commit this on your behalf once build
> > has passed the point of failure.
>
> ...which includes not just compiling auto-inc-dec.c but also
> compiling e.g. libgcc with the compiled compiler.  No such luck,
> segv in that function (must be from Richard's code, not from the
> patch as no dumps are output at that time).  Bah.

Ok, I'm out; I don't know why the insn_info is invalid here.
Hopefully obvious to you or Richard.  PR61516 for this.

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}
  2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
                     ` (3 preceding siblings ...)
  2014-06-15 11:27   ` breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}" Hans-Peter Nilsson
@ 2014-06-16  7:59   ` Andreas Schwab
  4 siblings, 0 replies; 27+ messages in thread
From: Andreas Schwab @ 2014-06-16  7:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: rdsandiford

Richard Sandiford <rdsandiford@googlemail.com> writes:

> Index: gcc/auto-inc-dec.c
> ===================================================================
> --- gcc/auto-inc-dec.c	2014-06-14 20:08:31.421565177 +0100
> +++ gcc/auto-inc-dec.c	2014-06-14 20:08:33.433584004 +0100
> @@ -969,7 +969,7 @@ find_inc (bool first_try)
>    rtx insn;
>    basic_block bb = BLOCK_FOR_INSN (mem_insn.insn);
>    rtx other_insn;
> -  df_ref *def_rec;
> +  df_ref def;
>  
>    /* Make sure this reg appears only once in this insn.  */
>    if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
> @@ -1013,9 +1013,8 @@ find_inc (bool first_try)
>  
>    /* Need to assure that none of the operands of the inc instruction are
>       assigned to by the mem insn.  */
> -  for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
> +  FOR_EACH_INSN_DEF (def, mem_insn.insn)
>      {
> -      df_ref def = *def_rec;
>        unsigned int regno = DF_REF_REGNO (def);
>        if ((regno == REGNO (inc_insn.reg0))
>  	  || (regno == REGNO (inc_insn.reg_res)))
> @@ -1342,7 +1341,7 @@ merge_in_block (int max_reg, basic_block
>  
>    FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
>      {
> -      unsigned int uid = INSN_UID (insn);
> +      df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
>        bool insn_is_add_or_inc = true;
>  
>        if (!NONDEBUG_INSN_P (insn))
> @@ -1418,22 +1417,20 @@ merge_in_block (int max_reg, basic_block
>  
>        /* If the inc insn was merged with a mem, the inc insn is gone
>  	 and there is noting to update.  */
> -      if (DF_INSN_UID_GET (uid))
> +      if (insn_info)

This is wrong.  As the comment explains, the insn may already be
recycled, and you use a stale pointer.  Since insn_info is a local
variable, it cannot reflect that fact.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 23:39           ` Hans-Peter Nilsson
@ 2014-06-16  8:04             ` Andreas Schwab
  2014-06-16  8:29               ` Ramana Radhakrishnan
  0 siblings, 1 reply; 27+ messages in thread
From: Andreas Schwab @ 2014-06-16  8:04 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Steven Bosscher, Richard Sandiford, GCC Patches

Hans-Peter Nilsson <hp@bitrange.com> writes:

> On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
>
>> On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
>> > On Sun, 15 Jun 2014, Steven Bosscher wrote:
>> > > Can you please try:
>> > >
>> > > [...]
>> >
>> > Thanks.  Looks pretty obvious.  I was heading for the door with
>> > just enough time to report the issue, so I didn't actually look
>> > at the code before.  I'll commit this on your behalf once build
>> > has passed the point of failure.
>>
>> ...which includes not just compiling auto-inc-dec.c but also
>> compiling e.g. libgcc with the compiled compiler.  No such luck,
>> segv in that function (must be from Richard's code, not from the
>> patch as no dumps are output at that time).  Bah.
>
> Ok, I'm out; I don't know why the insn_info is invalid here.
> Hopefully obvious to you or Richard.  PR61516 for this.

Please try this:

diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
index 64a3706..d84e097 100644
--- a/gcc/auto-inc-dec.c
+++ b/gcc/auto-inc-dec.c
@@ -1341,6 +1341,7 @@ merge_in_block (int max_reg, basic_block bb)
 
   FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
     {
+      unsigned int uid = INSN_UID (insn);
       df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
       bool insn_is_add_or_inc = true;
 
@@ -1417,7 +1418,7 @@ merge_in_block (int max_reg, basic_block bb)
 
       /* If the inc insn was merged with a mem, the inc insn is gone
 	 and there is noting to update.  */
-      if (insn_info)
+      if (DF_INSN_UID_GET (uid))
 	{
 	  df_ref def, use;
 

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-16  8:04             ` Andreas Schwab
@ 2014-06-16  8:29               ` Ramana Radhakrishnan
  0 siblings, 0 replies; 27+ messages in thread
From: Ramana Radhakrishnan @ 2014-06-16  8:29 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Hans-Peter Nilsson, Steven Bosscher, Richard Sandiford, GCC Patches

On Mon, Jun 16, 2014 at 9:04 AM, Andreas Schwab <schwab@suse.de> wrote:
> Hans-Peter Nilsson <hp@bitrange.com> writes:
>
>> On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
>>
>>> On Sun, 15 Jun 2014, Hans-Peter Nilsson wrote:
>>> > On Sun, 15 Jun 2014, Steven Bosscher wrote:
>>> > > Can you please try:
>>> > >
>>> > > [...]
>>> >
>>> > Thanks.  Looks pretty obvious.  I was heading for the door with
>>> > just enough time to report the issue, so I didn't actually look
>>> > at the code before.  I'll commit this on your behalf once build
>>> > has passed the point of failure.
>>>
>>> ...which includes not just compiling auto-inc-dec.c but also
>>> compiling e.g. libgcc with the compiled compiler.  No such luck,
>>> segv in that function (must be from Richard's code, not from the
>>> patch as no dumps are output at that time).  Bah.
>>
>> Ok, I'm out; I don't know why the insn_info is invalid here.
>> Hopefully obvious to you or Richard.  PR61516 for this.
>
> Please try this:
>
> diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
> index 64a3706..d84e097 100644
> --- a/gcc/auto-inc-dec.c
> +++ b/gcc/auto-inc-dec.c
> @@ -1341,6 +1341,7 @@ merge_in_block (int max_reg, basic_block bb)
>
>    FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
>      {
> +      unsigned int uid = INSN_UID (insn);
>        df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
>        bool insn_is_add_or_inc = true;
>
> @@ -1417,7 +1418,7 @@ merge_in_block (int max_reg, basic_block bb)
>
>        /* If the inc insn was merged with a mem, the inc insn is gone
>          and there is noting to update.  */
> -      if (insn_info)
> +      if (DF_INSN_UID_GET (uid))
>         {
>           df_ref def, use;

Doesn't appear to help on arm-none-linux-gnueabihf where I tried
applying a slight variant of this after the latest fixups for the
auto-inc-dec breakage.

I've gone through all the stages of breakage on this on my
arm-none-linux-gnueabihf auto-tester too.

regards
Ramana

>
>
> Andreas.
>
> --
> Andreas Schwab, SUSE Labs, schwab@suse.de
> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
> "And now for something completely different."

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-15 22:37       ` Hans-Peter Nilsson
  2014-06-15 22:53         ` Hans-Peter Nilsson
@ 2014-06-16  8:30         ` Steven Bosscher
  2014-06-16 11:23           ` Hans-Peter Nilsson
  1 sibling, 1 reply; 27+ messages in thread
From: Steven Bosscher @ 2014-06-16  8:30 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Richard Sandiford, GCC Patches

On Mon, Jun 16, 2014 at 12:36 AM, Hans-Peter Nilsson wrote:
> On Sun, 15 Jun 2014, Steven Bosscher wrote:
>> On Sun, Jun 15, 2014 at 1:27 PM, Hans-Peter Nilsson wrote:
>> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c: In function 'void
>> > merge_in_block(int, basic_block_def*)':
>> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c:1442: error: 'uid'
>> > was not declared in this scope
>> > make[2]: *** [auto-inc-dec.o] Error 1
>> >
>> > brgds, H-P
>>
>>
>> Bah, this is why I just *hate* all the gcc code that's only compiled
>> if certain #defines are set...
>
> I couldn't agree more.  Might not have been obvious when writing
> the mosly-mechanical patch, still the auto-inc-dec.c name should
> have been a red flag that a representative target should have
> been tested (i.e. not x86_64 and i686).

I agree, but I think you'd agree with me if I say that Richard S. is
one of the few people who almost always goes beyond the normal amount
of testing required for a patch. Breakage like this will just happen
to us all, every once in a while, until we compile all middle-end code
at least, regardless of #defines and whatnot (conditionally compiled
code, from the top of my head: CC0, scheduler, dbrsched, auto-inc-dec,
HAVE_conditional_move, etc...).

Ciao!
Steven

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}"
  2014-06-16  8:30         ` Steven Bosscher
@ 2014-06-16 11:23           ` Hans-Peter Nilsson
  0 siblings, 0 replies; 27+ messages in thread
From: Hans-Peter Nilsson @ 2014-06-16 11:23 UTC (permalink / raw)
  To: Steven Bosscher; +Cc: Richard Sandiford, GCC Patches

On Mon, 16 Jun 2014, Steven Bosscher wrote:
> On Mon, Jun 16, 2014 at 12:36 AM, Hans-Peter Nilsson wrote:
> > On Sun, 15 Jun 2014, Steven Bosscher wrote:
> >> On Sun, Jun 15, 2014 at 1:27 PM, Hans-Peter Nilsson wrote:
> >> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c: In function 'void
> >> > merge_in_block(int, basic_block_def*)':
> >> > /tmp/hpautotest-gcc0/gcc/gcc/auto-inc-dec.c:1442: error: 'uid'
> >> > was not declared in this scope
> >> > make[2]: *** [auto-inc-dec.o] Error 1
> >> >
> >> > brgds, H-P
> >>
> >>
> >> Bah, this is why I just *hate* all the gcc code that's only compiled
> >> if certain #defines are set...
> >
> > I couldn't agree more.  Might not have been obvious when writing
> > the mosly-mechanical patch, still the auto-inc-dec.c name should
> > have been a red flag that a representative target should have
> > been tested (i.e. not x86_64 and i686).
>
> I agree, but I think you'd agree with me if I say that Richard S. is
> one of the few people who almost always goes beyond the normal amount
> of testing required for a patch.

His testing efforts relative many others I'd agree on (and I
seem to have a knack for being caught when things still go bad
with his patches), but I'd say the amount of testing that
Richard S usually applies is entirely appropriate and I wish
others would follow!  Also, looks like he fixed it.  (Thanks!)

> Breakage like this will just happen
> to us all, every once in a while, until we compile all middle-end code
> at least, regardless of #defines and whatnot (conditionally compiled
> code, from the top of my head: CC0, scheduler, dbrsched, auto-inc-dec,
> HAVE_conditional_move, etc...).

The patch looked pretty mechanical.  I feared the rabbit-hole,
but the stage 2 issue was apparently just the use of stale data
from the loop.  Exercising that required actually running the
code when testing.

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2014-06-16 11:23 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-14 19:36 [PATCH 0/6] Make df_ref representation more efficient Richard Sandiford
2014-06-14 19:43 ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Richard Sandiford
2014-06-14 19:45   ` [PATCH 3/6] Add FOR_EACH_INSN_INFO_MW Richard Sandiford
2014-06-14 20:12     ` Steven Bosscher
2014-06-14 19:47   ` [PATCH 4/6] Add df_single_{def,use} helper functions Richard Sandiford
2014-06-14 20:15     ` Steven Bosscher
2014-06-14 20:10   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Steven Bosscher
2014-06-15 11:27   ` breakage with "[PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES}" Hans-Peter Nilsson
2014-06-15 16:21     ` Steven Bosscher
2014-06-15 22:37       ` Hans-Peter Nilsson
2014-06-15 22:53         ` Hans-Peter Nilsson
2014-06-15 23:39           ` Hans-Peter Nilsson
2014-06-16  8:04             ` Andreas Schwab
2014-06-16  8:29               ` Ramana Radhakrishnan
2014-06-16  8:30         ` Steven Bosscher
2014-06-16 11:23           ` Hans-Peter Nilsson
2014-06-16  7:59   ` [PATCH 1/6] Add FOR_EACH_INSN{_INFO}_{DEFS,USES,EQ_USES} Andreas Schwab
2014-06-14 19:44 ` [PATCH 2/6] FOR_EACH_ARTIFICIAL_{DEF,USE} Richard Sandiford
2014-06-14 20:11   ` Steven Bosscher
2014-06-14 19:48 ` [PATCH 5/6] Remove dead code Richard Sandiford
2014-06-14 20:17   ` Steven Bosscher
2014-06-14 19:53 ` [PATCH 6/6] Use a linked list for insn defs and uses Richard Sandiford
2014-06-14 20:24   ` Steven Bosscher
2014-06-14 20:29 ` [PATCH 0/6] Make df_ref representation more efficient Steven Bosscher
2014-06-15  7:31   ` Richard Sandiford
2014-06-15 19:35 ` Jan Hubicka
2014-06-15 20:46   ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).