diff mbox

Fix dead_debug_* ICE (PR debug/46171)

Message ID 20101027135019.GD29412@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 27, 2010, 1:50 p.m. UTC
Hi!

We have RTL like:
   (insn 6 3 7 2 (set (reg:SF 21 xmm0)
           (reg/v:SF 61 [ f ])) pr46171.c:7 110 {*movsf_internal}
        (nil))
   (call_insn 7 6 17 2 (set (reg:SF 21 xmm0)
           (call (mem:QI (symbol_ref:DI ("barf") [flags 0x41] <function_decl 0x7ffff16d1000 barf>) [0 S1 A8])
               (const_int 0 [0]))) pr46171.c:7 883 {*call_value_0_rex64}
        (nil)
       (expr_list:REG_DEP_TRUE (use (reg:SF 21 xmm0))
           (nil)))
   (debug_insn 17 7 9 2 (var_location:SF D#2 (reg:SF 21 xmm0)) -1
        (nil))
   (debug_insn 9 17 10 2 (var_location:SF f (debug_expr:SF D#2)) pr46171.c:7 -1
        (nil))
   (insn 10 9 11 2 (set (reg:QI 0 ax)
           (const_int 0 [0])) pr46171.c:8 66 {*movqi_internal}
        (nil))
   (call_insn 11 10 16 2 (set (reg:DF 21 xmm0)
           (call (mem:QI (symbol_ref:DI ("bard") [flags 0x41] <function_decl 0x7ffff16b2f00 bard>) [0 S1 A8])
               (const_int 0 [0]))) pr46171.c:8 883 {*call_value_0_rex64}
        (expr_list:REG_UNUSED (reg:DF 21 xmm0)		<---
           (nil))
       (expr_list:REG_DEP_TRUE (use (reg:QI 0 ax))
           (nil)))
   (debug_insn 16 11 13 2 (var_location:DF D#1 (reg:DF 21 xmm0)) -1
        (nil))
   (debug_insn 13 16 0 2 (var_location:DF d (debug_expr:DF D#1)) pr46171.c:8 -1
        (nil))

DF wants to add REG_UNUSED note, as xmm0 is never used afterwards and thus should
be live just on a single insn.  We don't do anything with the queued dead_debug
references though, and up mixing DFmode xmm0 with SFmode xmm0 and ICE on trying to
do a SFmode SUBREG from DFmode DEBUG_EXPR.

Fixed by making sure we reset things when we are creating REG_UNUSED notes.

Bootstrapped/regtested on x86_64-linux and i686-linux, dwarflint --check=locstats

	Jakub
diff mbox

Patch

differences are in the noise (+-3 vars at most in any single 10% coverage range).

Ok for trunk?

2010-10-27  Jakub Jelinek  <jakub@redhat.com>

	PR debug/46171
	* df-problems.c (struct dead_debug_use, struct dead_debug): Move
	earlier.
	(df_set_unused_notes_for_mw, df_create_unused_note): Add DEBUG
	argument, call dead_debug_reset when adding REG_UNUSED note.
	(dead_debug_reset): New function.
	(df_note_bb_compute): Adjust df_set_unused_notes_for_mw and
	df_create_unused_note callers.

	* gcc.dg/pr46171.c: New test.

--- gcc/df-problems.c.jj	2010-10-27 05:49:24.450716761 +0200
+++ gcc/df-problems.c	2010-10-27 13:37:48.178386128 +0200
@@ -2838,6 +2838,26 @@  df_whole_mw_reg_unused_p (struct df_mw_h
   return true;
 }
 
+
+/* 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
@@ -2848,7 +2868,8 @@  df_whole_mw_reg_unused_p (struct df_mw_h
 static void
 df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
 			    bitmap live, bitmap do_not_gen,
-			    bitmap artificial_uses)
+			    bitmap artificial_uses,
+			    struct dead_debug *debug)
 {
   unsigned int r;
 
@@ -2862,6 +2883,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);
 
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 1: ", insn, REG_NOTES (insn));
@@ -2876,6 +2898,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);
 #ifdef REG_DEAD_DEBUGGING
 	    df_print_note ("adding 2: ", insn, REG_NOTES (insn));
 #endif
@@ -2981,7 +3007,8 @@  df_set_dead_notes_for_mw (rtx insn, stru
 
 static void
 df_create_unused_note (rtx insn, df_ref def,
-		       bitmap live, bitmap artificial_uses)
+		       bitmap live, bitmap artificial_uses,
+		       struct dead_debug *debug)
 {
   unsigned int dregno = DF_REF_REGNO (def);
 
@@ -3001,6 +3028,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);
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 3: ", insn, REG_NOTES (insn));
 #endif
@@ -3009,21 +3037,6 @@  df_create_unused_note (rtx insn, df_ref 
   return;
 }
 
-/* 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;
-};
 
 /* Initialize DEBUG to an empty list, and clear USED, if given.  */
 static inline void
@@ -3077,6 +3090,34 @@  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
@@ -3259,7 +3299,7 @@  df_note_bb_compute (unsigned int bb_inde
 		  && !df_ignore_stack_reg (mws->start_regno))
 	      df_set_unused_notes_for_mw (insn,
 					  mws, live, do_not_gen,
-					  artificial_uses);
+					  artificial_uses, &debug);
 	      mws_rec++;
 	    }
 
@@ -3272,7 +3312,7 @@  df_note_bb_compute (unsigned int bb_inde
 	      if (!DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
 		{
 		  df_create_unused_note (insn,
-					 def, live, artificial_uses);
+					 def, live, artificial_uses, &debug);
 		  bitmap_set_bit (do_not_gen, dregno);
 		}
 
@@ -3290,7 +3330,7 @@  df_note_bb_compute (unsigned int bb_inde
 	      if (DF_MWS_REG_DEF_P (mws))
 		df_set_unused_notes_for_mw (insn,
 					    mws, live, do_not_gen,
-					    artificial_uses);
+					    artificial_uses, &debug);
 	      mws_rec++;
 	    }
 
@@ -3299,7 +3339,7 @@  df_note_bb_compute (unsigned int bb_inde
 	      df_ref def = *def_rec;
 	      unsigned int dregno = DF_REF_REGNO (def);
 	      df_create_unused_note (insn,
-				     def, live, artificial_uses);
+				     def, live, artificial_uses, &debug);
 
 	      if (!DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))
 		bitmap_set_bit (do_not_gen, dregno);
--- gcc/testsuite/gcc.dg/pr46171.c.jj	2010-10-27 13:16:35.363248051 +0200
+++ gcc/testsuite/gcc.dg/pr46171.c	2010-10-27 13:16:16.000000000 +0200
@@ -0,0 +1,13 @@ 
+/* PR debug/46171 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-dce -g" } */
+
+double bard ();
+float barf (float);
+
+void
+foo (float f)
+{
+  f = barf (f);
+  double d = bard ();
+}