[dataflow]: PATCH: fix regressions on IA64/PPC, add more debug points.

Seongbae Park seongbae.park@gmail.com
Sat Dec 2 00:09:00 GMT 2006


Bootstrapped and regression tested on x86, x86-64, PPC and ia64.
This patch clears up all dataflow branch regressions on above platforms,
except a few extra regressions on x86 (32bit) due to a latent bug
which Ken Zadeck is already working on.


2006-12-01  Seongbae Park <seongbae.park@gmail.com>

        * dbgcnt.def: New counters
        * postreload-gcse.c (delete_redundant_insns_1): New
        debug counter point.
        * postreload.c (reload_cse_move2add, gate_handle_postreload):
        New debug counter point.
        * auto-inc-dec.c (move_notes): Removed.
        (move_dead_notes): New function.
        (attempt_change): Call move_dead_notes(). Add missing dependency check.
        * haifa-sched.c (schedule_block): New debug counter point.
        * cse.c (delete_trivially_dead_insns): New debug counter point.
        * gcse.c (pre_delete): New debug counter point.
        * Makefile.in: Adding dependency on DBGCNT_H.
        * sched-rgn.c (schedule_region): New debug counter point.
        * dce.c (delete_corresponding_reg_equal_notes): New function
        (delete_unmarked_insns): Call delete_corresponding_reg_equal_notes.

-- 
#pragma ident "Seongbae Park, compiler, http://seongbae.blogspot.com"
-------------- next part --------------
Index: gcc/dbgcnt.def
===================================================================
--- gcc/dbgcnt.def	(revision 119428)
+++ gcc/dbgcnt.def	(working copy)
@@ -74,3 +74,10 @@ DEBUG_COUNTER (sched2_func)
 DEBUG_COUNTER (local_alloc_for_sched)
 DEBUG_COUNTER (split_for_sched2)
 DEBUG_COUNTER (ia64_sched2)
+DEBUG_COUNTER (pre_insn)
+DEBUG_COUNTER (sched_block)
+DEBUG_COUNTER (sched_insn)
+DEBUG_COUNTER (gcse2_delete)
+DEBUG_COUNTER (cse2_move2add)
+DEBUG_COUNTER (delete_trivial_dead)
+DEBUG_COUNTER (postreload_cse)
Index: gcc/postreload-gcse.c
===================================================================
--- gcc/postreload-gcse.c	(revision 119428)
+++ gcc/postreload-gcse.c	(working copy)
@@ -46,6 +46,7 @@ Software Foundation, 51 Franklin Street,
 #include "target.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "dbgcnt.h"
 
 /* The following code implements gcse after reload, the purpose of this
    pass is to cleanup redundant loads generated by reload and other
@@ -1290,7 +1291,7 @@ delete_redundant_insns_1 (void **slot, v
 
   for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
     {
-      if (occr->deleted_p)
+      if (occr->deleted_p && dbg_cnt (gcse2_delete))
 	{
 	  delete_insn (occr->insn);
 	  stats.insns_deleted++;
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	(revision 119428)
+++ gcc/postreload.c	(working copy)
@@ -47,6 +47,7 @@ Software Foundation, 51 Franklin Street,
 #include "timevar.h"
 #include "tree-pass.h"
 #include "df.h"
+#include "dbgcnt.h"
 
 static int reload_cse_noop_set_p (rtx);
 static void reload_cse_simplify (rtx, rtx);
@@ -1227,7 +1228,8 @@ reload_cse_move2add (rtx first)
 	  /* Check if we have valid information on the contents of this
 	     register in the mode of REG.  */
 	  if (reg_set_luid[regno] > move2add_last_label_luid
-	      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]))
+	      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])
+              && dbg_cnt (cse2_move2add))
 	    {
 	      /* Try to transform (set (REGX) (CONST_INT A))
 				  ...
@@ -1574,6 +1576,9 @@ gate_handle_postreload (void)
 static unsigned int
 rest_of_handle_postreload (void)
 {
+  if (!dbg_cnt (postreload_cse))
+    return 0;
+
   /* Do a very simple CSE pass over just the hard registers.  */
   reload_cse_regs (get_insns ());
   /* Reload_cse_regs can eliminate potentially-trapping MEMs.
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c	(revision 119428)
+++ gcc/auto-inc-dec.c	(working copy)
@@ -452,39 +452,34 @@ static rtx * reg_next_def = NULL;
 static struct df *df = NULL;
 
 
-/* Move notes that match PATTERN to TO_INSN from FROM_INSN.  If
-   PATTERN is NULL, move all notes.  */
+/* Move dead note that match PATTERN to TO_INSN from FROM_INSN.  We do
+   not really care about moving any other notes from the inc or add
+   insn.  Moving the REG_EQUAL and REG_EQUIV is clearly wrong and it
+   does not appear that there are any other kinds of relavant notes.  */
 
 static void 
-move_notes (rtx to_insn, rtx from_insn, rtx pattern)
+move_dead_notes (rtx to_insn, rtx from_insn, rtx pattern)
 {
   rtx note; 
   rtx next_note;
   rtx prev_note = NULL;
 
-  if (pattern)
-    for (note = REG_NOTES (from_insn); note; note = next_note)
-      {
-	next_note = XEXP (note, 1);
-	
-	if (pattern == XEXP (note, 0))
-	  {
-	    XEXP (note, 1) = REG_NOTES (to_insn);
-	    REG_NOTES (to_insn) = note;
-	    if (prev_note)
-	      XEXP (prev_note, 1) = next_note;
-	    else
-	      REG_NOTES (from_insn) = next_note;
-	  }
-	else prev_note = note;
-      }
-  else
-    for (note = REG_NOTES (from_insn); note; note = next_note)
-      {
-	next_note = XEXP (note, 1);
-	XEXP (note, 1) = REG_NOTES (to_insn);
-	REG_NOTES (to_insn) = note;
-      }
+  for (note = REG_NOTES (from_insn); note; note = next_note)
+    {
+      next_note = XEXP (note, 1);
+      
+      if ((REG_NOTE_KIND(note) == REG_DEAD)
+	  && pattern == XEXP (note, 0))
+	{
+	  XEXP (note, 1) = REG_NOTES (to_insn);
+	  REG_NOTES (to_insn) = note;
+	  if (prev_note)
+	    XEXP (prev_note, 1) = next_note;
+	  else
+	    REG_NOTES (from_insn) = next_note;
+	}
+      else prev_note = note;
+    }
 }
 
 
@@ -565,9 +560,9 @@ attempt_change (rtx new_addr_pat, rtx in
   switch (inc_insn.form)
     {
     case FORM_PRE_ADD:
-      move_notes (mem_insn.insn, inc_insn.insn, NULL);
       mov_insn = insert_move_insn_before (mem_insn.insn, 
 					  inc_insn.reg_res, inc_insn.reg0);
+      move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
 
       regno = REGNO (inc_insn.reg_res);
       reg_next_def [regno] = mov_insn;
@@ -583,7 +578,6 @@ attempt_change (rtx new_addr_pat, rtx in
 
       /* Fallthru.  */
     case FORM_PRE_INC:
-      move_notes (mem_insn.insn, inc_insn.insn, NULL);
       regno = REGNO (inc_insn.reg_res);
       reg_next_def [regno] = mem_insn.insn;
       reg_next_use [regno] = NULL;
@@ -593,9 +587,7 @@ attempt_change (rtx new_addr_pat, rtx in
     case FORM_POST_ADD:
       mov_insn = insert_move_insn_before (mem_insn.insn, 
 					  inc_insn.reg_res, inc_insn.reg0);
-      move_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
-      move_notes (mem_insn.insn, inc_insn.insn, inc_insn.reg1);
-      move_notes (mem_insn.insn, inc_insn.insn, inc_insn.reg_res);
+      move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0);
 
       /* Do not move anything to the mov insn because the instruction
 	 pointer for the main iteration has not yet hit that.  It is
@@ -1096,7 +1088,20 @@ find_inc (bool first_try)
 	{
 	  if (dump_file)
 	    fprintf (dump_file, 
-		     "result of inc is assigned to between mem and inc insns.\n");
+		     "result of add is assigned to between mem and inc insns.\n");
+	  return false;
+	}
+
+      other_insn = get_next_ref (REGNO (inc_insn.reg_res), 
+				 BASIC_BLOCK (BLOCK_NUM (mem_insn.insn)), 
+				 reg_next_use);
+      if (other_insn 
+	  && (other_insn != inc_insn.insn)
+	  && (DF_INSN_LUID (df, inc_insn.insn) > DF_INSN_LUID (df, other_insn)))
+	{
+	  if (dump_file)
+	    fprintf (dump_file, 
+		     "result of add is used between mem and inc insns.\n");
 	  return false;
 	}
 
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c	(revision 119428)
+++ gcc/haifa-sched.c	(working copy)
@@ -144,6 +144,7 @@ Software Foundation, 51 Franklin Street,
 #include "target.h"
 #include "output.h"
 #include "params.h"
+#include "dbgcnt.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -2294,8 +2295,6 @@ schedule_block (basic_block *target_bb, 
 		 there's nothing better to do (ready list is empty) but
 		 there are still vacant dispatch slots in the current cycle.  */
 	      if (sched_verbose >= 6)
-		fprintf(sched_dump,";;\t\tSecond chance\n");
-	      memcpy (temp_state, curr_state, dfa_state_size);
 	      if (early_queue_to_ready (temp_state, &ready))
 		ready_sort (&ready);
 	    }
@@ -2305,6 +2304,23 @@ schedule_block (basic_block *target_bb, 
 	      || !(*current_sched_info->schedule_more_p) ())
 	    break;
 
+          if (dbg_cnt (sched_insn) == false)
+            {
+              insn = NEXT_INSN (last_scheduled_insn); 
+              while ((*current_sched_info->schedule_more_p) ())
+                {
+                  (*current_sched_info->begin_schedule_ready) (insn,
+                                                               last_scheduled_insn);
+                  if (QUEUE_INDEX (insn) >= 0)
+                    queue_remove (insn);
+                  last_scheduled_insn = insn;
+                  insn = NEXT_INSN (insn);
+                }
+              while (ready.n_ready)
+                ready_remove_first (&ready);
+              goto bail_out;
+            }
+
 	  /* Select and remove the insn from the ready list.  */
 	  if (sort_p)
 	    {
@@ -2462,6 +2478,7 @@ schedule_block (basic_block *target_bb, 
 	}
     }
 
+bail_out:
   /* Debug info.  */
   if (sched_verbose)
     {
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(revision 119428)
+++ gcc/cse.c	(working copy)
@@ -44,6 +44,7 @@ Software Foundation, 51 Franklin Street,
 #include "params.h"
 #include "rtlhooks-def.h"
 #include "tree-pass.h"
+#include "dbgcnt.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -6541,7 +6542,7 @@ delete_trivially_dead_insns (rtx insns, 
       /* If this is a dead insn, delete it and show registers in it aren't
 	 being used.  */
 
-      if (! live_insn)
+      if (! live_insn && dbg_cnt (delete_trivial_dead))
 	{
 	  count_reg_usage (insn, counts, NULL_RTX, -1);
 	  delete_insn_and_edges (insn);
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c	(revision 119428)
+++ gcc/gcse.c	(working copy)
@@ -171,6 +171,7 @@ Software Foundation, 51 Franklin Street,
 #include "timevar.h"
 #include "tree-pass.h"
 #include "hashtab.h"
+#include "dbgcnt.h"
 
 /* Propagate flow information through back edges and thus enable PRE's
    moving loop invariant calculations out of loops.
@@ -4437,7 +4438,8 @@ pre_delete (void)
 
 	    /* We only delete insns that have a single_set.  */
 	    if (TEST_BIT (pre_delete_map[bb->index], indx)
-		&& (set = single_set (insn)) != 0)
+		&& (set = single_set (insn)) != 0
+                && dbg_cnt (pre_insn))
 	      {
 		/* Create a pseudo-reg to store the result of reaching
 		   expressions into.  Get the mode for the new pseudo from
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 119428)
+++ gcc/Makefile.in	(working copy)
@@ -2342,7 +2342,8 @@ cselib.o : cselib.c $(CONFIG_H) $(SYSTEM
 cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
    hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
    output.h $(FUNCTION_H) $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \
-   except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h $(REAL_H)
+   except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h $(REAL_H) \
+   $(DBGCNT_H)
 dce.o : dce.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(DF_H) cselib.h \
    $(DBGCNT_H) dce.h timevar.h tree-pass.h
@@ -2359,7 +2360,7 @@ gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) 
    $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h $(GGC_H) \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
    $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h $(TREE_H) cselib.h $(TIMEVAR_H) \
-   intl.h $(OBSTACK_H) tree-pass.h
+   intl.h $(OBSTACK_H) tree-pass.h $(DBGCNT_H)
 resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
    coretypes.h $(TM_H) $(REGS_H) $(FLAGS_H) output.h $(RESOURCE_H) $(DF_H) \
    $(FUNCTION_H) toplev.h $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H)
@@ -2536,7 +2537,7 @@ postreload-gcse.o : postreload-gcse.c $(
    $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
    $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
    $(TM_P_H) except.h $(TREE_H) $(TARGET_H) $(HASHTAB_H) intl.h $(OBSTACK_H) \
-   $(PARAMS_H) $(TIMEVAR_H) tree-pass.h $(REAL_H)
+   $(PARAMS_H) $(TIMEVAR_H) tree-pass.h $(REAL_H) $(DBGCNT_H)
 caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(FUNCTION_H) \
    addresses.h $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H)
@@ -2577,7 +2578,7 @@ modulo-sched.o : modulo-sched.c $(DDG_H)
 haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \
    $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H) output.h \
-   $(PARAMS_H)
+   $(PARAMS_H) $(DBGCNT_H)
 sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
    $(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h \
Index: gcc/sched-rgn.c
===================================================================
--- gcc/sched-rgn.c	(revision 119428)
+++ gcc/sched-rgn.c	(working copy)
@@ -2800,9 +2800,16 @@ schedule_region (int rgn)
       current_sched_info->queue_must_finish_empty = current_nr_blocks == 1;
 
       curr_bb = first_bb;
-      schedule_block (&curr_bb, rgn_n_insns);
-      gcc_assert (EBB_FIRST_BB (bb) == first_bb);
-      sched_rgn_n_insns += sched_n_insns;
+      if (dbg_cnt (sched_block))
+        {
+          schedule_block (&curr_bb, rgn_n_insns);
+          gcc_assert (EBB_FIRST_BB (bb) == first_bb);
+          sched_rgn_n_insns += sched_n_insns;
+        }
+      else
+        {
+          sched_rgn_n_insns += rgn_n_insns;
+        }
 
       /* Clean up.  */
       if (current_nr_blocks > 1)
Index: gcc/dce.c
===================================================================
--- gcc/dce.c	(revision 119428)
+++ gcc/dce.c	(working copy)
@@ -213,6 +213,46 @@ init_dce (bool fast)
 }
 
 
+/* Delete all REG_EQUAL notes of the registers INSN writes,
+   to prevent bad dangling REG_EQUAL notes. */
+
+static void
+delete_corresponding_reg_equal_notes (rtx insn)
+{
+  struct df_ref *def;
+  for (def = DF_INSN_DEFS (dce_df, insn); def; def = DF_REF_NEXT_REF (def))
+    {
+      struct df_ref *eq_use = DF_REG_EQ_USE_CHAIN (dce_df, DF_REF_REGNO (def));
+
+      if (eq_use)
+        {
+          rtx *insns = alloca (sizeof(rtx) 
+                               * DF_REG_EQ_USE_COUNT (dce_df, DF_REF_REGNO (def)));
+          rtx *p_insn = insns;
+          do
+            {
+              rtx note;
+              if (DF_REF_INSN (eq_use) != insn
+                  && (note = find_reg_note (DF_REF_INSN (eq_use), 
+                                            REG_EQUAL, NULL_RTX)) != NULL)
+                {
+                  remove_note (DF_REF_INSN (eq_use), note);
+                  /* We can't rescan while iterating over EQ_USE chain,
+                     because rescanning invalidates EQ_USE chain. 
+                     Instead, we just keep the record of the insns. */
+                  *p_insn++ = DF_REF_INSN (eq_use);
+                }
+            }
+          while ((eq_use = DF_REF_NEXT_REG (eq_use)) != NULL);
+
+          /* Now rescan insns that have REG_EQUAL note removed.  */
+          while (--p_insn >= insns)
+            df_insn_rescan (*p_insn);
+        }
+    }
+}
+
+
 /* Delete every instruction that hasn't been marked.  Clear the insn from DCE_DF if
    DF_DELETE is true.  */
 
@@ -232,6 +272,11 @@ delete_unmarked_insns (void)
 	  if (dump_file)
 	    fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn));
 	  /* XXX: This may need to be changed to delete_insn_and_edges */
+
+          /* Before we delete the insn, we have to delete
+             REG_EQUAL of the destination regs of the deleted insn
+             to prevent dangling REG_EQUAL. */
+          delete_corresponding_reg_equal_notes (insn);
 	  delete_insn (insn);
 	  something_changed = true;
 	}


More information about the Gcc-patches mailing list