public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* fix left-over debug insns in DCE
@ 2011-05-30 12:15 Alexandre Oliva
  2011-06-02 15:26 ` Eric Botcazou
  0 siblings, 1 reply; 23+ messages in thread
From: Alexandre Oliva @ 2011-05-30 12:15 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1118 bytes --]

The insn shuffling in one of my patches for PR48866 shook out some
latent problems in DCE.

One of the issues was that DCE removed an insn that set a REG in a
certain mode, without adjusting a debug use of that REG.  This was in
libstdc++, but I failed to take note of the affected file.  DF later
attached that debug use to another SET to the same REG in a different,
incompatible mode.  When that one was found to be dead by DF, we ended
up ICEing as we attempted to emit the invalid SUBREGs.

I reused some of the infrastructure to propagate dead DEFs into debug
uses in DF to get DCE to emit debug temps and adjust debug uses as well,
fixing this issue.  While at that, I improved the handling of unused
DEFs in DF, that previously resulted in loss of debug information, so as
to retain it as much as possible.

The changes above ended up exposing another latent problem in regstack,
by which a debug insn referenced a stack register that wasn't available.
I adjusted the code to tolerate this possibility.

This is the patch I ended up with.  Regstrapped on x86_64-linux-gnu and
i686-linux-gnu.  Ok to install?



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-df-preserve-unused-dead-in-debug-temp-pr48866.patch --]
[-- Type: text/x-diff, Size: 21336 bytes --]

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

	* df.h (enum debug_temp_where): New.
	(dead_debug_init, dead_debug_finish) Declare.
	(dead_debug_add, dead_debug_insert_temp): Declare.
	(struct dead_debug_use, struct dead_debug): Moved from...
	* df-problems.c: ... here.
	(df_set_unused_notes_for_mw): Bind debug uses of unused regno
	to a debug temp.
	(df_create_unused_note): Likewise.
	(df_set_dead_notes_for_mw): Move comment where it belongs.
	(dead_debug_init): Export.
	(dead_debug_reset_uses): New, factored out of...
	(dead_debug_finish): ...this.  Export.
	(dead_debug_reset): Remove.
	(dead_debug_add): Export.
	(dead_debug_insert_before): Rename to...
	(dead_debug_insert_temp): ... this.  Add where argument.  Export.
	Locate stored value for BEFORE_WITH_VALUE.  Avoid repeat inserts.
	Return insertion count.
	(df_note_bb_compute): Adjust.
	* dce.c (reset_unmarked_insns_debug_uses): New.
	(delete_unmarked_insns): Skip debug insns.
	(prescan_insns_for_dce): Likewise.
	(rest_of_handle_ud_dce): Propagate debug uses.
	(word_dce_process_block): Adjust dead debug uses.
	(dce_process_block): Likewise.
	* 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/df-problems.c
===================================================================
--- gcc/df-problems.c.orig	2011-05-26 05:03:08.545989094 -0300
+++ gcc/df-problems.c	2011-05-26 05:03:28.163028026 -0300
@@ -2842,25 +2842,6 @@ df_whole_mw_reg_unused_p (struct df_mw_h
 }
 
 
-/* Node of a linked list of uses of dead REGs in debug insns.  */
-struct dead_debug_use
-{
-  df_ref use;
-  struct dead_debug_use *next;
-};
-
-/* Linked list of the above, with a bitmap of the REGs in the
-   list.  */
-struct dead_debug
-{
-  struct dead_debug_use *head;
-  bitmap used;
-  bitmap to_rescan;
-};
-
-static void dead_debug_reset (struct dead_debug *, unsigned int);
-
-
 /* Set the REG_UNUSED notes for the multiword hardreg defs in INSN
    based on the bits in LIVE.  Do not generate notes for registers in
    artificial uses.  DO_NOT_GEN is updated so that REG_DEAD notes are
@@ -2886,7 +2867,7 @@ df_set_unused_notes_for_mw (rtx insn, st
     {
       unsigned int regno = mws->start_regno;
       df_set_note (REG_UNUSED, insn, mws->mw_reg);
-      dead_debug_reset (debug, regno);
+      dead_debug_insert_temp (debug, regno, insn, DEBUG_TEMP_AFTER_WITH_REG);
 
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 1: ", insn, REG_NOTES (insn));
@@ -2901,7 +2882,7 @@ df_set_unused_notes_for_mw (rtx insn, st
 	    && !bitmap_bit_p (artificial_uses, r))
 	  {
 	    df_set_note (REG_UNUSED, insn, regno_reg_rtx[r]);
-	    dead_debug_reset (debug, r);
+	    dead_debug_insert_temp (debug, r, insn, DEBUG_TEMP_AFTER_WITH_REG);
 #ifdef REG_DEAD_DEBUGGING
 	    df_print_note ("adding 2: ", insn, REG_NOTES (insn));
 #endif
@@ -2969,12 +2950,12 @@ df_set_dead_notes_for_mw (rtx insn, stru
 
   if (df_whole_mw_reg_dead_p (mws, live, artificial_uses, do_not_gen))
     {
-      /* Add a dead note for the entire multi word register.  */
       if (is_debug)
 	{
 	  *added_notes_p = true;
 	  return;
 	}
+      /* Add a dead note for the entire multi word register.  */
       df_set_note (REG_DEAD, insn, mws->mw_reg);
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 1: ", insn, REG_NOTES (insn));
@@ -3028,7 +3009,7 @@ df_create_unused_note (rtx insn, df_ref 
       rtx reg = (DF_REF_LOC (def))
                 ? *DF_REF_REAL_LOC (def): DF_REF_REG (def);
       df_set_note (REG_UNUSED, insn, reg);
-      dead_debug_reset (debug, dregno);
+      dead_debug_insert_temp (debug, dregno, insn, DEBUG_TEMP_AFTER_WITH_REG);
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 3: ", insn, REG_NOTES (insn));
 #endif
@@ -3039,7 +3020,7 @@ df_create_unused_note (rtx insn, df_ref 
 
 
 /* Initialize DEBUG to an empty list, and clear USED, if given.  */
-static inline void
+void
 dead_debug_init (struct dead_debug *debug, bitmap used)
 {
   debug->head = NULL;
@@ -3049,32 +3030,83 @@ dead_debug_init (struct dead_debug *debu
     bitmap_clear (used);
 }
 
-/* Reset all debug insns with pending uses.  Release the bitmap in it,
-   unless it is USED.  USED must be the same bitmap passed to
-   dead_debug_init.  */
-static inline void
-dead_debug_finish (struct dead_debug *debug, bitmap used)
+/* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of
+   each reset insn.  DEBUG is not otherwise modified.  If HEAD is
+   DEBUG->head, DEBUG->head will be set to NULL at the end.
+   Otherwise, entries from DEBUG->head that pertain to reset insns
+   will be removed, and only then rescanned.  */
+
+static void
+dead_debug_reset_uses (struct dead_debug *debug, struct dead_debug_use *head)
 {
-  struct dead_debug_use *head;
-  rtx insn = NULL;
+  bool got_head = (debug->head == head);
+  bitmap rescan;
+  struct dead_debug_use **tailp = &debug->head;
+  struct dead_debug_use *cur;
+  bitmap_iterator bi;
+  unsigned int uid;
 
-  if (debug->used != used)
-    BITMAP_FREE (debug->used);
+  if (got_head)
+    rescan = NULL;
+  else
+    rescan = BITMAP_ALLOC (NULL);
 
-  while ((head = debug->head))
+  while (head)
     {
+      struct dead_debug_use *next = head->next;
+      rtx insn;
+
       insn = DF_REF_INSN (head->use);
-      if (!head->next || DF_REF_INSN (head->next->use) != insn)
+      if (!next || DF_REF_INSN (next->use) != insn)
 	{
 	  INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
-	  df_insn_rescan_debug_internal (insn);
+	  if (got_head)
+	    df_insn_rescan_debug_internal (insn);
+	  else
+	    bitmap_set_bit (rescan, INSN_UID (insn));
 	  if (debug->to_rescan)
 	    bitmap_clear_bit (debug->to_rescan, INSN_UID (insn));
 	}
-      debug->head = head->next;
       XDELETE (head);
+      head = next;
     }
 
+  if (got_head)
+    {
+      debug->head = NULL;
+      return;
+    }
+
+  while ((cur = *tailp))
+    if (bitmap_bit_p (rescan, INSN_UID (DF_REF_INSN (cur->use))))
+      {
+	*tailp = cur->next;
+	XDELETE (cur);
+      }
+    else
+      tailp = &cur->next;
+
+  EXECUTE_IF_SET_IN_BITMAP (rescan, 0, uid, bi)
+    {
+      struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
+      if (insn_info)
+	df_insn_rescan_debug_internal (insn_info->insn);
+    }
+
+  BITMAP_FREE (rescan);
+}
+
+/* Reset all debug insns with pending uses.  Release the bitmap in it,
+   unless it is USED.  USED must be the same bitmap passed to
+   dead_debug_init.  */
+void
+dead_debug_finish (struct dead_debug *debug, bitmap used)
+{
+  if (debug->used != used)
+    BITMAP_FREE (debug->used);
+
+  dead_debug_reset_uses (debug, debug->head);
+
   if (debug->to_rescan)
     {
       bitmap_iterator bi;
@@ -3090,37 +3122,9 @@ dead_debug_finish (struct dead_debug *de
     }
 }
 
-/* Reset DEBUG_INSNs with pending uses of DREGNO.  */
-static void
-dead_debug_reset (struct dead_debug *debug, unsigned int dregno)
-{
-  struct dead_debug_use **tailp = &debug->head;
-  struct dead_debug_use *cur;
-  rtx insn;
-
-  if (!debug->used || !bitmap_clear_bit (debug->used, dregno))
-    return;
-
-  while ((cur = *tailp))
-    {
-      if (DF_REF_REGNO (cur->use) == dregno)
-	{
-	  *tailp = cur->next;
-	  insn = DF_REF_INSN (cur->use);
-	  INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
-	  if (debug->to_rescan == NULL)
-	    debug->to_rescan = BITMAP_ALLOC (NULL);
-	  bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
-	  XDELETE (cur);
-	}
-      else
-	tailp = &(*tailp)->next;
-    }
-}
-
 /* Add USE to DEBUG.  It must be a dead reference to UREGNO in a debug
    insn.  Create a bitmap for DEBUG as needed.  */
-static inline void
+void
 dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno)
 {
   struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
@@ -3136,12 +3140,15 @@ dead_debug_add (struct dead_debug *debug
 }
 
 /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
-   before INSN that binds the REG to a debug temp, and replace all
-   uses of UREGNO in DEBUG with uses of the debug temp.  INSN must be
-   the insn where UREGNO dies.  */
-static inline void
-dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno,
-			  rtx insn)
+   before or after INSN (depending on WHERE), that binds a debug temp
+   to the widest-mode use of UREGNO, if WHERE is _WITH_REG, or
+   _WITH_VALUE otherwise, and replace all uses of UREGNO in DEBUG with
+   uses of the debug temp.  INSN must be where UREGNO dies, if WHERE
+   is DEAD_DEBUG_BEFORE_WITH_REG, or where it is set otherwise.
+   Return the number of debug insns emitted.  */
+int
+dead_debug_insert_temp (struct dead_debug *debug, unsigned int uregno,
+			rtx insn, enum debug_temp_where where)
 {
   struct dead_debug_use **tailp = &debug->head;
   struct dead_debug_use *cur;
@@ -3152,7 +3159,7 @@ dead_debug_insert_before (struct dead_de
   rtx bind;
 
   if (!debug->used || !bitmap_clear_bit (debug->used, uregno))
-    return;
+    return 0;
 
   /* Move all uses of uregno from debug->head to uses, setting mode to
      the widest referenced mode.  */
@@ -3173,17 +3180,100 @@ dead_debug_insert_before (struct dead_de
 	tailp = &(*tailp)->next;
     }
 
-  gcc_assert (reg);
+  if (!reg)
+    {
+      gcc_checking_assert (!uses);
+      return 0;
+    }
+
+  gcc_checking_assert (uses);
+
+  bind = reg;
+  if (where == DEBUG_TEMP_BEFORE_WITH_VALUE)
+    {
+      rtx set = single_set (insn);
+      rtx dest, src;
+
+      if (set)
+	{
+	  dest = SET_DEST (set);
+	  src = SET_SRC (set);
+	  if (GET_CODE (src) == CALL)
+	    {
+	      while (uses)
+		{
+		  cur = uses->next;
+		  XDELETE (uses);
+		  uses = cur;
+		}
+	      return 0;
+	    }
+	}
+      else
+	set = NULL;
+
+      if (!set)
+	bind = NULL;
+      else if (dest == reg)
+	bind = copy_rtx (src);
+      else if (REG_P (dest))
+	{
+	  if (REGNO (dest) != REGNO (reg))
+	    bind = NULL;
+	  else
+	    bind = lowpart_subreg (GET_MODE (reg), copy_rtx (src),
+				   GET_MODE (dest));
+	}
+      else if (GET_CODE (dest) == SUBREG)
+	{
+	  if (REGNO (SUBREG_REG (dest)) != REGNO (reg))
+	    bind = NULL;
+	  else if (!subreg_lowpart_p (dest))
+	    bind = NULL;
+	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
+		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
+		       == hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
+	    bind = NULL;
+	  else
+	    bind = lowpart_subreg (GET_MODE (reg), copy_rtx (src),
+				   GET_MODE (dest));
+	}
+      else
+	bind = NULL;
+
+      if (!bind)
+	{
+	  dead_debug_reset_uses (debug, uses);
+	  return 0;
+	}
+    }
+
+  /* If there's a single (debug) use of an otherwise unused REG, and
+     the debug use is not part of a larger expression, then it
+     probably doesn't make sense to introduce a new debug temp.  */
+  if (where == DEBUG_TEMP_AFTER_WITH_REG && !uses->next)
+    {
+      rtx next = DF_REF_INSN (uses->use);
+
+      if (DEBUG_INSN_P (next) && reg == INSN_VAR_LOCATION_LOC (next))
+	{
+	  XDELETE (uses);
+	  return 0;
+	}
+    }
 
   /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
   dval = make_debug_expr_from_rtl (reg);
 
   /* Emit a debug bind insn before the insn in which reg dies.  */
   bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
-			       DEBUG_EXPR_TREE_DECL (dval), reg,
+			       DEBUG_EXPR_TREE_DECL (dval), bind,
 			       VAR_INIT_STATUS_INITIALIZED);
 
-  bind = emit_debug_insn_before (bind, insn);
+  if (where == DEBUG_TEMP_AFTER_WITH_REG)
+    bind = emit_debug_insn_after (bind, insn);
+  else
+    bind = emit_debug_insn_before (bind, insn);
   df_insn_rescan (bind);
 
   /* Adjust all uses.  */
@@ -3201,6 +3291,8 @@ dead_debug_insert_before (struct dead_de
       uses = cur->next;
       XDELETE (cur);
     }
+
+  return 1;
 }
 
 /* Recompute the REG_DEAD and REG_UNUSED notes and compute register
@@ -3395,7 +3487,8 @@ df_note_bb_compute (unsigned int bb_inde
 		  break;
 		}
 	      else
-		dead_debug_insert_before (&debug, uregno, insn);
+		dead_debug_insert_temp (&debug, uregno, insn,
+					DEBUG_TEMP_BEFORE_WITH_REG);
 
 	      if ( (!(DF_REF_FLAGS (use)
 		      & (DF_REF_MW_HARDREG | DF_REF_READ_WRITE)))
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);
@@ -767,6 +807,7 @@ word_dce_process_block (basic_block bb, 
   bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
   rtx insn;
   bool block_changed;
+  struct dead_debug debug;
 
   if (redo_out)
     {
@@ -788,11 +829,24 @@ word_dce_process_block (basic_block bb, 
     }
 
   bitmap_copy (local_live, DF_WORD_LR_OUT (bb));
+  dead_debug_init (&debug, NULL);
 
   FOR_BB_INSNS_REVERSE (bb, insn)
-    if (NONDEBUG_INSN_P (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)))
+		  == 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));
+      }
+    else if (INSN_P (insn))
       {
 	bool any_changed;
+
 	/* No matter if the instruction is needed or not, we remove
 	   any regno in the defs from the live set.  */
 	any_changed = df_word_lr_simulate_defs (insn, local_live);
@@ -804,6 +858,15 @@ word_dce_process_block (basic_block bb, 
 	if (marked_insn_p (insn))
 	  df_word_lr_simulate_uses (insn, local_live);
 
+	if (debug.used && !bitmap_empty_p (debug.used))
+	  {
+	    df_ref *def_rec;
+
+	    for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+	      dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
+				      DEBUG_TEMP_BEFORE_WITH_VALUE);
+	  }
+
 	if (dump_file)
 	  {
 	    fprintf (dump_file, "finished processing insn %d live out = ",
@@ -816,6 +879,7 @@ word_dce_process_block (basic_block bb, 
   if (block_changed)
     bitmap_copy (DF_WORD_LR_IN (bb), local_live);
 
+  dead_debug_finish (&debug, NULL);
   BITMAP_FREE (local_live);
   return block_changed;
 }
@@ -833,6 +897,7 @@ dce_process_block (basic_block bb, bool 
   rtx insn;
   bool block_changed;
   df_ref *def_rec;
+  struct dead_debug debug;
 
   if (redo_out)
     {
@@ -856,22 +921,36 @@ dce_process_block (basic_block bb, bool 
   bitmap_copy (local_live, DF_LR_OUT (bb));
 
   df_simulate_initialize_backwards (bb, local_live);
+  dead_debug_init (&debug, NULL);
 
   FOR_BB_INSNS_REVERSE (bb, insn)
-    if (INSN_P (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));
+      }
+    else if (INSN_P (insn))
       {
 	bool needed = marked_insn_p (insn);
 
 	/* 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)))
-	      {
-		needed = true;
-		mark_insn (insn, true);
-		break;
-	      }
+	    {
+	      dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
+				      DEBUG_TEMP_BEFORE_WITH_VALUE);
+
+	      if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec))
+		  || bitmap_bit_p (au, DF_REF_REGNO (*def_rec)))
+		{
+		  needed = true;
+		  mark_insn (insn, true);
+		  break;
+		}
+	    }
 
 	/* No matter if the instruction is needed or not, we remove
 	   any regno in the defs from the live set.  */
@@ -883,6 +962,7 @@ dce_process_block (basic_block bb, bool 
 	  df_simulate_uses (insn, local_live);
       }
 
+  dead_debug_finish (&debug, NULL);
   df_simulate_finalize_backwards (bb, local_live);
 
   block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
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);
 	}
     }
 
Index: gcc/df.h
===================================================================
--- gcc/df.h.orig	2011-05-26 05:03:08.555989114 -0300
+++ gcc/df.h	2011-05-26 05:03:28.170028039 -0300
@@ -1101,4 +1101,35 @@ extern void union_defs (df_ref, struct w
 			unsigned int *used, struct web_entry *,
 			bool (*fun) (struct web_entry *, struct web_entry *));
 
+/* Debug uses of dead regs.  */
+
+/* Node of a linked list of uses of dead REGs in debug insns.  */
+struct dead_debug_use
+{
+  df_ref use;
+  struct dead_debug_use *next;
+};
+
+/* Linked list of the above, with a bitmap of the REGs in the
+   list.  */
+struct dead_debug
+{
+  struct dead_debug_use *head;
+  bitmap used;
+  bitmap to_rescan;
+};
+
+enum debug_temp_where
+  {
+    DEBUG_TEMP_BEFORE_WITH_REG = -1,
+    DEBUG_TEMP_BEFORE_WITH_VALUE = 0,
+    DEBUG_TEMP_AFTER_WITH_REG = 1
+  };
+
+void dead_debug_init (struct dead_debug *, bitmap);
+void dead_debug_finish (struct dead_debug *, bitmap);
+void dead_debug_add (struct dead_debug *, df_ref, unsigned int);
+int dead_debug_insert_temp (struct dead_debug *, unsigned int, rtx,
+			    enum debug_temp_where);
+
 #endif /* GCC_DF_H */

[-- Attachment #3: Type: text/plain, Size: 258 bytes --]



-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

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

end of thread, other threads:[~2012-07-02 12:29 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-30 12:15 fix left-over debug insns in DCE Alexandre Oliva
2011-06-02 15:26 ` Eric Botcazou
2011-06-03  1:16   ` Alexandre Oliva
2011-06-03 11:06     ` Eric Botcazou
2011-06-06  5:38       ` Alexandre Oliva
2011-06-06  6:05         ` Jakub Jelinek
2011-06-06  8:00         ` Eric Botcazou
2011-06-06 10:07           ` Alexandre Oliva
2011-06-06 13:28           ` Alexandre Oliva
2011-06-07 12:25             ` [PATCH] Fix ICE in reset_unmarked_insns_debug_uses (PR middle-end/49308) Jakub Jelinek
2011-06-09  8:04               ` Jakub Jelinek
2012-04-09  6:14             ` fix left-over debug insns in DCE Alexandre Oliva
2012-04-09 13:42               ` Eric Botcazou
2012-04-13 15:59                 ` Alexandre Oliva
2012-04-13 16:45                   ` Paolo Bonzini
2012-05-03 18:27                     ` [PR52983] eliminate autoinc from debug_insn locs (was: Re: fix left-over debug insns in DCE) Alexandre Oliva
2012-05-03 22:40                       ` [PR52983] eliminate autoinc from debug_insn locs Alexandre Oliva
2012-06-13  8:01                         ` Alexandre Oliva
2012-07-02 12:29                           ` Alexandre Oliva
2012-05-03 22:46                       ` [PR52983, PR48866] " Alexandre Oliva
2012-06-13  8:56                         ` Alexandre Oliva
2012-06-13  9:15                           ` Jakub Jelinek
2011-06-06  7:11       ` fix left-over debug insns in DCE Alexandre Oliva

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).