summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/df-problems.c142
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/varasm.c27
4 files changed, 183 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d751d2dbcc..89487f7aa52 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2010-05-05 Alexandre Oliva <aoliva@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/43478
+ * df-problems.c (struct dead_debug_use, struct dead_debug): New.
+ (dead_debug_init, dead_debug_finish): New functions.
+ (dead_debug_add, dead_debug_insert_before): Likewise.
+ (df_note_bb_compute): Initialize a dead_debug object, add dead
+ debug uses to it, insert debug bind insns before death insns,
+ reset debug insns that refer to pending uses at the end.
+ * rtl.h (make_debug_expr_from_rtl): New prototype.
+ * varasm.c (make_debug_expr_from_rtl): New function.
+
2010-05-05 Jan Hubicka <jh@suse.cz>
* lto-cgraph.c (output_varpool): Forward declare; work on encoder.
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index dbb469e1e2f..5f908da07ef 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -3403,6 +3403,138 @@ df_create_unused_note (rtx insn, rtx old, df_ref def,
return old;
}
+/* 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;
+};
+
+/* Initialize DEBUG to an empty list, and clear USED, if given. */
+static inline void
+dead_debug_init (struct dead_debug *debug, bitmap used)
+{
+ debug->head = NULL;
+ debug->used = used;
+ if (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)
+{
+ struct dead_debug_use *head;
+ rtx insn = NULL;
+
+ if (debug->used != used)
+ BITMAP_FREE (debug->used);
+
+ while ((head = debug->head))
+ {
+ insn = DF_REF_INSN (head->use);
+ if (!head->next || DF_REF_INSN (head->next->use) != insn)
+ {
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+ df_insn_rescan_debug_internal (insn);
+ }
+ debug->head = head->next;
+ XDELETE (head);
+ }
+}
+
+/* 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
+dead_debug_add (struct dead_debug *debug, df_ref use, unsigned int uregno)
+{
+ struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
+
+ newddu->use = use;
+ newddu->next = debug->head;
+ debug->head = newddu;
+
+ if (!debug->used)
+ debug->used = BITMAP_ALLOC (NULL);
+
+ bitmap_set_bit (debug->used, 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)
+{
+ 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 dval;
+ rtx bind;
+
+ if (!debug->used || !bitmap_clear_bit (debug->used, uregno))
+ return;
+
+ /* Move all uses of uregno from debug->head to uses, setting mode to
+ the widest referenced mode. */
+ while ((cur = *tailp))
+ {
+ if (DF_REF_REGNO (cur->use) == uregno)
+ {
+ *usesp = cur;
+ usesp = &cur->next;
+ *tailp = cur->next;
+ cur->next = NULL;
+ if (!reg
+ || (GET_MODE_BITSIZE (GET_MODE (reg))
+ < GET_MODE_BITSIZE (GET_MODE (DF_REF_REAL_REG (cur->use)))))
+ reg = DF_REF_REAL_REG (cur->use);
+ }
+ else
+ tailp = &(*tailp)->next;
+ }
+
+ gcc_assert (reg);
+
+ /* 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,
+ VAR_INIT_STATUS_INITIALIZED);
+
+ bind = emit_debug_insn_before (bind, insn);
+ df_insn_rescan (bind);
+
+ /* Adjust all uses. */
+ while ((cur = uses))
+ {
+ if (GET_MODE (DF_REF_REAL_REG (cur->use)) == GET_MODE (reg))
+ *DF_REF_REAL_LOC (cur->use) = dval;
+ else
+ *DF_REF_REAL_LOC (cur->use)
+ = gen_lowpart_SUBREG (GET_MODE (DF_REF_REAL_REG (cur->use)), dval);
+ /* ??? Should we simplify subreg of subreg? */
+ df_insn_rescan (DF_REF_INSN (cur->use));
+ uses = cur->next;
+ XDELETE (cur);
+ }
+}
/* Recompute the REG_DEAD and REG_UNUSED notes and compute register
info: lifetime, bb, and number of defs and uses for basic block
@@ -3416,6 +3548,9 @@ df_note_bb_compute (unsigned int bb_index,
rtx insn;
df_ref *def_rec;
df_ref *use_rec;
+ struct dead_debug debug;
+
+ dead_debug_init (&debug, NULL);
bitmap_copy (live, df_get_live_out (bb));
bitmap_clear (artificial_uses);
@@ -3592,9 +3727,12 @@ df_note_bb_compute (unsigned int bb_index,
{
if (debug_insn)
{
- debug_insn = -1;
+ if (debug_insn > 0)
+ dead_debug_add (&debug, use, uregno);
break;
}
+ else
+ dead_debug_insert_before (&debug, uregno, insn);
if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG))
&& (!bitmap_bit_p (do_not_gen, uregno))
@@ -3636,6 +3774,8 @@ df_note_bb_compute (unsigned int bb_index,
df_insn_rescan_debug_internal (insn);
}
}
+
+ dead_debug_finish (&debug, NULL);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index fe17ae7cba5..88c0abf6204 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2382,6 +2382,8 @@ extern rtx emit_library_call_value (rtx, rtx, enum libcall_type,
extern void init_varasm_once (void);
extern enum tls_model decl_default_tls_model (const_tree);
+extern rtx make_debug_expr_from_rtl (const_rtx);
+
/* In rtl.c */
extern void traverse_md_constants (int (*) (void **, void *), void *);
struct md_constant { char *name, *value; };
diff --git a/gcc/varasm.c b/gcc/varasm.c
index bcb5b114238..9f2f0a6f957 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7261,4 +7261,31 @@ default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
maybe_assemble_visibility (decl);
}
+/* Create a DEBUG_EXPR_DECL / DEBUG_EXPR pair from RTL expression
+ EXP. */
+rtx
+make_debug_expr_from_rtl (const_rtx exp)
+{
+ tree ddecl = make_node (DEBUG_EXPR_DECL), type;
+ enum machine_mode mode = GET_MODE (exp);
+ rtx dval;
+
+ DECL_ARTIFICIAL (ddecl) = 1;
+ if (REG_P (exp) && REG_EXPR (exp))
+ type = TREE_TYPE (REG_EXPR (exp));
+ else if (MEM_P (exp) && MEM_EXPR (exp))
+ type = TREE_TYPE (MEM_EXPR (exp));
+ else
+ type = NULL_TREE;
+ if (type && TYPE_MODE (type) == mode)
+ TREE_TYPE (ddecl) = type;
+ else
+ TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
+ DECL_MODE (ddecl) = mode;
+ dval = gen_rtx_DEBUG_EXPR (mode);
+ DEBUG_EXPR_TREE_DECL (dval) = ddecl;
+ SET_DECL_RTL (ddecl, dval);
+ return dval;
+}
+
#include "gt-varasm.h"