This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: VTA merge - rtl compare-debug
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 05 Jun 2009 07:19:58 -0300
- Subject: Re: VTA merge - rtl compare-debug
- References: <orws7r6lmg.fsf@free.oliva.athome.lsd.ic.unicamp.br> <orskif6lc9.fsf@free.oliva.athome.lsd.ic.unicamp.br>
rtl-compare-debug (53K) - fix -fcompare-debug errors that showed up in the
presence of debug insns
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c.orig 2009-06-05 04:56:43.000000000 -0300
+++ gcc/regrename.c 2009-06-05 05:03:03.000000000 -0300
@@ -265,6 +265,7 @@ regrename_optimize (void)
n_uses = 0;
for (last = this_du; last->next_use; last = last->next_use)
{
+ /* ??? Do we need to discount debug insns here? */
n_uses++;
IOR_COMPL_HARD_REG_SET (this_unavailable,
reg_class_contents[last->cl]);
@@ -819,7 +820,8 @@ build_def_use (basic_block bb)
*recog_data.dup_loc[i] = cc0_rtx;
}
- scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
+ scan_rtx (insn, &PATTERN (insn), NO_REGS,
+ DEBUG_INSN_P (insn) ? mark_access : terminate_all_read,
OP_IN, 0);
for (i = 0; i < recog_data.n_dups; i++)
Index: gcc/ira-conflicts.c
===================================================================
--- gcc/ira-conflicts.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/ira-conflicts.c 2009-06-05 05:08:11.000000000 -0300
@@ -522,7 +522,7 @@ add_copies (ira_loop_tree_node_t loop_tr
if (bb == NULL)
return;
FOR_BB_INSNS (bb, insn)
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
add_insn_allocno_copies (insn);
}
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/regstat.c 2009-06-05 05:08:11.000000000 -0300
@@ -61,11 +61,27 @@ regstat_init_n_sets_and_refs (void)
regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno);
- for (i = 0; i < max_regno; i++)
- {
- SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
- SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
- }
+ if (MAY_HAVE_DEBUG_INSNS)
+ for (i = 0; i < max_regno; i++)
+ {
+ int use_count;
+ df_ref use;
+
+ use_count = DF_REG_USE_COUNT (i);
+ for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
+ if (DF_REF_INSN_INFO (use) && DEBUG_INSN_P (DF_REF_INSN (use)))
+ use_count--;
+
+
+ SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+ SET_REG_N_REFS (i, use_count + REG_N_SETS (i));
+ }
+ else
+ for (i = 0; i < max_regno; i++)
+ {
+ SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+ SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
+ }
timevar_pop (TV_REG_STATS);
}
@@ -149,7 +165,7 @@ regstat_bb_compute_ri (unsigned int bb_i
struct df_mw_hardreg **mws_rec;
rtx link;
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
/* Increment the live_length for all of the registers that
Index: gcc/reload.c
===================================================================
--- gcc/reload.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/reload.c 2009-06-05 05:07:56.000000000 -0300
@@ -6727,6 +6727,8 @@ find_equiv_reg (rtx goal, rtx insn, enum
while (1)
{
p = PREV_INSN (p);
+ if (p && DEBUG_INSN_P (p))
+ continue;
num++;
if (p == 0 || LABEL_P (p)
|| num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/rtlanal.c 2009-06-05 05:08:11.000000000 -0300
@@ -741,7 +741,7 @@ reg_used_between_p (const_rtx reg, const
return 0;
for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
+ if (NONDEBUG_INSN_P (insn)
&& (reg_overlap_mentioned_p (reg, PATTERN (insn))
|| (CALL_P (insn) && find_reg_fusage (insn, USE, reg))))
return 1;
@@ -2148,6 +2148,7 @@ side_effects_p (const_rtx x)
case SCRATCH:
case ADDR_VEC:
case ADDR_DIFF_VEC:
+ case VAR_LOCATION:
return 0;
case CLOBBER:
@@ -4727,7 +4728,11 @@ canonicalize_condition (rtx insn, rtx co
stop if it isn't a single set or if it has a REG_INC note because
we don't want to bother dealing with it. */
- if ((prev = prev_nonnote_insn (prev)) == 0
+ do
+ prev = prev_nonnote_insn (prev);
+ while (prev && DEBUG_INSN_P (prev));
+
+ if (prev == 0
|| !NONJUMP_INSN_P (prev)
|| FIND_REG_INC_NOTE (prev, NULL_RTX)
/* In cfglayout mode, there do not have to be labels at the
Index: gcc/final.c
===================================================================
--- gcc/final.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/final.c 2009-06-05 05:07:56.000000000 -0300
@@ -409,7 +409,8 @@ get_attr_length_1 (rtx insn ATTRIBUTE_UN
case INSN:
body = PATTERN (insn);
- if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
+ if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER
+ || DEBUG_INSN_P (insn))
return 0;
else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
Index: gcc/cfgloopanal.c
===================================================================
--- gcc/cfgloopanal.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/cfgloopanal.c 2009-06-05 05:08:11.000000000 -0300
@@ -174,8 +174,8 @@ num_loop_insns (const struct loop *loop)
{
bb = bbs[i];
ninsns++;
- for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
- if (INSN_P (insn))
+ FOR_BB_INSNS (bb, insn)
+ if (NONDEBUG_INSN_P (insn))
ninsns++;
}
free(bbs);
@@ -197,9 +197,9 @@ average_num_loop_insns (const struct loo
{
bb = bbs[i];
- binsns = 1;
- for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
- if (INSN_P (insn))
+ binsns = 0;
+ FOR_BB_INSNS (bb, insn)
+ if (NONDEBUG_INSN_P (insn))
binsns++;
ratio = loop->header->frequency == 0
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/auto-inc-dec.c 2009-06-05 05:08:11.000000000 -0300
@@ -1341,7 +1341,7 @@ merge_in_block (int max_reg, basic_block
unsigned int uid = INSN_UID (insn);
bool insn_is_add_or_inc = true;
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
/* This continue is deliberate. We do not want the uses of the
@@ -1414,7 +1414,7 @@ merge_in_block (int max_reg, basic_block
/* If the inc insn was merged with a mem, the inc insn is gone
and there is noting to update. */
- if (DF_INSN_UID_GET(uid))
+ if (DF_INSN_UID_GET (uid))
{
df_ref *def_rec;
df_ref *use_rec;
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/df-scan.c 2009-06-05 05:07:56.000000000 -0300
@@ -1361,6 +1361,62 @@ df_insn_rescan (rtx insn)
return true;
}
+/* Same as df_insn_rescan, but don't mark the basic block as
+ dirty. */
+
+bool
+df_insn_rescan_debug_internal (rtx insn)
+{
+ unsigned int uid = INSN_UID (insn);
+ struct df_insn_info *insn_info;
+
+ gcc_assert (DEBUG_INSN_P (insn));
+ gcc_assert (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)));
+
+ if (!df)
+ return false;
+
+ insn_info = DF_INSN_UID_SAFE_GET (INSN_UID (insn));
+ if (!insn_info)
+ return false;
+
+ if (dump_file)
+ fprintf (dump_file, "deleting debug_insn with uid = %d.\n", uid);
+
+ bitmap_clear_bit (df->insns_to_delete, uid);
+ bitmap_clear_bit (df->insns_to_rescan, uid);
+ bitmap_clear_bit (df->insns_to_notes_rescan, uid);
+
+ if (!insn_info->defs)
+ return false;
+
+ if (insn_info->defs == df_null_ref_rec
+ && insn_info->uses == df_null_ref_rec
+ && insn_info->eq_uses == df_null_ref_rec
+ && insn_info->mw_hardregs == df_null_mw_rec)
+ return false;
+
+ df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
+
+ if (df_chain)
+ {
+ df_ref_chain_delete_du_chain (insn_info->defs);
+ df_ref_chain_delete_du_chain (insn_info->uses);
+ df_ref_chain_delete_du_chain (insn_info->eq_uses);
+ }
+
+ df_ref_chain_delete (insn_info->defs);
+ df_ref_chain_delete (insn_info->uses);
+ df_ref_chain_delete (insn_info->eq_uses);
+
+ insn_info->defs = df_null_ref_rec;
+ insn_info->uses = df_null_ref_rec;
+ insn_info->eq_uses = df_null_ref_rec;
+ insn_info->mw_hardregs = df_null_mw_rec;
+
+ return true;
+}
+
/* Rescan all of the insns in the function. Note that the artificial
uses and defs are not touched. This function will destroy def-se
@@ -3306,12 +3362,20 @@ df_uses_record (enum df_ref_class cl, st
break;
}
+ case VAR_LOCATION:
+ df_uses_record (cl, collection_rec,
+ &PAT_VAR_LOCATION_LOC (x),
+ DF_REF_REG_USE, bb, insn_info,
+ flags, width, offset, mode);
+ return;
+
case PRE_DEC:
case POST_DEC:
case PRE_INC:
case POST_INC:
case PRE_MODIFY:
case POST_MODIFY:
+ gcc_assert (!DEBUG_INSN_P (insn_info->insn));
/* Catch the def of the register being modified. */
df_ref_record (cl, collection_rec, XEXP (x, 0), &XEXP (x, 0),
bb, insn_info,
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/ifcvt.c 2009-06-05 05:08:11.000000000 -0300
@@ -194,7 +194,7 @@ first_active_insn (basic_block bb)
insn = NEXT_INSN (insn);
}
- while (NOTE_P (insn))
+ while (NOTE_P (insn) || DEBUG_INSN_P (insn))
{
if (insn == BB_END (bb))
return NULL_RTX;
@@ -217,6 +217,7 @@ last_active_insn (basic_block bb, int sk
while (NOTE_P (insn)
|| JUMP_P (insn)
+ || DEBUG_INSN_P (insn)
|| (skip_use_p
&& NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == USE))
@@ -269,7 +270,7 @@ cond_exec_process_insns (ce_if_block_t *
for (insn = start; ; insn = NEXT_INSN (insn))
{
- if (NOTE_P (insn))
+ if (NOTE_P (insn) || DEBUG_INSN_P (insn))
goto insn_done;
gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn));
@@ -2256,6 +2257,8 @@ noce_process_if_block (struct noce_if_in
else
{
insn_b = prev_nonnote_insn (if_info->cond_earliest);
+ while (insn_b && DEBUG_INSN_P (insn_b))
+ insn_b = prev_nonnote_insn (insn_b);
/* We're going to be moving the evaluation of B down from above
COND_EARLIEST to JUMP. Make sure the relevant data is still
intact. */
@@ -2266,14 +2269,13 @@ noce_process_if_block (struct noce_if_in
|| ! rtx_equal_p (x, SET_DEST (set_b))
|| ! noce_operand_ok (SET_SRC (set_b))
|| reg_overlap_mentioned_p (x, SET_SRC (set_b))
- || modified_between_p (SET_SRC (set_b),
- PREV_INSN (if_info->cond_earliest), jump)
+ || modified_between_p (SET_SRC (set_b), insn_b, jump)
/* Likewise with X. In particular this can happen when
noce_get_condition looks farther back in the instruction
stream than one might expect. */
|| reg_overlap_mentioned_p (x, cond)
|| reg_overlap_mentioned_p (x, a)
- || modified_between_p (x, PREV_INSN (if_info->cond_earliest), jump))
+ || modified_between_p (x, insn_b, jump))
insn_b = set_b = NULL_RTX;
}
@@ -2474,6 +2476,8 @@ check_cond_move_block (basic_block bb, r
/* We can only handle simple jumps at the end of the basic block.
It is almost impossible to update the CFG otherwise. */
insn = BB_END (bb);
+ while (DEBUG_INSN_P (insn))
+ insn = PREV_INSN (insn);
if (JUMP_P (insn) && !onlyjump_p (insn))
return FALSE;
@@ -2481,7 +2485,7 @@ check_cond_move_block (basic_block bb, r
{
rtx set, dest, src;
- if (!INSN_P (insn) || JUMP_P (insn))
+ if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
continue;
set = single_set (insn);
if (!set)
@@ -2559,7 +2563,8 @@ cond_move_convert_if_block (struct noce_
rtx set, target, dest, t, e;
unsigned int regno;
- if (!INSN_P (insn) || JUMP_P (insn))
+ /* ??? Maybe emit conditional debug insn? */
+ if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
continue;
set = single_set (insn);
gcc_assert (set && REG_P (SET_DEST (set)));
@@ -3120,6 +3125,7 @@ block_jumps_and_fallthru_p (basic_block
if (INSN_P (insn)
&& !JUMP_P (insn)
+ && !DEBUG_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER)
n_insns++;
@@ -3787,6 +3793,9 @@ dead_or_predicable (basic_block test_bb,
head = BB_HEAD (merge_bb);
end = BB_END (merge_bb);
+ while (DEBUG_INSN_P (end) && end != head)
+ end = PREV_INSN (end);
+
/* If merge_bb ends with a tablejump, predicating/moving insn's
into test_bb and then deleting merge_bb will result in the jumptable
that follows merge_bb being removed along with merge_bb and then we
@@ -3796,6 +3805,8 @@ dead_or_predicable (basic_block test_bb,
if (LABEL_P (head))
head = NEXT_INSN (head);
+ while (DEBUG_INSN_P (head) && head != end)
+ head = NEXT_INSN (head);
if (NOTE_P (head))
{
if (head == end)
@@ -3804,6 +3815,8 @@ dead_or_predicable (basic_block test_bb,
goto no_body;
}
head = NEXT_INSN (head);
+ while (DEBUG_INSN_P (head) && head != end)
+ head = NEXT_INSN (head);
}
if (JUMP_P (end))
@@ -3814,6 +3827,8 @@ dead_or_predicable (basic_block test_bb,
goto no_body;
}
end = PREV_INSN (end);
+ while (DEBUG_INSN_P (end) && end != head)
+ end = PREV_INSN (end);
}
/* Disable handling dead code by conditional execution if the machine needs
@@ -3871,7 +3886,7 @@ dead_or_predicable (basic_block test_bb,
{
if (CALL_P (insn))
return FALSE;
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
{
if (may_trap_p (PATTERN (insn)))
return FALSE;
@@ -3917,7 +3932,7 @@ dead_or_predicable (basic_block test_bb,
FOR_BB_INSNS (merge_bb, insn)
{
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
{
unsigned int uid = INSN_UID (insn);
df_ref *def_rec;
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-lives.c 2009-06-05 05:08:11.000000000 -0300
@@ -894,7 +894,7 @@ process_bb_node_lives (ira_loop_tree_nod
df_ref *def_rec, *use_rec;
bool call_p;
- if (! INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
Index: gcc/regmove.c
===================================================================
--- gcc/regmove.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/regmove.c 2009-06-05 05:07:56.000000000 -0300
@@ -321,9 +321,12 @@ optimize_reg_copy_1 (rtx insn, rtx dest,
/* For SREGNO, count the total number of insns scanned.
For DREGNO, count the total number of insns scanned after
passing the death note for DREGNO. */
- s_length++;
- if (dest_death)
- d_length++;
+ if (!DEBUG_INSN_P (p))
+ {
+ s_length++;
+ if (dest_death)
+ d_length++;
+ }
/* If the insn in which SRC dies is a CALL_INSN, don't count it
as a call that has been crossed. Otherwise, count it. */
@@ -767,7 +770,7 @@ fixup_match_2 (rtx insn, rtx dst, rtx sr
if (find_regno_note (p, REG_DEAD, REGNO (dst)))
dst_death = p;
- if (! dst_death)
+ if (! dst_death && !DEBUG_INSN_P (p))
length++;
pset = single_set (p);
@@ -1095,7 +1098,8 @@ regmove_backward_pass (void)
if (BLOCK_FOR_INSN (p) != bb)
break;
- length++;
+ if (!DEBUG_INSN_P (p))
+ length++;
/* ??? See if all of SRC is set in P. This test is much
more conservative than it needs to be. */
@@ -1105,22 +1109,9 @@ regmove_backward_pass (void)
/* We use validate_replace_rtx, in case there
are multiple identical source operands. All of
them have to be changed at the same time. */
+ validate_change (p, &SET_DEST (pset), dst, 1);
if (validate_replace_rtx (src, dst, insn))
- {
- if (validate_change (p, &SET_DEST (pset),
- dst, 0))
- success = 1;
- else
- {
- /* Change all source operands back.
- This modifies the dst as a side-effect. */
- validate_replace_rtx (dst, src, insn);
- /* Now make sure the dst is right. */
- validate_change (insn,
- recog_data.operand_loc[match_no],
- dst, 0);
- }
- }
+ success = 1;
break;
}
@@ -1129,9 +1120,21 @@ regmove_backward_pass (void)
eliminate SRC. We can't make this change
if DST is mentioned at all in P,
since we are going to change its value. */
- if (reg_overlap_mentioned_p (src, PATTERN (p))
- || reg_mentioned_p (dst, PATTERN (p)))
- break;
+ if (reg_overlap_mentioned_p (src, PATTERN (p)))
+ {
+ if (DEBUG_INSN_P (p))
+ validate_replace_rtx_group (dst, src, insn);
+ else
+ break;
+ }
+ if (reg_mentioned_p (dst, PATTERN (p)))
+ {
+ if (DEBUG_INSN_P (p))
+ validate_change (p, &INSN_VAR_LOCATION_LOC (p),
+ gen_rtx_UNKNOWN_VAR_LOC (), 1);
+ else
+ break;
+ }
/* If we have passed a call instruction, and the
pseudo-reg DST is not already live across a call,
@@ -1193,6 +1196,8 @@ regmove_backward_pass (void)
break;
}
+ else if (num_changes_pending () > 0)
+ cancel_changes (0);
}
/* If we weren't able to replace any of the alternatives, try an
Index: gcc/function.c
===================================================================
--- gcc/function.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/function.c 2009-06-05 05:07:56.000000000 -0300
@@ -1774,8 +1774,11 @@ instantiate_virtual_regs (void)
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
|| GET_CODE (PATTERN (insn)) == ASM_INPUT)
continue;
-
- instantiate_virtual_regs_in_insn (insn);
+ else if (DEBUG_INSN_P (insn))
+ for_each_rtx (&INSN_VAR_LOCATION (insn),
+ instantiate_virtual_regs_in_rtx, NULL);
+ else
+ instantiate_virtual_regs_in_insn (insn);
if (INSN_DELETED_P (insn))
continue;
Index: gcc/df.h
===================================================================
--- gcc/df.h.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/df.h 2009-06-05 05:07:56.000000000 -0300
@@ -980,6 +980,7 @@ extern struct df_insn_info * df_insn_cre
extern void df_insn_delete (basic_block, unsigned int);
extern void df_bb_refs_record (int, bool);
extern bool df_insn_rescan (rtx);
+extern bool df_insn_rescan_debug_internal (rtx);
extern void df_insn_rescan_all (void);
extern void df_process_deferred_rescans (void);
extern void df_recompute_luids (basic_block);
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/gcse.c 2009-06-05 05:08:11.000000000 -0300
@@ -2610,6 +2610,9 @@ cprop_insn (rtx insn)
}
}
+ if (changed && DEBUG_INSN_P (insn))
+ return 0;
+
return changed;
}
@@ -3137,7 +3140,9 @@ bypass_conditional_jumps (void)
{
setcc = NULL_RTX;
FOR_BB_INSNS (bb, insn)
- if (NONJUMP_INSN_P (insn))
+ if (DEBUG_INSN_P (insn))
+ continue;
+ else if (NONJUMP_INSN_P (insn))
{
if (setcc)
break;
@@ -4752,7 +4757,7 @@ compute_ld_motion_mems (void)
{
FOR_BB_INSNS (bb, insn)
{
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
{
if (GET_CODE (PATTERN (insn)) == SET)
{
Index: gcc/init-regs.c
===================================================================
--- gcc/init-regs.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/init-regs.c 2009-06-05 05:08:11.000000000 -0300
@@ -70,7 +70,7 @@ initialize_uninitialized_regs (void)
{
unsigned int uid = INSN_UID (insn);
df_ref *use_rec;
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
Index: gcc/ira-build.c
===================================================================
--- gcc/ira-build.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-build.c 2009-06-05 05:08:11.000000000 -0300
@@ -1491,7 +1491,7 @@ create_bb_allocnos (ira_loop_tree_node_t
curr_bb = bb = bb_node->bb;
ira_assert (bb != NULL);
FOR_BB_INSNS_REVERSE (bb, insn)
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
create_insn_allocnos (PATTERN (insn), false);
/* It might be a allocno living through from one subloop to
another. */
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/cfgcleanup.c 2009-06-05 05:08:11.000000000 -0300
@@ -1086,10 +1086,10 @@ flow_find_cross_jump (int mode ATTRIBUTE
while (true)
{
/* Ignore notes. */
- while (!INSN_P (i1) && i1 != BB_HEAD (bb1))
+ while (!NONDEBUG_INSN_P (i1) && i1 != BB_HEAD (bb1))
i1 = PREV_INSN (i1);
- while (!INSN_P (i2) && i2 != BB_HEAD (bb2))
+ while (!NONDEBUG_INSN_P (i2) && i2 != BB_HEAD (bb2))
i2 = PREV_INSN (i2);
if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
@@ -1140,13 +1140,13 @@ flow_find_cross_jump (int mode ATTRIBUTE
Two, it keeps line number notes as matched as may be. */
if (ninsns)
{
- while (last1 != BB_HEAD (bb1) && !INSN_P (PREV_INSN (last1)))
+ while (last1 != BB_HEAD (bb1) && !NONDEBUG_INSN_P (PREV_INSN (last1)))
last1 = PREV_INSN (last1);
if (last1 != BB_HEAD (bb1) && LABEL_P (PREV_INSN (last1)))
last1 = PREV_INSN (last1);
- while (last2 != BB_HEAD (bb2) && !INSN_P (PREV_INSN (last2)))
+ while (last2 != BB_HEAD (bb2) && !NONDEBUG_INSN_P (PREV_INSN (last2)))
last2 = PREV_INSN (last2);
if (last2 != BB_HEAD (bb2) && LABEL_P (PREV_INSN (last2)))
@@ -1586,8 +1586,12 @@ try_crossjump_to_edge (int mode, edge e1
/* Skip possible basic block header. */
if (LABEL_P (newpos2))
newpos2 = NEXT_INSN (newpos2);
+ while (DEBUG_INSN_P (newpos2))
+ newpos2 = NEXT_INSN (newpos2);
if (NOTE_P (newpos2))
newpos2 = NEXT_INSN (newpos2);
+ while (DEBUG_INSN_P (newpos2))
+ newpos2 = NEXT_INSN (newpos2);
}
if (dump_file)
@@ -1672,9 +1676,16 @@ try_crossjump_to_edge (int mode, edge e1
/* Skip possible basic block header. */
if (LABEL_P (newpos1))
newpos1 = NEXT_INSN (newpos1);
+
+ while (DEBUG_INSN_P (newpos1))
+ newpos1 = NEXT_INSN (newpos1);
+
if (NOTE_INSN_BASIC_BLOCK_P (newpos1))
newpos1 = NEXT_INSN (newpos1);
+ while (DEBUG_INSN_P (newpos1))
+ newpos1 = NEXT_INSN (newpos1);
+
redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
to_remove = single_succ (redirect_from);
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/simplify-rtx.c 2009-06-05 05:07:56.000000000 -0300
@@ -202,6 +202,106 @@ avoid_constant_pool_reference (rtx x)
return x;
}
+/* Simplify a MEM based on its attributes. This is the default
+ delegitimize_address target hook, and it's recommended that every
+ overrider call it. */
+
+rtx
+delegitimize_mem_from_attrs (rtx x)
+{
+ if (MEM_P (x)
+ && MEM_EXPR (x)
+ && (!MEM_OFFSET (x)
+ || GET_CODE (MEM_OFFSET (x)) == CONST_INT))
+ {
+ tree decl = MEM_EXPR (x);
+ enum machine_mode mode = GET_MODE (x);
+ HOST_WIDE_INT offset = 0;
+
+ switch (TREE_CODE (decl))
+ {
+ default:
+ decl = NULL;
+ break;
+
+ case VAR_DECL:
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case VIEW_CONVERT_EXPR:
+ {
+ HOST_WIDE_INT bitsize, bitpos;
+ tree toffset;
+ int unsignedp = 0, volatilep = 0;
+
+ decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
+ &mode, &unsignedp, &volatilep, false);
+ if (bitsize != GET_MODE_BITSIZE (mode)
+ || (bitpos % BITS_PER_UNIT)
+ || (toffset && !host_integerp (toffset, 0)))
+ decl = NULL;
+ else
+ {
+ offset += bitpos / BITS_PER_UNIT;
+ if (toffset)
+ offset += TREE_INT_CST_LOW (toffset);
+ }
+ break;
+ }
+ }
+
+ if (decl
+ && mode == GET_MODE (x)
+ && TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl)
+ || DECL_THREAD_LOCAL_P (decl))
+ && DECL_RTL_SET_P (decl)
+ && MEM_P (DECL_RTL (decl)))
+ {
+ rtx newx;
+
+ if (MEM_OFFSET (x))
+ offset += INTVAL (MEM_OFFSET (x));
+
+ newx = DECL_RTL (decl);
+
+ if (MEM_P (newx))
+ {
+ rtx n = XEXP (newx, 0), o = XEXP (x, 0);
+
+ /* Avoid creating a new MEM needlessly if we already had
+ the same address. We do if there's no OFFSET and the
+ old address X is identical to NEWX, or if X is of the
+ form (plus NEWX OFFSET), or the NEWX is of the form
+ (plus Y (const_int Z)) and X is that with the offset
+ added: (plus Y (const_int Z+OFFSET)). */
+ if (!((offset == 0
+ || (GET_CODE (o) == PLUS
+ && GET_CODE (XEXP (o, 1)) == CONST_INT
+ && (offset == INTVAL (XEXP (o, 1))
+ || (GET_CODE (n) == PLUS
+ && GET_CODE (XEXP (n, 1)) == CONST_INT
+ && (INTVAL (XEXP (n, 1)) + offset
+ == INTVAL (XEXP (o, 1)))
+ && (n = XEXP (n, 0))))
+ && (o = XEXP (o, 0))))
+ && rtx_equal_p (o, n)))
+ x = adjust_address_nv (newx, mode, offset);
+ }
+ else if (GET_MODE (x) == GET_MODE (newx)
+ && offset == 0)
+ x = newx;
+ }
+ }
+
+ return x;
+}
+
/* Make a unary operation by first seeing if it folds and otherwise making
the specified operation. */
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/loop-invariant.c 2009-06-05 05:08:11.000000000 -0300
@@ -912,7 +912,7 @@ find_invariants_bb (basic_block bb, bool
FOR_BB_INSNS (bb, insn)
{
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
find_invariants_insn (insn, always_reached, always_executed);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira.c 2009-06-05 05:08:11.000000000 -0300
@@ -2201,7 +2201,7 @@ memref_used_between_p (rtx memref, rtx s
for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
insn = NEXT_INSN (insn))
{
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
if (memref_referenced_p (memref, PATTERN (insn)))
@@ -2645,7 +2645,7 @@ update_equiv_regs (void)
}
/* Move the initialization of the register to just before
INSN. Update the flow information. */
- else if (PREV_INSN (insn) != equiv_insn)
+ else if (prev_nondebug_insn (insn) != equiv_insn)
{
rtx new_insn;
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/target-def.h 2009-06-05 05:07:56.000000000 -0300
@@ -488,7 +488,7 @@
#define TARGET_CANNOT_COPY_INSN_P NULL
#define TARGET_COMMUTATIVE_P hook_bool_const_rtx_commutative_p
#define TARGET_LEGITIMIZE_ADDRESS default_legitimize_address
-#define TARGET_DELEGITIMIZE_ADDRESS hook_rtx_rtx_identity
+#define TARGET_DELEGITIMIZE_ADDRESS delegitimize_mem_from_attrs
#define TARGET_LEGITIMATE_ADDRESS_P default_legitimate_address_p
#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_false
#define TARGET_MIN_ANCHOR_OFFSET 0
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-costs.c 2009-06-05 05:08:11.000000000 -0300
@@ -995,7 +995,7 @@ scan_one_insn (rtx insn)
rtx set, note;
int i, k;
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
return insn;
pat_code = GET_CODE (PATTERN (insn));
@@ -1384,7 +1384,7 @@ process_bb_node_for_hard_reg_moves (ira_
freq = 1;
FOR_BB_INSNS (bb, insn)
{
- if (! INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
set = single_set (insn);
if (set == NULL_RTX)
Index: gcc/combine.c
===================================================================
--- gcc/combine.c.orig 2009-06-05 05:07:48.000000000 -0300
+++ gcc/combine.c 2009-06-05 05:08:11.000000000 -0300
@@ -921,7 +921,7 @@ create_log_links (void)
{
FOR_BB_INSNS_REVERSE (bb, insn)
{
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
/* Log links are created only once. */
@@ -1129,7 +1129,7 @@ combine_instructions (rtx f, unsigned in
insn = next ? next : NEXT_INSN (insn))
{
next = 0;
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
{
/* See if we know about function return values before this
insn based upon SUBREG flags. */
@@ -2163,6 +2163,188 @@ reg_subword_p (rtx x, rtx reg)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_INT;
}
+#ifdef AUTO_INC_DEC
+/* Replace auto-increment addressing modes with explicit operations to
+ access the same addresses without modifying the corresponding
+ registers. If AFTER holds, SRC is meant to be reused after the
+ side effect, otherwise it is to be reused before that. */
+
+static rtx
+cleanup_auto_inc_dec (rtx src, bool after, enum machine_mode mem_mode)
+{
+ rtx x = src, n, o;
+ const RTX_CODE code = GET_CODE (x);
+ int i;
+ const char *fmt;
+
+ switch (code)
+ {
+ case MEM:
+ mem_mode = GET_MODE (x);
+ break;
+
+ case PRE_INC:
+ case PRE_DEC:
+ case POST_INC:
+ case POST_DEC:
+ gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
+ if (after == (code == PRE_INC || code == PRE_DEC))
+ x = XEXP (x, 0);
+ else
+ x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+ GEN_INT ((code == PRE_INC || code == POST_INC)
+ ? GET_MODE_SIZE (mem_mode)
+ : -GET_MODE_SIZE (mem_mode)));
+ return cleanup_auto_inc_dec (x, after, mem_mode);
+
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ if (after == (code == PRE_MODIFY))
+ x = XEXP (x, 0);
+ else
+ x = XEXP (x, 1);
+ return cleanup_auto_inc_dec (x, after, mem_mode);
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ {
+ o = XEXP (x, i);
+ n = cleanup_auto_inc_dec (o, after, mem_mode);
+ if (o != n)
+ {
+ if (x == src)
+ x = shallow_copy_rtx (x);
+ XEXP (x, i) = n;
+ }
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ {
+ o = XVECEXP (x, i, j);
+ n = cleanup_auto_inc_dec (o, after, mem_mode);
+ if (o != n)
+ {
+ if (x == src)
+ x = shallow_copy_rtx (x);
+ XVECEXP (x, i, j) = n;
+ }
+ }
+ }
+
+ return x;
+}
+#endif
+
+/* Auxiliary data structure for propagate_for_debug_stmt. */
+
+struct rtx_subst_pair
+{
+ rtx from, to;
+ bool changed;
+#ifdef AUTO_INC_DEC
+ bool adjusted;
+ bool after;
+#endif
+};
+
+/* Clean up any auto-updates in PAIR->to the first time it is called
+ for a PAIR. PAIR->adjusted is used to tell whether we've cleaned
+ up before. */
+
+static void
+auto_adjust_pair (struct rtx_subst_pair *pair ATTRIBUTE_UNUSED)
+{
+#ifdef AUTO_INC_DEC
+ if (!pair->adjusted)
+ {
+ pair->adjusted = true;
+ pair->to = cleanup_auto_inc_dec (pair->to, pair->after, VOIDmode);
+ }
+#endif
+}
+
+/* If *LOC is the same as FROM in the struct rtx_subst_pair passed as
+ DATA, replace it with a copy of TO. Handle SUBREGs of *LOC as
+ well. */
+
+static int
+propagate_for_debug_subst (rtx *loc, void *data)
+{
+ struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
+ rtx from = pair->from, to = pair->to;
+ rtx x = *loc, s = x;
+
+ if (rtx_equal_p (x, from)
+ || (GET_CODE (x) == SUBREG && rtx_equal_p ((s = SUBREG_REG (x)), from)))
+ {
+ auto_adjust_pair (pair);
+ if (pair->to != to)
+ to = pair->to;
+ else
+ to = copy_rtx (to);
+ if (s != x)
+ {
+ gcc_assert (GET_CODE (x) == SUBREG && SUBREG_REG (x) == s);
+ to = simplify_gen_subreg (GET_MODE (x), to,
+ GET_MODE (from), SUBREG_BYTE (x));
+ }
+ *loc = to;
+ pair->changed = true;
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Replace occurrences of DEST with SRC in DEBUG_INSNs between INSN
+ and LAST. If MOVE holds, debug insns must also be moved past
+ LAST. */
+
+static void
+propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move)
+{
+ struct rtx_subst_pair p;
+ rtx next, move_pos = move ? last : NULL_RTX;
+
+ p.from = dest;
+ p.to = src;
+ p.changed = false;
+
+#ifdef AUTO_INC_DEC
+ p.adjusted = false;
+ p.after = move;
+#endif
+
+ next = NEXT_INSN (insn);
+ while (next != last)
+ {
+ insn = next;
+ next = NEXT_INSN (insn);
+ if (DEBUG_INSN_P (insn))
+ {
+ for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
+ propagate_for_debug_subst, &p);
+ if (!p.changed)
+ continue;
+ p.changed = false;
+ if (move_pos)
+ {
+ remove_insn (insn);
+ PREV_INSN (insn) = NEXT_INSN (insn) = NULL_RTX;
+ move_pos = emit_debug_insn_after (insn, move_pos);
+ }
+ else
+ df_insn_rescan (insn);
+ }
+ }
+}
/* Delete the conditional jump INSN and adjust the CFG correspondingly.
Note that the INSN should be deleted *after* removing dead edges, so
@@ -2219,7 +2401,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
I2 and not in I3, a REG_DEAD note must be made. */
rtx i3dest_killed = 0;
/* SET_DEST and SET_SRC of I2 and I1. */
- rtx i2dest, i2src, i1dest = 0, i1src = 0;
+ rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0;
/* PATTERN (I1) and PATTERN (I2), or a copy of it in certain cases. */
rtx i1pat = 0, i2pat = 0;
/* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC. */
@@ -2293,7 +2475,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
&& GET_CODE (SET_DEST (PATTERN (i3))) != STRICT_LOW_PART
&& ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3)),
SET_DEST (PATTERN (i3)))
- && next_real_insn (i2) == i3)
+ && next_active_insn (i2) == i3)
{
rtx p2 = PATTERN (i2);
@@ -2326,6 +2508,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
subst_low_luid = DF_INSN_LUID (i2);
added_sets_2 = added_sets_1 = 0;
+ i2src = SET_DEST (PATTERN (i3));
i2dest = SET_SRC (PATTERN (i3));
i2dest_killed = dead_or_set_p (i2, i2dest);
@@ -3588,12 +3771,18 @@ try_combine (rtx i3, rtx i2, rtx i1, int
PATTERN (i2) = newi2pat;
}
else
- SET_INSN_DELETED (i2);
+ {
+ if (MAY_HAVE_DEBUG_INSNS && i2src)
+ propagate_for_debug (i2, i3, i2dest, i2src, i3_subst_into_i2);
+ SET_INSN_DELETED (i2);
+ }
if (i1)
{
LOG_LINKS (i1) = 0;
REG_NOTES (i1) = 0;
+ if (MAY_HAVE_DEBUG_INSNS)
+ propagate_for_debug (i1, i3, i1dest, i1src, false);
SET_INSN_DELETED (i1);
}
@@ -12314,6 +12503,29 @@ reg_bitfield_target_p (rtx x, rtx body)
return 0;
}
+
+/* Return the next insn after INSN that is neither a NOTE nor a
+ DEBUG_INSN. This routine does not look inside SEQUENCEs. */
+
+static rtx
+next_nonnote_nondebug_insn (rtx insn)
+{
+ while (insn)
+ {
+ insn = NEXT_INSN (insn);
+ if (insn == 0)
+ break;
+ if (NOTE_P (insn))
+ continue;
+ if (DEBUG_INSN_P (insn))
+ continue;
+ break;
+ }
+
+ return insn;
+}
+
+
/* Given a chain of REG_NOTES originally from FROM_INSN, try to place them
as appropriate. I3 and I2 are the insns resulting from the combination
@@ -12567,7 +12779,7 @@ distribute_notes (rtx notes, rtx from_in
place = from_insn;
else if (reg_referenced_p (XEXP (note, 0), PATTERN (i3)))
place = i3;
- else if (i2 != 0 && next_nonnote_insn (i2) == i3
+ else if (i2 != 0 && next_nonnote_nondebug_insn (i2) == i3
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
place = i2;
else if ((rtx_equal_p (XEXP (note, 0), elim_i2)
@@ -12585,7 +12797,7 @@ distribute_notes (rtx notes, rtx from_in
for (tem = PREV_INSN (tem); place == 0; tem = PREV_INSN (tem))
{
- if (! INSN_P (tem))
+ if (!NONDEBUG_INSN_P (tem))
{
if (tem == BB_HEAD (bb))
break;
@@ -12786,7 +12998,7 @@ distribute_notes (rtx notes, rtx from_in
for (tem = PREV_INSN (place); ;
tem = PREV_INSN (tem))
{
- if (! INSN_P (tem))
+ if (!NONDEBUG_INSN_P (tem))
{
if (tem == BB_HEAD (bb))
break;
@@ -12876,7 +13088,9 @@ distribute_links (rtx links)
(insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
|| BB_HEAD (this_basic_block->next_bb) != insn));
insn = NEXT_INSN (insn))
- if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+ if (DEBUG_INSN_P (insn))
+ continue;
+ else if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
{
if (reg_referenced_p (reg, PATTERN (insn)))
place = insn;
Index: gcc/resource.c
===================================================================
--- gcc/resource.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/resource.c 2009-06-05 05:07:56.000000000 -0300
@@ -975,6 +975,9 @@ mark_target_live_regs (rtx insns, rtx ta
rtx real_insn = insn;
enum rtx_code code = GET_CODE (insn);
+ if (DEBUG_INSN_P (insn))
+ continue;
+
/* If this insn is from the target of a branch, it isn't going to
be used in the sequel. If it is used in both cases, this
test will not be true. */
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/df-problems.c 2009-06-05 05:08:11.000000000 -0300
@@ -877,7 +877,7 @@ df_lr_bb_local_compute (unsigned int bb_
{
unsigned int uid = INSN_UID (insn);
- if (!INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
continue;
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
@@ -3201,6 +3201,8 @@ df_set_note (enum reg_note note_type, rt
rtx curr = old;
rtx prev = NULL;
+ gcc_assert (!DEBUG_INSN_P (insn));
+
while (curr)
if (XEXP (curr, 0) == reg)
{
@@ -3333,9 +3335,12 @@ df_whole_mw_reg_dead_p (struct df_mw_har
static rtx
df_set_dead_notes_for_mw (rtx insn, rtx old, struct df_mw_hardreg *mws,
bitmap live, bitmap do_not_gen,
- bitmap artificial_uses)
+ bitmap artificial_uses, bool *added_notes_p)
{
unsigned int r;
+ bool is_debug = *added_notes_p;
+
+ *added_notes_p = false;
#ifdef REG_DEAD_DEBUGGING
if (dump_file)
@@ -3353,6 +3358,11 @@ df_set_dead_notes_for_mw (rtx insn, rtx
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 old;
+ }
old = df_set_note (REG_DEAD, insn, old, mws->mw_reg);
#ifdef REG_DEAD_DEBUGGING
df_print_note ("adding 1: ", insn, REG_NOTES (insn));
@@ -3365,6 +3375,11 @@ df_set_dead_notes_for_mw (rtx insn, rtx
&& !bitmap_bit_p (artificial_uses, r)
&& !bitmap_bit_p (do_not_gen, r))
{
+ if (is_debug)
+ {
+ *added_notes_p = true;
+ return old;
+ }
old = df_set_note (REG_DEAD, insn, old, regno_reg_rtx[r]);
#ifdef REG_DEAD_DEBUGGING
df_print_note ("adding 2: ", insn, REG_NOTES (insn));
@@ -3475,10 +3490,13 @@ df_note_bb_compute (unsigned int bb_inde
struct df_mw_hardreg **mws_rec;
rtx old_dead_notes;
rtx old_unused_notes;
+ int debug_insn;
if (!INSN_P (insn))
continue;
+ debug_insn = DEBUG_INSN_P (insn);
+
bitmap_clear (do_not_gen);
df_kill_notes (insn, &old_dead_notes, &old_unused_notes);
@@ -3563,10 +3581,18 @@ df_note_bb_compute (unsigned int bb_inde
struct df_mw_hardreg *mws = *mws_rec;
if ((DF_MWS_REG_DEF_P (mws))
&& !df_ignore_stack_reg (mws->start_regno))
- old_dead_notes
- = df_set_dead_notes_for_mw (insn, old_dead_notes,
- mws, live, do_not_gen,
- artificial_uses);
+ {
+ bool really_add_notes = debug_insn != 0;
+
+ old_dead_notes
+ = df_set_dead_notes_for_mw (insn, old_dead_notes,
+ mws, live, do_not_gen,
+ artificial_uses,
+ &really_add_notes);
+
+ if (really_add_notes)
+ debug_insn = -1;
+ }
mws_rec++;
}
@@ -3576,7 +3602,7 @@ df_note_bb_compute (unsigned int bb_inde
unsigned int uregno = DF_REF_REGNO (use);
#ifdef REG_DEAD_DEBUGGING
- if (dump_file)
+ if (dump_file && !debug_insn)
{
fprintf (dump_file, " regular looking at use ");
df_ref_debug (use, dump_file);
@@ -3584,6 +3610,12 @@ df_note_bb_compute (unsigned int bb_inde
#endif
if (!bitmap_bit_p (live, uregno))
{
+ if (debug_insn)
+ {
+ debug_insn = -1;
+ break;
+ }
+
if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG))
&& (!bitmap_bit_p (do_not_gen, uregno))
&& (!bitmap_bit_p (artificial_uses, uregno))
@@ -3615,6 +3647,14 @@ df_note_bb_compute (unsigned int bb_inde
free_EXPR_LIST_node (old_dead_notes);
old_dead_notes = next;
}
+
+ if (debug_insn == -1)
+ {
+ /* ??? We could probably do better here, replacing dead
+ registers with their definitions. */
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+ df_insn_rescan_debug_internal (insn);
+ }
}
}
@@ -3760,6 +3800,9 @@ df_simulate_uses (rtx insn, bitmap live)
df_ref *use_rec;
unsigned int uid = INSN_UID (insn);
+ if (DEBUG_INSN_P (insn))
+ return;
+
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
df_ref use = *use_rec;
@@ -3826,7 +3869,7 @@ df_simulate_initialize_backwards (basic_
void
df_simulate_one_insn_backwards (basic_block bb, rtx insn, bitmap live)
{
- if (! INSN_P (insn))
+ if (!NONDEBUG_INSN_P (insn))
return;
df_simulate_defs (insn, live);
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/reg-stack.c 2009-06-05 05:07:56.000000000 -0300
@@ -1327,6 +1327,30 @@ compare_for_stack_reg (rtx insn, stack r
}
}
+/* Substitute new registers in LOC, which is part of a debug insn.
+ REGSTACK is the current register layout. */
+
+static int
+subst_stack_regs_in_debug_insn (rtx *loc, void *data)
+{
+ rtx *tloc = get_true_reg (loc);
+ stack regstack = (stack)data;
+ int hard_regno;
+
+ if (!STACK_REG_P (*tloc))
+ return 0;
+
+ if (tloc != loc)
+ return 0;
+
+ hard_regno = get_hard_regnum (regstack, *loc);
+ gcc_assert (hard_regno >= FIRST_STACK_REG);
+
+ replace_reg (loc, hard_regno);
+
+ return -1;
+}
+
/* Substitute new registers in PAT, which is part of INSN. REGSTACK
is the current register layout. Return whether a control flow insn
was deleted in the process. */
@@ -1360,6 +1384,9 @@ subst_stack_regs_pat (rtx insn, stack re
since the REG_DEAD notes are not issued.) */
break;
+ case VAR_LOCATION:
+ gcc_unreachable ();
+
case CLOBBER:
{
rtx note;
@@ -2871,6 +2898,7 @@ convert_regs_1 (basic_block block)
int reg;
rtx insn, next;
bool control_flow_insn_deleted = false;
+ int debug_insns_with_starting_stack = 0;
any_malformed_asm = false;
@@ -2923,8 +2951,25 @@ convert_regs_1 (basic_block block)
/* Don't bother processing unless there is a stack reg
mentioned or if it's a CALL_INSN. */
- if (stack_regs_mentioned (insn)
- || CALL_P (insn))
+ if (DEBUG_INSN_P (insn))
+ {
+ if (starting_stack_p)
+ debug_insns_with_starting_stack++;
+ else
+ {
+ for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+ ®stack);
+
+ /* Nothing must ever die at a debug insn. If something
+ is referenced in it that becomes dead, it should have
+ died before and the reference in the debug insn
+ should have been removed so as to avoid changing code
+ generation. */
+ gcc_assert (!REG_NOTES (insn));
+ }
+ }
+ else if (stack_regs_mentioned (insn)
+ || CALL_P (insn))
{
if (dump_file)
{
@@ -2938,6 +2983,24 @@ convert_regs_1 (basic_block block)
}
while (next);
+ if (debug_insns_with_starting_stack)
+ {
+ /* Since it's the first non-debug instruction that determines
+ the stack requirements of the current basic block, we refrain
+ from updating debug insns before it in the loop above, and
+ fix them up here. */
+ for (insn = BB_HEAD (block); debug_insns_with_starting_stack;
+ insn = NEXT_INSN (insn))
+ {
+ if (!DEBUG_INSN_P (insn))
+ continue;
+
+ debug_insns_with_starting_stack--;
+ for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+ &bi->stack_in);
+ }
+ }
+
if (dump_file)
{
fprintf (dump_file, "Expected live registers [");
Index: gcc/cfgrtl.c
===================================================================
--- gcc/cfgrtl.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/cfgrtl.c 2009-06-05 05:07:56.000000000 -0300
@@ -568,11 +568,15 @@ rtl_merge_blocks (basic_block a, basic_b
{
rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
rtx del_first = NULL_RTX, del_last = NULL_RTX;
+ rtx b_debug_start = b_end, b_debug_end = b_end;
int b_empty = 0;
if (dump_file)
fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
+ while (DEBUG_INSN_P (b_end))
+ b_end = PREV_INSN (b_debug_start = b_end);
+
/* If there was a CODE_LABEL beginning B, delete it. */
if (LABEL_P (b_head))
{
@@ -638,9 +642,21 @@ rtl_merge_blocks (basic_block a, basic_b
/* Reassociate the insns of B with A. */
if (!b_empty)
{
- update_bb_for_insn_chain (a_end, b_end, a);
+ update_bb_for_insn_chain (a_end, b_debug_end, a);
- a_end = b_end;
+ a_end = b_debug_end;
+ }
+ else if (b_end != b_debug_end)
+ {
+ /* Move any deleted labels and other notes between the end of A
+ and the debug insns that make up B after the debug insns,
+ bringing the debug insns into A while keeping the notes after
+ the end of A. */
+ if (NEXT_INSN (a_end) != b_debug_start)
+ reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
+ b_debug_end);
+ update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
+ a_end = b_debug_end;
}
df_bb_delete (b->index);
@@ -2164,6 +2180,11 @@ purge_dead_edges (basic_block bb)
bool found;
edge_iterator ei;
+ if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb))
+ do
+ insn = PREV_INSN (insn);
+ while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb));
+
/* If this instruction cannot trap, remove REG_EH_REGION notes. */
if (NONJUMP_INSN_P (insn)
&& (note = find_reg_note (insn, REG_EH_REGION, NULL)))
@@ -2184,10 +2205,10 @@ purge_dead_edges (basic_block bb)
latter can appear when nonlocal gotos are used. */
if (e->flags & EDGE_EH)
{
- if (can_throw_internal (BB_END (bb))
+ if (can_throw_internal (insn)
/* If this is a call edge, verify that this is a call insn. */
&& (! (e->flags & EDGE_ABNORMAL_CALL)
- || CALL_P (BB_END (bb))))
+ || CALL_P (insn)))
{
ei_next (&ei);
continue;
@@ -2195,7 +2216,7 @@ purge_dead_edges (basic_block bb)
}
else if (e->flags & EDGE_ABNORMAL_CALL)
{
- if (CALL_P (BB_END (bb))
+ if (CALL_P (insn)
&& (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
|| INTVAL (XEXP (note, 0)) >= 0))
{
@@ -2773,7 +2794,8 @@ rtl_block_ends_with_call_p (basic_block
while (!CALL_P (insn)
&& insn != BB_HEAD (bb)
&& (keep_with_call_p (insn)
- || NOTE_P (insn)))
+ || NOTE_P (insn)
+ || DEBUG_INSN_P (insn)))
insn = PREV_INSN (insn);
return (CALL_P (insn));
}
Index: gcc/dce.c
===================================================================
--- gcc/dce.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/dce.c 2009-06-05 05:07:56.000000000 -0300
@@ -124,6 +124,7 @@ deletable_insn_p (rtx insn, bool fast, b
switch (GET_CODE (body))
{
case USE:
+ case VAR_LOCATION:
return false;
case CLOBBER:
@@ -643,6 +644,9 @@ mark_reg_dependencies (rtx insn)
struct df_link *defs;
df_ref *use_rec;
+ if (DEBUG_INSN_P (insn))
+ return;
+
for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
{
df_ref use = *use_rec;
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/regcprop.c 2009-06-05 05:08:11.000000000 -0300
@@ -450,7 +450,10 @@ replace_oldest_value_reg (rtx *loc, enum
fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
- validate_change (insn, loc, new_rtx, 1);
+ if (DEBUG_INSN_P (insn))
+ *loc = new_rtx;
+ else
+ validate_change (insn, loc, new_rtx, 1);
return true;
}
return false;
@@ -474,6 +477,9 @@ replace_oldest_value_addr (rtx *loc, enu
switch (code)
{
case PLUS:
+ if (DEBUG_INSN_P (insn))
+ break;
+
{
rtx orig_op0 = XEXP (x, 0);
rtx orig_op1 = XEXP (x, 1);
@@ -608,9 +614,14 @@ replace_oldest_value_addr (rtx *loc, enu
static bool
replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
{
- return replace_oldest_value_addr (&XEXP (x, 0),
- base_reg_class (GET_MODE (x), MEM,
- SCRATCH),
+ enum reg_class cl;
+
+ if (DEBUG_INSN_P (insn))
+ cl = ALL_REGS;
+ else
+ cl = base_reg_class (GET_MODE (x), MEM, SCRATCH);
+
+ return replace_oldest_value_addr (&XEXP (x, 0), cl,
GET_MODE (x), insn, vd);
}
@@ -619,7 +630,7 @@ replace_oldest_value_mem (rtx x, rtx ins
static bool
copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
{
- bool changed = false;
+ bool anything_changed = false;
rtx insn;
for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
@@ -628,8 +639,22 @@ copyprop_hardreg_forward_1 (basic_block
bool is_asm, any_replacements;
rtx set;
bool replaced[MAX_RECOG_OPERANDS];
+ bool changed = false;
- if (! INSN_P (insn))
+ if (DEBUG_INSN_P (insn))
+ {
+ rtx loc = INSN_VAR_LOCATION_LOC (insn);
+ if (!VAR_LOC_UNKNOWN_P (loc)
+ && replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
+ ALL_REGS, GET_MODE (loc),
+ insn, vd))
+ {
+ df_insn_rescan (insn);
+ anything_changed = true;
+ }
+ }
+
+ if (!NONDEBUG_INSN_P (insn))
{
if (insn == BB_END (bb))
break;
@@ -817,6 +842,12 @@ copyprop_hardreg_forward_1 (basic_block
}
did_replacement:
+ if (changed)
+ {
+ df_insn_rescan (insn);
+ anything_changed = true;
+ }
+
/* Clobber call-clobbered registers. */
if (CALL_P (insn))
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -834,7 +865,7 @@ copyprop_hardreg_forward_1 (basic_block
break;
}
- return changed;
+ return anything_changed;
}
/* Main entry point for the forward copy propagation optimization. */
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c.orig 2009-06-05 05:07:49.000000000 -0300
+++ gcc/reload1.c 2009-06-05 05:08:11.000000000 -0300
@@ -800,7 +800,7 @@ reload (rtx first, int global)
&& GET_MODE (insn) != VOIDmode)
PUT_MODE (insn, VOIDmode);
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
scan_paradoxical_subregs (PATTERN (insn));
if (set != 0 && REG_P (SET_DEST (set)))
@@ -1233,6 +1233,36 @@ reload (rtx first, int global)
else if (reg_equiv_mem[i])
XEXP (reg_equiv_mem[i], 0) = addr;
}
+
+ /* We don't want complex addressing modes in debug insns
+ if simpler ones will do, so delegitimize equivalences
+ in debug insns. */
+ if (MAY_HAVE_DEBUG_INSNS && reg_renumber[i] < 0)
+ {
+ rtx reg = regno_reg_rtx[i];
+ rtx equiv = 0;
+ df_ref use;
+
+ if (reg_equiv_constant[i])
+ equiv = reg_equiv_constant[i];
+ else if (reg_equiv_invariant[i])
+ equiv = reg_equiv_invariant[i];
+ else if (reg && MEM_P (reg))
+ {
+ equiv = targetm.delegitimize_address (reg);
+ if (equiv == reg)
+ equiv = 0;
+ }
+ else if (reg && REG_P (reg) && (int)REGNO (reg) != i)
+ equiv = reg;
+
+ if (equiv)
+ for (use = DF_REG_USE_CHAIN (i); use;
+ use = DF_REF_NEXT_REG (use))
+ if (DEBUG_INSN_P (DF_REF_INSN (use))
+ && *DF_REF_LOC (use) == reg)
+ *DF_REF_LOC (use) = copy_rtx (equiv);
+ }
}
/* We must set reload_completed now since the cleanup_subreg_operands call
@@ -3150,7 +3180,8 @@ eliminate_regs_in_insn (rtx insn, int re
|| GET_CODE (PATTERN (insn)) == CLOBBER
|| GET_CODE (PATTERN (insn)) == ADDR_VEC
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
- || GET_CODE (PATTERN (insn)) == ASM_INPUT);
+ || GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || DEBUG_INSN_P (insn));
return 0;
}
@@ -6940,7 +6971,7 @@ emit_input_reload_insns (struct insn_cha
rl->when_needed, old, rl->out, j, 0))
{
rtx temp = PREV_INSN (insn);
- while (temp && NOTE_P (temp))
+ while (temp && (NOTE_P (temp) || DEBUG_INSN_P (temp)))
temp = PREV_INSN (temp);
if (temp
&& NONJUMP_INSN_P (temp)
@@ -6983,6 +7014,13 @@ emit_input_reload_insns (struct insn_cha
alter_reg (REGNO (old), -1, false);
}
special = 1;
+
+ /* Adjust any debug insns between temp and insn. */
+ while ((temp = NEXT_INSN (temp)) != insn)
+ if (DEBUG_INSN_P (temp))
+ replace_rtx (PATTERN (temp), old, reloadreg);
+ else
+ gcc_assert (NOTE_P (temp));
}
else
{
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist Red Hat Brazil Compiler Engineer