/* Data flow analysis for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+ Inc.
This file is part of GCC.
FLAGS is a set of PROP_* flags to be used in accumulating flow info. */
void
-life_analysis (FILE *file, int flags)
+life_analysis (int flags)
{
#ifdef ELIMINABLE_REGS
int i;
if (optimize && (flags & PROP_SCAN_DEAD_STORES))
end_alias_analysis ();
- if (file)
- dump_flow_info (file);
+ if (dump_file)
+ dump_flow_info (dump_file, dump_flags);
/* Removing dead insns should have made jumptables really dead. */
delete_dead_jumptables ();
ndead = 0;
if ((prop_flags & PROP_REG_INFO) && !reg_deaths)
- reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
+ reg_deaths = XCNEWVEC (int, max_regno);
timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
? TV_LIFE_UPDATE : TV_LIFE);
EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi)
{
bb = BASIC_BLOCK (i);
-
- COPY_REG_SET (tmp, bb->il.rtl->global_live_at_end);
- propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
-
- if (extent == UPDATE_LIFE_LOCAL)
- verify_local_live_at_start (tmp, bb);
+ if (bb)
+ {
+ /* The bitmap may be flawed in that one of the basic
+ blocks may have been deleted before you get here. */
+ COPY_REG_SET (tmp, bb->il.rtl->global_live_at_end);
+ propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
+
+ if (extent == UPDATE_LIFE_LOCAL)
+ verify_local_live_at_start (tmp, bb);
+ }
};
}
else
}
}
}
+
if (nnoops && dump_file)
- fprintf (dump_file, "deleted %i noop moves", nnoops);
+ fprintf (dump_file, "deleted %i noop moves\n", nnoops);
+
return nnoops;
}
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 - (INVALID_BLOCK + 1)) * sizeof (*queue));
+ local_sets = XCNEWVEC (bitmap, last_basic_block);
+ cond_local_sets = XCNEWVEC (bitmap, last_basic_block);
+
+ /* Create a worklist. Allocate an extra slot for the `head == tail'
+ style test for an empty queue doesn't work with a full queue. */
+ queue = XNEWVEC (basic_block, n_basic_blocks + 1);
qtail = queue;
- qhead = qend = queue + n_basic_blocks - (INVALID_BLOCK + 1);
+ qhead = qend = queue + n_basic_blocks;
/* 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
}
}
- block_accesses = xcalloc (last_basic_block, sizeof (int));
+ block_accesses = XCNEWVEC (int, last_basic_block);
/* We clean aux when we remove the initially-enqueued bbs, but we
don't enqueue ENTRY and EXIT initially, so clean them upfront and
basic block. On subsequent passes, we get to skip out early if
live_at_end wouldn't have changed. */
- if (local_sets[bb->index - (INVALID_BLOCK + 1)] == NULL)
+ if (local_sets[bb->index] == NULL)
{
- local_sets[bb->index - (INVALID_BLOCK + 1)]
- = ALLOC_REG_SET (®_obstack);
- cond_local_sets[bb->index - (INVALID_BLOCK + 1)]
- = ALLOC_REG_SET (®_obstack);
+ local_sets[bb->index] = ALLOC_REG_SET (®_obstack);
+ cond_local_sets[bb->index] = ALLOC_REG_SET (®_obstack);
rescan = 1;
}
else
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)];
+ cond_local_set = cond_local_sets[bb->index];
rescan = bitmap_intersect_p (new_live_at_end, cond_local_set);
}
/* If any of the changed bits overlap with local_sets[bb],
we'll have to rescan the block. */
- local_set = local_sets[bb->index - (INVALID_BLOCK + 1)];
+ local_set = local_sets[bb->index];
rescan = bitmap_intersect_p (tmp, local_set);
}
}
/* 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,
- local_sets[bb->index - (INVALID_BLOCK + 1)],
- cond_local_sets[bb->index - (INVALID_BLOCK + 1)],
+ local_sets[bb->index],
+ cond_local_sets[bb->index],
flags);
/* If live_at start didn't change, no need to go farther. */
SET_BIT (blocks_out, pbb->index);
/* Makes sure to really rescan the block. */
- if (local_sets[pbb->index - (INVALID_BLOCK + 1)])
+ if (local_sets[pbb->index])
{
- FREE_REG_SET (local_sets[pbb->index - (INVALID_BLOCK + 1)]);
- FREE_REG_SET (cond_local_sets[pbb->index - (INVALID_BLOCK + 1)]);
- local_sets[pbb->index - (INVALID_BLOCK + 1)] = 0;
+ FREE_REG_SET (local_sets[pbb->index]);
+ FREE_REG_SET (cond_local_sets[pbb->index]);
+ local_sets[pbb->index] = 0;
}
/* Add it to the queue. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
basic_block pb = e->src;
+
+ gcc_assert ((e->flags & EDGE_FAKE) == 0);
+
if (pb->aux == NULL)
{
*qtail++ = pb;
EXECUTE_IF_SET_IN_SBITMAP (blocks_out, 0, i, sbi)
{
basic_block bb = BASIC_BLOCK (i);
- FREE_REG_SET (local_sets[bb->index - (INVALID_BLOCK + 1)]);
- FREE_REG_SET (cond_local_sets[bb->index - (INVALID_BLOCK + 1)]);
+ FREE_REG_SET (local_sets[bb->index]);
+ FREE_REG_SET (cond_local_sets[bb->index]);
};
}
else
{
FOR_EACH_BB (bb)
{
- FREE_REG_SET (local_sets[bb->index - (INVALID_BLOCK + 1)]);
- FREE_REG_SET (cond_local_sets[bb->index - (INVALID_BLOCK + 1)]);
+ FREE_REG_SET (local_sets[bb->index]);
+ FREE_REG_SET (cond_local_sets[bb->index]);
}
}
registers whose value is unknown, and may contain some kind of sticky
bits we don't want. */
-int
+static int
initialize_uninitialized_subregs (void)
{
rtx insn;
max_regno = max_reg_num ();
gcc_assert (!reg_deaths);
- reg_deaths = xcalloc (sizeof (*reg_deaths), max_regno);
+ reg_deaths = XCNEWVEC (int, max_regno);
/* Recalculate the register space, in case it has grown. Old style
vector oriented regsets would set regset_{size,bytes} here also. */
init_propagate_block_info (basic_block bb, regset live, regset local_set,
regset cond_local_set, int flags)
{
- struct propagate_block_info *pbi = xmalloc (sizeof (*pbi));
+ struct propagate_block_info *pbi = XNEW (struct propagate_block_info);
pbi->bb = bb;
pbi->reg_live = live;
pbi->insn_num = 0;
if (flags & (PROP_LOG_LINKS | PROP_AUTOINC))
- pbi->reg_next_use = xcalloc (max_reg_num (), sizeof (rtx));
+ pbi->reg_next_use = XCNEWVEC (rtx, max_reg_num ());
else
pbi->reg_next_use = NULL;
struct reg_cond_life_info *rcli;
rtx cond;
- rcli = xmalloc (sizeof (*rcli));
+ rcli = XNEW (struct reg_cond_life_info);
if (REGNO_REG_SET_P (bb_true->il.rtl->global_live_at_start,
i))
int
regno_clobbered_at_setjmp (int regno)
{
- if (n_basic_blocks == 0)
+ if (n_basic_blocks == NUM_FIXED_BLOCKS)
return 0;
return ((REG_N_SETS (regno) > 1
/* The register was unconditionally live previously.
Record the current condition as the condition under
which it is dead. */
- rcli = xmalloc (sizeof (*rcli));
+ rcli = XNEW (struct reg_cond_life_info);
rcli->condition = cond;
rcli->stores = cond;
rcli->orig_condition = const0_rtx;
{
/* The register was not previously live at all. Record
the condition under which it is still dead. */
- rcli = xmalloc (sizeof (*rcli));
+ rcli = XNEW (struct reg_cond_life_info);
rcli->condition = not_reg_cond (cond);
rcli->stores = const0_rtx;
rcli->orig_condition = const0_rtx;
update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES);
if (dump_file)
- dump_flow_info (dump_file);
+ dump_flow_info (dump_file, dump_flags);
}
struct tree_opt_pass pass_recompute_reg_usage =
EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i, sbi)
{
- count += count_or_remove_death_notes_bb (BASIC_BLOCK (i), kill);
+ basic_block bb = BASIC_BLOCK (i);
+ /* The bitmap may be flawed in that one of the basic blocks
+ may have been deleted before you get here. */
+ if (bb)
+ count += count_or_remove_death_notes_bb (bb, kill);
};
}
else
{
regclass_init ();
- life_analysis (dump_file, PROP_FINAL);
+ life_analysis (PROP_FINAL);
if (optimize)
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS
| (flag_thread_jumps ? CLEANUP_THREADING : 0));