aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/basic-block.h21
-rw-r--r--gcc/flow.c78
3 files changed, 70 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 24fc6c2..a83ec6e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2004-11-10 Steven Bosscher <stevenb@suse.de>
+
+ * basic-block.h (XMALLOC_REG_SET, XFREE_REG_SET): New.
+ (struct basic_block_def): Remove local_set and cond_local_set
+ fields. Update comment for global_live_at_start.
+ * flow.c (calculate_global_regs_live): Allocate local_sets and
+ cond_local_sets here as arrays of bitmaps previously stored in
+ bb->local_set and bb->cond_local_set. Use xmalloc instead of
+ obstack allocated bitmaps.
+
2004-11-09 H.J. Lu <hongjiu.lu@intel.com>
PR target/18380
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 7e61a1a..7ef4a46 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -110,6 +110,12 @@ typedef bitmap_iterator reg_set_iterator;
/* Do any cleanup needed on a regset when it is no longer used. */
#define FREE_REG_SET(REGSET) BITMAP_FREE(REGSET)
+/* Allocate a register set with xmalloc. */
+#define XMALLOC_REG_SET() BITMAP_XMALLOC ()
+
+/* Free a register set. */
+#define XFREE_REG_SET(REGSET) BITMAP_XFREE (REGSET)
+
/* Do any one-time initializations needed for regsets. */
#define INIT_ONCE_REG_SET() BITMAP_INIT_ONCE ()
@@ -229,20 +235,9 @@ struct basic_block_def GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb")
VEC(edge) *preds;
VEC(edge) *succs;
- /* Liveness info. */
-
- /* The registers that are modified within this in block. */
- bitmap GTY ((skip (""))) local_set;
- /* The registers that are conditionally modified within this block.
- In other words, registers that are set only as part of a
- COND_EXEC. */
- bitmap GTY ((skip (""))) cond_local_set;
- /* The registers that are live on entry to this block.
-
- Note that in SSA form, global_live_at_start does not reflect the
- use of regs in phi functions, since the liveness of these regs
- may depend on which edge was taken into the block. */
+ /* The registers that are live on entry to this block. */
bitmap GTY ((skip (""))) global_live_at_start;
+
/* The registers that are live on exit from this block. */
bitmap GTY ((skip (""))) global_live_at_end;
diff --git a/gcc/flow.c b/gcc/flow.c
index 86587cc..2ccd755 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -112,7 +112,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* TODO:
Split out from life_analysis:
- - local property discovery (bb->local_live, bb->local_set)
+ - local property discovery
- global property computation
- log links creation
- pre/post modify transformation
@@ -1018,6 +1018,14 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
regset tmp, new_live_at_end, invalidated_by_call;
regset_head tmp_head, invalidated_by_call_head;
regset_head new_live_at_end_head;
+
+ /* The registers that are modified within this in block. */
+ regset *local_sets;
+
+ /* The registers that are conditionally modified within this block.
+ In other words, regs that are set only as part of a COND_EXEC. */
+ regset *cond_local_sets;
+
int i;
/* Some passes used to forget clear aux field of basic block causing
@@ -1036,12 +1044,18 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
SET_REGNO_REG_SET (invalidated_by_call, i);
+ /* Allocate space for the sets of local properties. */
+ local_sets = xcalloc (last_basic_block - (INVALID_BLOCK + 1),
+ sizeof (regset));
+ cond_local_sets = xcalloc (last_basic_block - (INVALID_BLOCK + 1),
+ sizeof (regset));
+
/* Create a worklist. Allocate an extra slot for ENTRY_BLOCK, and one
because the `head == tail' style test for an empty queue doesn't
work with a full queue. */
- queue = xmalloc ((n_basic_blocks + 2) * sizeof (*queue));
+ queue = xmalloc ((n_basic_blocks - (INVALID_BLOCK + 1)) * sizeof (*queue));
qtail = queue;
- qhead = qend = queue + n_basic_blocks + 2;
+ qhead = qend = queue + n_basic_blocks - (INVALID_BLOCK + 1);
/* Queue the blocks set in the initial mask. Do this in reverse block
number order so that we are more likely for the first round to do
@@ -1171,13 +1185,14 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
}
/* On our first pass through this block, we'll go ahead and continue.
- Recognize first pass by local_set NULL. On subsequent passes, we
- get to skip out early if live_at_end wouldn't have changed. */
+ Recognize first pass by checking if local_set is NULL for this
+ basic block. On subsequent passes, we get to skip out early if
+ live_at_end wouldn't have changed. */
- if (bb->local_set == NULL)
+ if (local_sets[bb->index - (INVALID_BLOCK + 1)] == NULL)
{
- bb->local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
- bb->cond_local_set = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+ local_sets[bb->index - (INVALID_BLOCK + 1)] = XMALLOC_REG_SET ();
+ cond_local_sets[bb->index - (INVALID_BLOCK + 1)] = XMALLOC_REG_SET ();
rescan = 1;
}
else
@@ -1190,28 +1205,35 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
new_live_at_end);
if (!rescan)
- /* If any of the registers in the new live_at_end set are
- conditionally set in this basic block, we must rescan.
- This is because conditional lifetimes at the end of the
- block do not just take the live_at_end set into
- account, but also the liveness at the start of each
- successor block. We can miss changes in those sets if
- we only compare the new live_at_end against the
- previous one. */
- rescan = bitmap_intersect_p (new_live_at_end,
- bb->cond_local_set);
+ {
+ regset cond_local_set;
+
+ /* If any of the registers in the new live_at_end set are
+ conditionally set in this basic block, we must rescan.
+ This is because conditional lifetimes at the end of the
+ block do not just take the live_at_end set into
+ account, but also the liveness at the start of each
+ successor block. We can miss changes in those sets if
+ we only compare the new live_at_end against the
+ previous one. */
+ cond_local_set = cond_local_sets[bb->index - (INVALID_BLOCK + 1)];
+ rescan = bitmap_intersect_p (new_live_at_end, cond_local_set);
+ }
if (!rescan)
{
+ regset local_set;
+
/* Find the set of changed bits. Take this opportunity
to notice that this set is empty and early out. */
bitmap_xor (tmp, bb->global_live_at_end, new_live_at_end);
if (bitmap_empty_p (tmp))
continue;
- /* If any of the changed bits overlap with local_set,
+ /* If any of the changed bits overlap with local_sets[bb],
we'll have to rescan the block. */
- rescan = bitmap_intersect_p (tmp, bb->local_set);
+ local_set = local_sets[bb->index - (INVALID_BLOCK + 1)];
+ rescan = bitmap_intersect_p (tmp, local_set);
}
}
@@ -1238,8 +1260,10 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
/* Rescan the block insn by insn to turn (a copy of) live_at_end
into live_at_start. */
- propagate_block (bb, new_live_at_end, bb->local_set,
- bb->cond_local_set, flags);
+ propagate_block (bb, new_live_at_end,
+ local_sets[bb->index - (INVALID_BLOCK + 1)],
+ cond_local_sets[bb->index - (INVALID_BLOCK + 1)],
+ flags);
/* If live_at start didn't change, no need to go farther. */
if (REG_SET_EQUAL_P (bb->global_live_at_start, new_live_at_end))
@@ -1272,20 +1296,22 @@ calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i,
{
basic_block bb = BASIC_BLOCK (i);
- FREE_REG_SET (bb->local_set);
- FREE_REG_SET (bb->cond_local_set);
+ XFREE_REG_SET (local_sets[bb->index - (INVALID_BLOCK + 1)]);
+ XFREE_REG_SET (cond_local_sets[bb->index - (INVALID_BLOCK + 1)]);
});
}
else
{
FOR_EACH_BB (bb)
{
- FREE_REG_SET (bb->local_set);
- FREE_REG_SET (bb->cond_local_set);
+ XFREE_REG_SET (local_sets[bb->index - (INVALID_BLOCK + 1)]);
+ XFREE_REG_SET (cond_local_sets[bb->index - (INVALID_BLOCK + 1)]);
}
}
free (queue);
+ free (cond_local_sets);
+ free (local_sets);
}