diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2012-08-02 00:34:11 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2012-08-02 00:34:11 +0000 |
commit | 08df6c0db1dbdeda1e22b16eb83c77ad05f8ba32 (patch) | |
tree | e8586f90b0101adcc1ada9b7625fd4d25cb71a67 /gcc/df-problems.c | |
parent | 57e8ecc3bacd6f3794c535eafc3114b56b40321b (diff) | |
download | gcc-08df6c0db1dbdeda1e22b16eb83c77ad05f8ba32.zip gcc-08df6c0db1dbdeda1e22b16eb83c77ad05f8ba32.tar.gz gcc-08df6c0db1dbdeda1e22b16eb83c77ad05f8ba32.tar.bz2 |
re PR debug/52983 (internal compiler error: in df_uses_record, at df-scan.c:3243)
PR debug/52983
* valtrack.h, valtrack.c: New.
* Makefile.in (VALTRACK_H): New.
(OBJS): Add valtrack.o.
(valtrack.o): New.
(cselib.o, dce.o, df-problems.o, combine.o): Add VALTRACK_H.
* combine.c: Include valtrack.h.
(make_compound_operation): Publish.
(cleanup_auto_inc_dec): Move to valtrack.c.
(struct rtx_subst_pair, propagate_for_debug_subst): Likewise.
(propagate_for_debug): Likewise. Add this_basic_block parameter.
Adjust all callers.
* cselib.c: Include valtrack.h.
* dce.c: Likewise.
* df-problems.c: Likewise.
(dead_debug_init, dead_debug_reset_uses): Move to valtrack.c.
(dead_debug_finish, dead_debug_add): Likewise.
(dead_debug_insert_temp): Likewise.
* df.h (struct dead_debug_use): Move to valtrack.h.
(struct dead_debug, enum debug_temp_where): Likewise.
(dead_debug_init, dead_debug_reset_uses): Move to valtrack.h.
(dead_debug_finish, dead_debug_add): Likewise.
(dead_debug_insert_temp): Likewise.
* rtl.h (make_compound_operation): Declare.
From-SVN: r190061
Diffstat (limited to 'gcc/df-problems.c')
-rw-r--r-- | gcc/df-problems.c | 307 |
1 files changed, 1 insertions, 306 deletions
diff --git a/gcc/df-problems.c b/gcc/df-problems.c index d572b0f..8699304 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "except.h" #include "dce.h" #include "vecprim.h" +#include "valtrack.h" #include "dumpfile.h" /* Note that turning REG_DEAD_DEBUGGING on will cause @@ -3047,312 +3048,6 @@ df_create_unused_note (rtx insn, df_ref def, } -/* Initialize DEBUG to an empty list, and clear USED, if given. */ -void -dead_debug_init (struct dead_debug *debug, bitmap used) -{ - debug->head = NULL; - debug->used = used; - debug->to_rescan = NULL; - if (used) - bitmap_clear (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) -{ - 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 (got_head) - rescan = NULL; - else - rescan = BITMAP_ALLOC (NULL); - - while (head) - { - struct dead_debug_use *next = head->next; - rtx insn; - - insn = DF_REF_INSN (head->use); - if (!next || DF_REF_INSN (next->use) != insn) - { - INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); - 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)); - } - 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; - unsigned int uid; - - EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi) - { - struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid); - if (insn_info) - df_insn_rescan (insn_info->insn); - } - BITMAP_FREE (debug->to_rescan); - } -} - -/* Add USE to DEBUG. It must be a dead reference to UREGNO in a debug - insn. Create a bitmap for DEBUG as needed. */ -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); - - /* ??? If we dealt with split multi-registers below, we should set - all registers for the used mode in case of hardware - registers. */ - bitmap_set_bit (debug->used, uregno); -} - -/* If UREGNO is referenced by any entry in DEBUG, emit a debug 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 0; - - /* 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_LOC (cur->use))))) - reg = *DF_REF_REAL_LOC (cur->use); - } - else - tailp = &(*tailp)->next; - } - - /* 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) - { - 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; - /* 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. ??? We could bind the debug_expr to a - CONCAT or PARALLEL with the split multi-registers, and - replace them as we found the corresponding sets. */ - 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; - /* 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), breg, - VAR_INIT_STATUS_INITIALIZED); - - 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. */ - while ((cur = uses)) - { - if (GET_MODE (*DF_REF_REAL_LOC (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_LOC (cur->use)), dval); - /* ??? Should we simplify subreg of subreg? */ - if (debug->to_rescan == NULL) - debug->to_rescan = BITMAP_ALLOC (NULL); - bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use))); - uses = cur->next; - XDELETE (cur); - } - - return 1; -} - /* Recompute the REG_DEAD and REG_UNUSED notes and compute register info: lifetime, bb, and number of defs and uses for basic block BB. The three bitvectors are scratch regs used here. */ |