aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <wilson@redhat.com>2001-03-27 22:48:03 +0000
committerJim Wilson <wilson@gcc.gnu.org>2001-03-27 14:48:03 -0800
commit685af3af8a54997d1d9e9aa2293b06eca703ec5f (patch)
tree28393dfbb1e83e28e13c0a657a5583983d22b562
parentb044e9d5e9f15c20a62ba92c601128e9630438f4 (diff)
downloadgcc-685af3af8a54997d1d9e9aa2293b06eca703ec5f.zip
gcc-685af3af8a54997d1d9e9aa2293b06eca703ec5f.tar.gz
gcc-685af3af8a54997d1d9e9aa2293b06eca703ec5f.tar.bz2
Fix ia64-linux ICE on bash.
* flow.c (struct reg_cond_life_info): New fields orig_condition and stores. (init_propagate_block_info): Set new fields. (mark_regno_cond_dead): Set and use new fields. (flush_reg_cond_reg_1): Likewise. (and_reg_cond, case AND): Check for redundant AND conditions. (mark_used_reg): Delete unnecessary clears before freeing splay trees. Set new fields. From-SVN: r40881
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/flow.c54
2 files changed, 53 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0ff9729..07107a4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2001-03-27 Jim Wilson <wilson@redhat.com>
+
+ * flow.c (struct reg_cond_life_info): New fields orig_condition
+ and stores.
+ (init_propagate_block_info): Set new fields.
+ (mark_regno_cond_dead): Set and use new fields.
+ (flush_reg_cond_reg_1): Likewise.
+ (and_reg_cond, case AND): Check for redundant AND conditions.
+ (mark_used_reg): Delete unnecessary clears before freeing splay trees.
+ Set new fields.
+
2001-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
* cppmacro.c (stringify_arg): Null terminate strings.
diff --git a/gcc/flow.c b/gcc/flow.c
index 5b9b31b..6625a69 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -275,8 +275,14 @@ static rtx tail_recursion_label_list;
/* Holds information for tracking conditional register life information. */
struct reg_cond_life_info
{
- /* An EXPR_LIST of conditions under which a register is dead. */
+ /* A boolean expression of conditions under which a register is dead. */
rtx condition;
+ /* Conditions under which a register is dead at the basic block end. */
+ rtx orig_condition;
+
+ /* A boolean expression of conditions under which a register has been
+ stored into. */
+ rtx stores;
/* ??? Could store mask of bytes that are dead, so that we could finally
track lifetimes of multi-word registers accessed via subregs. */
@@ -4202,6 +4208,8 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
else
cond = cond_true;
rcli->condition = cond;
+ rcli->stores = const0_rtx;
+ rcli->orig_condition = cond;
splay_tree_insert (pbi->reg_cond_dead, i,
(splay_tree_value) rcli);
@@ -5146,6 +5154,8 @@ mark_regno_cond_dead (pbi, regno, cond)
which it is dead. */
rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
rcli->condition = cond;
+ rcli->stores = cond;
+ rcli->orig_condition = const0_rtx;
splay_tree_insert (pbi->reg_cond_dead, regno,
(splay_tree_value) rcli);
@@ -5161,10 +5171,21 @@ mark_regno_cond_dead (pbi, regno, cond)
rcli = (struct reg_cond_life_info *) node->value;
ncond = rcli->condition;
ncond = ior_reg_cond (ncond, cond, 1);
-
- /* If the register is now unconditionally dead,
- remove the entry in the splay_tree. */
- if (ncond == const1_rtx)
+ if (rcli->stores == const0_rtx)
+ rcli->stores = cond;
+ else if (rcli->stores != const1_rtx)
+ rcli->stores = ior_reg_cond (rcli->stores, cond, 1);
+
+ /* If the register is now unconditionally dead, remove the entry
+ in the splay_tree. A register is unconditionally dead if the
+ dead condition ncond is true. A register is also unconditionally
+ dead if the sum of all conditional stores is an unconditional
+ store (stores is true), and the dead condition is identically the
+ same as the original dead condition initialized at the end of
+ the block. This is a pointer compare, not an rtx_equal_p
+ compare. */
+ if (ncond == const1_rtx
+ || (ncond == rcli->orig_condition && rcli->stores == const1_rtx))
splay_tree_remove (pbi->reg_cond_dead, regno);
else
{
@@ -5210,6 +5231,8 @@ flush_reg_cond_reg_1 (node, data)
/* Splice out portions of the expression that refer to regno. */
rcli = (struct reg_cond_life_info *) node->value;
rcli->condition = elim_reg_cond (rcli->condition, regno);
+ if (rcli->stores != const0_rtx && rcli->stores != const1_rtx)
+ rcli->stores = elim_reg_cond (rcli->stores, regno);
/* If the entire condition is now false, signal the node to be removed. */
if (rcli->condition == const0_rtx)
@@ -5416,6 +5439,17 @@ and_reg_cond (old, x, add)
}
if (! add)
return old;
+
+ /* If X is identical to one of the existing terms of the AND,
+ then just return what we already have. */
+ /* ??? There really should be some sort of recursive check here in
+ case there are nested ANDs. */
+ if ((GET_CODE (XEXP (old, 0)) == GET_CODE (x)
+ && REGNO (XEXP (XEXP (old, 0), 0)) == REGNO (XEXP (x, 0)))
+ || (GET_CODE (XEXP (old, 1)) == GET_CODE (x)
+ && REGNO (XEXP (XEXP (old, 1), 0)) == REGNO (XEXP (x, 0))))
+ return old;
+
return gen_rtx_AND (0, old, x);
case NOT:
@@ -5899,10 +5933,7 @@ mark_used_reg (pbi, reg, cond, insn)
/* If the register is now unconditionally live, remove the
entry in the splay_tree. */
if (ncond == const0_rtx)
- {
- rcli->condition = NULL_RTX;
- splay_tree_remove (pbi->reg_cond_dead, regno);
- }
+ splay_tree_remove (pbi->reg_cond_dead, regno);
else
{
rcli->condition = ncond;
@@ -5916,6 +5947,8 @@ mark_used_reg (pbi, reg, cond, insn)
the condition under which it is still dead. */
rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
rcli->condition = not_reg_cond (cond);
+ rcli->stores = const0_rtx;
+ rcli->orig_condition = const0_rtx;
splay_tree_insert (pbi->reg_cond_dead, regno,
(splay_tree_value) rcli);
@@ -5925,7 +5958,6 @@ mark_used_reg (pbi, reg, cond, insn)
else if (some_was_live)
{
splay_tree_node node;
- struct reg_cond_life_info *rcli;
node = splay_tree_lookup (pbi->reg_cond_dead, regno);
if (node != NULL)
@@ -5934,8 +5966,6 @@ mark_used_reg (pbi, reg, cond, insn)
unconditionally so. Remove it from the conditionally dead
list, so that a conditional set won't cause us to think
it dead. */
- rcli = (struct reg_cond_life_info *) node->value;
- rcli->condition = NULL_RTX;
splay_tree_remove (pbi->reg_cond_dead, regno);
}
}