summaryrefslogtreecommitdiff
path: root/gcc/df-problems.c
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-02 00:34:11 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2012-08-02 00:34:11 +0000
commite663775373e9fff81e57536eb860c28985a57c43 (patch)
treee8586f90b0101adcc1ada9b7625fd4d25cb71a67 /gcc/df-problems.c
parent51d6c5165bdb8b26855bdbd8c0fec7e3a8565af2 (diff)
downloadgcc-e663775373e9fff81e57536eb860c28985a57c43.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190061 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/df-problems.c')
-rw-r--r--gcc/df-problems.c307
1 files changed, 1 insertions, 306 deletions
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index d572b0f73b9..8699304e038 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. */