re PR debug/48866 (gcc hangs when -g is set)
authorAlexandre Oliva <aoliva@redhat.com>
Fri, 13 Apr 2012 15:56:21 +0000 (15:56 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Fri, 13 Apr 2012 15:56:21 +0000 (15:56 +0000)
PR debug/48866
* 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 (word_dce_process_block): Adjust dead debug uses.
(dce_process_block): Likewise.

From-SVN: r186422

gcc/ChangeLog
gcc/dce.c
gcc/df-problems.c
gcc/df.h

index c099a2c..c0df521 100644 (file)
@@ -1,5 +1,30 @@
 2012-04-13  Alexandre Oliva  <aoliva@redhat.com>
 
+       PR debug/48866
+       * 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 (word_dce_process_block): Adjust dead debug uses.
+       (dce_process_block): Likewise.
+
+2012-04-13  Alexandre Oliva  <aoliva@redhat.com>
+
        * df-problems.c (df_note_bb_compute): Do not take note of
        debug uses for whose REGs we won't emit DEAD or UNUSED notes.
 
index a36ac61..c706296 100644 (file)
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -807,6 +807,7 @@ word_dce_process_block (basic_block bb, bool redo_out)
   bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
   rtx insn;
   bool block_changed;
+  struct dead_debug debug;
 
   if (redo_out)
     {
@@ -828,11 +829,24 @@ word_dce_process_block (basic_block bb, bool redo_out)
     }
 
   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);
@@ -844,6 +858,15 @@ word_dce_process_block (basic_block bb, bool redo_out)
        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 = ",
@@ -856,6 +879,7 @@ word_dce_process_block (basic_block bb, bool redo_out)
   if (block_changed)
     bitmap_copy (DF_WORD_LR_IN (bb), local_live);
 
+  dead_debug_finish (&debug, NULL);
   BITMAP_FREE (local_live);
   return block_changed;
 }
@@ -873,6 +897,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
   rtx insn;
   bool block_changed;
   df_ref *def_rec;
+  struct dead_debug debug;
 
   if (redo_out)
     {
@@ -896,22 +921,36 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
   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.  */
@@ -923,6 +962,7 @@ dce_process_block (basic_block bb, bool redo_out, bitmap au)
          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 6912e11..e04dace 100644 (file)
@@ -2886,25 +2886,6 @@ df_whole_mw_reg_unused_p (struct df_mw_hardreg *mws,
 }
 
 
-/* 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
@@ -2930,7 +2911,7 @@ df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
     {
       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));
@@ -2945,7 +2926,7 @@ df_set_unused_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
            && !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
@@ -3013,12 +2994,12 @@ df_set_dead_notes_for_mw (rtx insn, struct df_mw_hardreg *mws,
 
   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));
@@ -3072,7 +3053,7 @@ df_create_unused_note (rtx insn, df_ref def,
       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
@@ -3083,7 +3064,7 @@ df_create_unused_note (rtx insn, df_ref def,
 
 
 /* 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;
@@ -3093,32 +3074,83 @@ dead_debug_init (struct dead_debug *debug, bitmap used)
     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;
@@ -3134,54 +3166,9 @@ dead_debug_finish (struct dead_debug *debug, bitmap used)
     }
 }
 
-/* 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 **insnp = &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);
-         /* If the current use isn't the first one attached to INSN, go back
-            to this first use.  We assume that the uses attached to an insn
-            are adjacent.  */                                                                       
-         if (tailp != insnp && DF_REF_INSN ((*insnp)->use) == insn)
-           tailp = insnp;
-         /* Then remove all the other uses attached to INSN.  */
-         while ((cur = *tailp) && DF_REF_INSN (cur->use) == insn)
-           {
-             *tailp = cur->next;
-             XDELETE (cur);
-           }
-         insnp = tailp;
-       }
-      else
-       {
-         if (DF_REF_INSN ((*insnp)->use) != DF_REF_INSN (cur->use))
-           insnp = tailp;
-         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);
@@ -3197,23 +3184,27 @@ dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno)
 }
 
 /* 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 the
+   value stored in UREGNO by INSN otherwise, and replace all uses of
+   UREGNO in DEBUG with uses of the debug temp.  INSN must be where
+   UREGNO dies, if WHERE is *_BEFORE_*, 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;
   struct dead_debug_use *uses = NULL;
   struct dead_debug_use **usesp = &uses;
   rtx reg = NULL;
+  rtx breg;
   rtx dval;
   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.  */
@@ -3237,17 +3228,114 @@ dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno,
   /* We may have dangling bits in debug->used for registers that were part
      of a multi-register use, one component of which has been reset.  */
   if (reg == NULL)
-    return;
+    {
+      gcc_checking_assert (!uses);
+      return 0;
+    }
+
+  gcc_checking_assert (uses);
+
+  breg = reg;
+  /* Recover the expression INSN stores in 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);
+         /* Lose if the REG-setting insn is a CALL.  */
+         if (GET_CODE (src) == CALL)
+           {
+             while (uses)
+               {
+                 cur = uses->next;
+                 XDELETE (uses);
+                 uses = cur;
+               }
+             return 0;
+           }
+       }
+
+      /* ??? Should we try to extract it from a PARALLEL?  */
+      if (!set)
+       breg = NULL;
+      /* Cool, it's the same REG, we can use SRC.  */
+      else if (dest == reg)
+       breg = copy_rtx (src);
+      else if (REG_P (dest))
+       {
+         /* Hmm...  Something's fishy, we should be setting REG here.  */
+         if (REGNO (dest) != REGNO (reg))
+           breg = NULL;
+         /* Ok, it's the same (hardware) REG, but with a different
+            mode, so SUBREG it.  */
+         else
+           breg = lowpart_subreg (GET_MODE (reg), copy_rtx (src),
+                                  GET_MODE (dest));
+       }
+      else if (GET_CODE (dest) == SUBREG)
+       {
+         /* We should be setting REG here.  Lose.  */
+         if (REGNO (SUBREG_REG (dest)) != REGNO (reg))
+           breg = NULL;
+         /* Lose if we're setting something other than the lowpart of
+            REG.  */
+         else if (!subreg_lowpart_p (dest))
+           breg = NULL;
+         /* If we're not overwriting all the hardware registers that
+            setting REG in its mode would, we won't know what to bind
+            the debug temp to.  */
+         else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
+                  && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
+                      != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
+           breg = NULL;
+         /* Yay, we can use SRC, just adjust its mode.  */
+         else
+           breg = lowpart_subreg (GET_MODE (reg), copy_rtx (src),
+                                  GET_MODE (dest));
+       }
+      /* Oh well, we're out of luck.  */
+      else
+       breg = NULL;
+
+      /* We couldn't figure out the value stored in REG, so reset all
+        of its pending debug uses.  */
+      if (!breg)
+       {
+         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), breg,
                               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.  */
@@ -3265,6 +3353,8 @@ dead_debug_insert_before (struct dead_debug *debug, unsigned int uregno,
       uses = cur->next;
       XDELETE (cur);
     }
+
+  return 1;
 }
 
 /* Recompute the REG_DEAD and REG_UNUSED notes and compute register
@@ -3464,7 +3554,8 @@ df_note_bb_compute (unsigned int bb_index,
                  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 aec9788..c0fabb9 100644 (file)
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -1101,4 +1101,46 @@ extern void union_defs (df_ref, struct web_entry *,
                        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;
+};
+
+/* This type controls the behavior of dead_debug_insert_temp WRT
+   UREGNO and INSN.  */
+enum debug_temp_where
+  {
+    /* Bind a newly-created debug temporary to a REG for UREGNO, and
+       insert the debug insn before INSN.  REG is expected to die at
+       INSN.  */
+    DEBUG_TEMP_BEFORE_WITH_REG = -1,
+    /* Bind a newly-created debug temporary to the value INSN stores
+       in REG, and insert the debug insn before INSN.  */
+    DEBUG_TEMP_BEFORE_WITH_VALUE = 0,
+    /* Bind a newly-created debug temporary to a REG for UREGNO, and
+       insert the debug insn after INSN.  REG is expected to be set at
+       INSN.  */
+    DEBUG_TEMP_AFTER_WITH_REG = 1
+  };
+
+extern void dead_debug_init (struct dead_debug *, bitmap);
+extern void dead_debug_finish (struct dead_debug *, bitmap);
+extern void dead_debug_add (struct dead_debug *, df_ref, unsigned int);
+extern int dead_debug_insert_temp (struct dead_debug *,
+                                  unsigned int uregno, rtx insn,
+                                  enum debug_temp_where);
+
 #endif /* GCC_DF_H */