/* Indexed by n, giving various register information */
-varray_type reg_n_info;
+VEC(reg_info_p,heap) *reg_n_info;
/* Regset of regs live when calls to `setjmp'-like functions happen. */
/* ??? Does this exist only for the setjmp-clobbered warning message? */
end_alias_analysis ();
if (dump_file)
- dump_flow_info (dump_file);
+ dump_flow_info (dump_file, dump_flags);
/* Removing dead insns should have made jumptables really dead. */
delete_dead_jumptables ();
fprintf (dump_file, "Register %d died unexpectedly.\n", regno);
dump_bb (bb, dump_file, 0);
}
- fatal_error ("internal consistency failure");
+ internal_error ("internal consistency failure");
}
/* A subroutine of update_life_info. Verify that there are no untoward
fputs ("Old:\n", dump_file);
dump_bb (bb, dump_file, 0);
}
- fatal_error ("internal consistency failure");
+ internal_error ("internal consistency failure");
}
}
else
"Register %d died unexpectedly.\n", i);
dump_bb (bb, dump_file, 0);
}
- fatal_error ("internal consistency failure");
+ internal_error ("internal consistency failure");
}
/* Verify that the now-live register is wider than word_mode. */
verify_wide_reg (i, bb);
count_or_remove_death_notes (blocks,
prop_flags & PROP_POST_REGSTACK ? -1 : 1);
}
+ else
+ {
+ /* FIXME: This can go when the dataflow branch has been merged in. */
+ /* For a local update, if we are creating new REG_DEAD notes, then we
+ must delete the old ones first to avoid conflicts if they are
+ different. */
+ if (prop_flags & PROP_DEATH_NOTES)
+ count_or_remove_death_notes (blocks,
+ prop_flags & PROP_POST_REGSTACK ? -1 : 1);
+ }
+
/* Clear log links in case we are asked to (re)compute them. */
if (prop_flags & PROP_LOG_LINKS)
calculate_global_regs_live (sbitmap blocks_in, sbitmap blocks_out, int flags)
{
basic_block *queue, *qhead, *qtail, *qend, bb;
- regset tmp, new_live_at_end, invalidated_by_call;
+ regset tmp, new_live_at_end, invalidated_by_eh_edge;
regset registers_made_dead;
bool failure_strategy_required = false;
int *block_accesses;
tmp = ALLOC_REG_SET (®_obstack);
new_live_at_end = ALLOC_REG_SET (®_obstack);
- invalidated_by_call = ALLOC_REG_SET (®_obstack);
+ invalidated_by_eh_edge = ALLOC_REG_SET (®_obstack);
registers_made_dead = ALLOC_REG_SET (®_obstack);
/* Inconveniently, this is only readily available in hard reg set form. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
- SET_REGNO_REG_SET (invalidated_by_call, i);
+ SET_REGNO_REG_SET (invalidated_by_eh_edge, i);
+
+ /* The exception handling registers die at eh edges. */
+#ifdef EH_RETURN_DATA_REGNO
+ for (i = 0; ; ++i)
+ {
+ unsigned regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ SET_REGNO_REG_SET (invalidated_by_eh_edge, regno);
+ }
+#endif
/* Allocate space for the sets of local properties. */
local_sets = XCNEWVEC (bitmap, last_basic_block);
if (e->flags & EDGE_EH)
bitmap_ior_and_compl_into (new_live_at_end,
sb->il.rtl->global_live_at_start,
- invalidated_by_call);
+ invalidated_by_eh_edge);
else
IOR_REG_SET (new_live_at_end, sb->il.rtl->global_live_at_start);
FREE_REG_SET (tmp);
FREE_REG_SET (new_live_at_end);
- FREE_REG_SET (invalidated_by_call);
+ FREE_REG_SET (invalidated_by_eh_edge);
FREE_REG_SET (registers_made_dead);
if (blocks_out)
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
- bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ if (bb->il.rtl->global_live_at_start)
+ {
+ CLEAR_REG_SET (bb->il.rtl->global_live_at_start);
+ CLEAR_REG_SET (bb->il.rtl->global_live_at_end);
+ }
+ else
+ {
+ bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
+ bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
+ }
}
regs_live_at_setjmp = ALLOC_REG_SET (®_obstack);
break;
}
+#ifdef EH_RETURN_DATA_REGNO
+ if (bb_has_eh_pred (bb))
+ {
+ unsigned int i;
+ for (i = 0; ; ++i)
+ {
+ unsigned regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ if (pbi->local_set)
+ {
+ CLEAR_REGNO_REG_SET (pbi->cond_local_set, regno);
+ SET_REGNO_REG_SET (pbi->local_set, regno);
+ }
+ if (REGNO_REG_SET_P (pbi->reg_live, regno))
+ SET_REGNO_REG_SET (pbi->new_set, regno);
+
+ regs_ever_live[regno] = 1;
+ }
+ }
+#endif
+
free_propagate_block_info (pbi);
return changed;
It might be worthwhile to update REG_LIVE_LENGTH, REG_BASIC_BLOCK and
possibly other information which is used by the register allocators. */
-void
+static unsigned int
recompute_reg_usage (void)
{
allocate_reg_life_data ();
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);
+ return 0;
}
struct tree_opt_pass pass_recompute_reg_usage =
return flag_profile_values;
}
-static void
+static unsigned int
rest_of_handle_remove_death_notes (void)
{
count_or_remove_death_notes (NULL, 1);
+ return 0;
}
struct tree_opt_pass pass_remove_death_notes =
};
/* Perform life analysis. */
-static void
+static unsigned int
rest_of_handle_life (void)
{
regclass_init ();
}
no_new_pseudos = 1;
+ return 0;
}
struct tree_opt_pass pass_life =
'f' /* letter */
};
-static void
+static unsigned int
rest_of_handle_flow2 (void)
{
/* If optimizing, then go ahead and split insns now. */
thread_prologue_and_epilogue_insns (get_insns ());
epilogue_completed = 1;
flow2_completed = 1;
+ return 0;
}
struct tree_opt_pass pass_flow2 =