Patchwork fix left-over debug insns in DCE

login
register
mail settings
Submitter Alexandre Oliva
Date June 6, 2011, 10:06 a.m.
Message ID <ortyc3cm07.fsf@livre.localdomain>
Download mbox | patch
Permalink /patch/98861/
State New
Headers show

Comments

Alexandre Oliva - June 6, 2011, 10:06 a.m.
On Jun  6, 2011, Eric Botcazou <ebotcazou@adacore.com> wrote:

>> Indeed, sorry, I misread it.

> Mind installing these bits separately?

Nope.  Testing it separately now.

> My understanding is that they are 
> independent correctness fixes.

Yeah, I guess they are.  They won't make debug info any worse, although
they may remove incorrect debug info, and they won't preserve debug info
that we currently discard, which the other part of the patch retains.

Here's what I'm going to check in if regstrapping succeeds.

Patch

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* dce.c (reset_unmarked_insns_debug_uses): New.
	(delete_unmarked_insns): Skip debug insns.
	(prescan_insns_for_dce): Likewise.
	(rest_of_handle_ud_dce): Reset debug uses of removed sets.
	* reg-stack.c (subst_stack_regs_in_debug_insn): Signal when no
	active reg can be found.
	(subst_all_stack_regs_in_debug_insn): New.  Reset debug insn then.
	(convert_regs_1): Use it.

Index: gcc/dce.c
===================================================================
--- gcc/dce.c.orig	2011-05-26 05:03:08.552989108 -0300
+++ gcc/dce.c	2011-05-27 03:09:07.711388764 -0300
@@ -493,6 +493,43 @@  remove_reg_equal_equiv_notes_for_defs (r
     remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (*def_rec));
 }
 
+/* Scan all BBs for debug insns and reset those that reference values
+   defined in unmarked insns.  */
+
+static void
+reset_unmarked_insns_debug_uses (void)
+{
+  basic_block bb;
+  rtx insn, next;
+
+  FOR_EACH_BB_REVERSE (bb)
+    FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
+      if (DEBUG_INSN_P (insn))
+	{
+	  df_ref *use_rec;
+
+	  for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
+	    {
+	      df_ref use = *use_rec;
+	      struct df_link *defs;
+	      for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
+		{
+		  rtx insn;
+		  if (DF_REF_IS_ARTIFICIAL (defs->ref))
+		    continue;
+		  insn = DF_REF_INSN (defs->ref);
+		  if (!marked_insn_p (insn))
+		    break;
+		}
+	      if (!defs)
+		continue;
+	      /* ??? FIXME could we propagate the values assigned to
+		 each of the DEFs?  */
+	      INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+	      df_insn_rescan_debug_internal (insn);
+	    }
+	}
+}
 
 /* Delete every instruction that hasn't been marked.  */
 
@@ -505,7 +542,7 @@  delete_unmarked_insns (void)
 
   FOR_EACH_BB_REVERSE (bb)
     FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
 	{
 	  /* Always delete no-op moves.  */
 	  if (noop_move_p (insn))
@@ -579,7 +616,7 @@  prescan_insns_for_dce (bool fast)
   FOR_EACH_BB (bb)
     {
       FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev)
-	if (INSN_P (insn))
+	if (NONDEBUG_INSN_P (insn))
 	  {
 	    /* Don't mark argument stores now.  They will be marked
 	       if needed when the associated CALL is marked.  */
@@ -713,6 +750,9 @@  rest_of_handle_ud_dce (void)
     }
   VEC_free (rtx, heap, worklist);
 
+  if (MAY_HAVE_DEBUG_INSNS)
+    reset_unmarked_insns_debug_uses ();
+
   /* Before any insns are deleted, we must remove the chains since
      they are not bidirectional.  */
   df_remove_problem (df_chain);
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c.orig	2011-05-26 05:03:08.554989112 -0300
+++ gcc/reg-stack.c	2011-05-27 03:11:23.756589358 -0300
@@ -1333,6 +1333,11 @@  subst_stack_regs_in_debug_insn (rtx *loc
     return 0;
 
   hard_regno = get_hard_regnum (regstack, *loc);
+
+  /* If we can't find an active register, reset this debug insn.  */
+  if (hard_regno == -1)
+    return 1;
+
   gcc_assert (hard_regno >= FIRST_STACK_REG);
 
   replace_reg (loc, hard_regno);
@@ -1340,6 +1345,23 @@  subst_stack_regs_in_debug_insn (rtx *loc
   return -1;
 }
 
+/* Substitute hardware stack regs in debug insn INSN, using stack
+   layout REGSTACK.  If we can't find a hardware stack reg for any of
+   the REGs in it, reset the debug insn.  */
+
+static void
+subst_all_stack_regs_in_debug_insn (rtx insn, struct stack_def *regstack)
+{
+  int ret = for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
+			  subst_stack_regs_in_debug_insn,
+			  regstack);
+
+  if (ret == 1)
+    INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+  else
+    gcc_checking_assert (ret == 0);
+}
+
 /* Substitute new registers in PAT, which is part of INSN.  REGSTACK
    is the current register layout.  Return whether a control flow insn
    was deleted in the process.  */
@@ -2947,8 +2969,7 @@  convert_regs_1 (basic_block block)
 	    debug_insns_with_starting_stack++;
 	  else
 	    {
-	      for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
-			    &regstack);
+	      subst_all_stack_regs_in_debug_insn (insn, &regstack);
 
 	      /* Nothing must ever die at a debug insn.  If something
 		 is referenced in it that becomes dead, it should have
@@ -2986,8 +3007,7 @@  convert_regs_1 (basic_block block)
 	    continue;
 
 	  debug_insns_with_starting_stack--;
-	  for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
-			&bi->stack_in);
+	  subst_all_stack_regs_in_debug_insn (insn, &bi->stack_in);
 	}
     }