diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/df-problems.c | 142 | ||||
-rw-r--r-- | gcc/rtl.h | 2 | ||||
-rw-r--r-- | gcc/varasm.c | 27 |
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" |