summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/flow.c76
-rw-r--r--gcc/recog.c2
-rw-r--r--gcc/reg-stack.c11
-rw-r--r--gcc/regrename.c2
-rw-r--r--gcc/toplev.c2
6 files changed, 101 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dea07e5a38c..3eaa2a20b46 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2004-02-06 Jan Hubicka <jh@suse.cz>
+
+ * recog.c (split_all_insns): Do not update reg info.
+ * regrename.c (regrename_optimize): Likewise.
+ * toplev.c (rest_of_handle_reorder_blocks): Likewise.
+ * flow.c (struct propagate_block_info): Add insn_num field.
+ (reg_deaths): New array.
+ (life_analysis): Free reg_deaths info.
+ (allocate_reg_life_data): Allocate reg_deaths array.
+ (propagate_one_insn): Use new array.
+ (init_propagate_block): Initialize it.
+ (free_propagate_block_info): Finish compuation of
+ REG_LIVE_LENGTH
+ (attempt_auto_inc): Sanity check that REG_INFO is not
+ computed at same time.
+ (mark_used_regs): Update new array.
+
+ * reg-stack.c (subst_stack_regs): Unshare clobbers before
+ substitution.
+
2004-02-06 Kazu Hirata <kazu@cs.umass.edu>
* config/s390/s390.md (*extendsiqi2_short_displ): Change to
diff --git a/gcc/flow.c b/gcc/flow.c
index 1ed469f8f48..049a587903e 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -264,11 +264,28 @@ struct propagate_block_info
/* Flags controlling the set of information propagate_block collects. */
int flags;
+ /* Index of instruction being processed. */
+ int insn_num;
};
/* Number of dead insns removed. */
static int ndead;
+/* When PROP_REG_INFO set, array contains pbi->insn_num of instruction
+ where given register died. When the register is marked alive, we use the
+ information to compute amount of instructions life range cross.
+ (remember, we are walking backward). This can be computed as current
+ pbi->insn_num - reg_deaths[regno].
+ At the end of processing each basic block, the remaining live registers
+ are inspected and liferanges are increased same way so liverange of global
+ registers are computed correctly.
+
+ The array is maintained clear for dead registers, so it can be safely reused
+ for next basic block without expensive memset of the whole array after
+ reseting pbi->insn_num to 0. */
+
+static int *reg_deaths;
+
/* Maximum length of pbi->mem_set_list before we start dropping
new elements on the floor. */
#define MAX_MEM_SET_LIST_LEN 100
@@ -458,6 +475,11 @@ life_analysis (rtx f, FILE *file, int flags)
memset (regs_asm_clobbered, 0, sizeof (regs_asm_clobbered));
}
update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
+ if (reg_deaths)
+ {
+ free (reg_deaths);
+ reg_deaths = NULL;
+ }
/* Clean up. */
if (optimize && (flags & PROP_SCAN_DEAD_STORES))
@@ -734,6 +756,11 @@ update_life_info (sbitmap blocks, enum update_life_extent extent, int prop_flags
}
});
}
+ if (reg_deaths)
+ {
+ free (reg_deaths);
+ reg_deaths = NULL;
+ }
timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
? TV_LIFE_UPDATE : TV_LIFE);
if (ndead && rtl_dump_file)
@@ -1457,6 +1484,9 @@ allocate_reg_life_data (void)
int i;
max_regno = max_reg_num ();
+ if (reg_deaths)
+ abort ();
+ reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
/* Recalculate the register space, in case it has grown. Old style
vector oriented regsets would set regset_{size,bytes} here also. */
@@ -1783,6 +1813,9 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn);
/* The stack ptr is used (honorarily) by a CALL insn. */
+ if ((flags & PROP_REG_INFO)
+ && !REGNO_REG_SET_P (pbi->reg_live, STACK_POINTER_REGNUM))
+ reg_deaths[STACK_POINTER_REGNUM] = pbi->insn_num;
SET_REGNO_REG_SET (pbi->reg_live, STACK_POINTER_REGNUM);
/* Calls may also reference any of the global registers,
@@ -1793,11 +1826,7 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
}
}
- /* On final pass, update counts of how many insns in which each reg
- is live. */
- if (flags & PROP_REG_INFO)
- EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
- { REG_LIVE_LENGTH (i)++; });
+ pbi->insn_num++;
return prev;
}
@@ -1820,6 +1849,7 @@ init_propagate_block_info (basic_block bb, regset live, regset local_set,
pbi->cond_local_set = cond_local_set;
pbi->cc0_live = 0;
pbi->flags = flags;
+ pbi->insn_num = 0;
if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx));
@@ -1976,6 +2006,16 @@ free_propagate_block_info (struct propagate_block_info *pbi)
BITMAP_XFREE (pbi->reg_cond_reg);
#endif
+ if (pbi->flags & PROP_REG_INFO)
+ {
+ int num = pbi->insn_num;
+ int i;
+
+ EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i,
+ { REG_LIVE_LENGTH (i) += num - reg_deaths[i];
+ reg_deaths[i] = 0;
+ });
+ }
if (pbi->reg_next_use)
free (pbi->reg_next_use);
@@ -2803,7 +2843,15 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
{
for (i = regno_first; i <= regno_last; ++i)
if (!(not_dead & (((unsigned long) 1) << (i - regno_first))))
- CLEAR_REGNO_REG_SET (pbi->reg_live, i);
+ {
+ if ((pbi->flags & PROP_REG_INFO)
+ && REGNO_REG_SET_P (pbi->reg_live, i))
+ {
+ REG_LIVE_LENGTH (i) += pbi->insn_num - reg_deaths[i];
+ reg_deaths[i] = 0;
+ }
+ CLEAR_REGNO_REG_SET (pbi->reg_live, i);
+ }
}
}
else if (GET_CODE (reg) == REG)
@@ -3334,6 +3382,10 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
on this insn, which is incorrect. */
SET_REGNO_REG_SET (pbi->reg_live, regno);
+ /* We shall not do the autoinc during final pass. */
+ if (flags & PROP_REG_INFO)
+ abort ();
+
/* If there are any calls between INSN and INCR, show
that REGNO now crosses them. */
for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
@@ -3365,6 +3417,9 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
/* If the original source was dead, it's dead now. */
rtx note;
+ /* We shall not do the autoinc during final pass. */
+ if (flags & PROP_REG_INFO)
+ abort ();
while ((note = find_reg_note (incr, REG_DEAD, NULL_RTX)) != NULL_RTX)
{
remove_note (incr, note);
@@ -3550,6 +3605,15 @@ mark_used_reg (struct propagate_block_info *pbi, rtx reg,
REG_FREQ (regno_first) += REG_FREQ_FROM_BB (pbi->bb);
REG_N_REFS (regno_first)++;
}
+ for (i = regno_first; i <= regno_last; ++i)
+ if (! REGNO_REG_SET_P (pbi->reg_live, i))
+ {
+#ifdef ENABLE_CHECKING
+ if (reg_deaths[i])
+ abort ();
+#endif
+ reg_deaths[i] = pbi->insn_num;
+ }
}
/* Record and count the insns in which a reg dies. If it is used in
diff --git a/gcc/recog.c b/gcc/recog.c
index 470e93b06a3..9b5f4d4152c 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2795,7 +2795,7 @@ split_all_insns (int upd_life)
if (changed && upd_life)
update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES | PROP_REG_INFO);
+ PROP_DEATH_NOTES);
#ifdef ENABLE_CHECKING
verify_flow_info ();
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 433b7393ab6..90e137df56a 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -2236,9 +2236,14 @@ subst_stack_regs (rtx insn, stack regstack)
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
{
if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
- control_flow_insn_deleted
- |= subst_stack_regs_pat (insn, regstack,
- XVECEXP (PATTERN (insn), 0, i));
+ {
+ if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == CLOBBER)
+ XVECEXP (PATTERN (insn), 0, i)
+ = shallow_copy_rtx (XVECEXP (PATTERN (insn), 0, i));
+ control_flow_insn_deleted
+ |= subst_stack_regs_pat (insn, regstack,
+ XVECEXP (PATTERN (insn), 0, i));
+ }
}
else
control_flow_insn_deleted
diff --git a/gcc/regrename.c b/gcc/regrename.c
index 914bfbc9cb6..8a83b9687e2 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -360,7 +360,7 @@ regrename_optimize (void)
count_or_remove_death_notes (NULL, 1);
update_life_info (NULL, UPDATE_LIFE_LOCAL,
- PROP_REG_INFO | PROP_DEATH_NOTES);
+ PROP_DEATH_NOTES);
}
static void
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5f2c12b6653..369ba5c04f4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2331,7 +2331,7 @@ rest_of_handle_reorder_blocks (tree decl, rtx insns)
but should not be terribly bad. */
if (changed && HAVE_conditional_execution)
update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES | PROP_REG_INFO);
+ PROP_DEATH_NOTES);
close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
}