/* Register renaming for the GNU compiler.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
#include "obstack.h"
#include "timevar.h"
#include "tree-pass.h"
+#include "df.h"
struct du_chain
{
static void merge_overlapping_regs (basic_block, HARD_REG_SET *,
struct du_chain *);
-/* Called through note_stores from update_life. Find sets of registers, and
+/* Called through note_stores. Find sets of registers, and
record them in *DATA (which is actually a HARD_REG_SET *). */
static void
note_sets (rtx x, rtx set ATTRIBUTE_UNUSED, void *data)
{
HARD_REG_SET *pset = (HARD_REG_SET *) data;
- unsigned int regno;
- int nregs;
if (GET_CODE (x) == SUBREG)
x = SUBREG_REG (x);
if (!REG_P (x))
return;
- regno = REGNO (x);
- nregs = hard_regno_nregs[regno][GET_MODE (x)];
-
/* There must not be pseudos at this point. */
- gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
-
- while (nregs-- > 0)
- SET_HARD_REG_BIT (*pset, regno + nregs);
+ gcc_assert (HARD_REGISTER_P (x));
+ add_to_hard_reg_set (pset, GET_MODE (x), REGNO (x));
}
/* Clear all registers from *PSET for which a note of kind KIND can be found
if (REG_NOTE_KIND (note) == kind && REG_P (XEXP (note, 0)))
{
rtx reg = XEXP (note, 0);
- unsigned int regno = REGNO (reg);
- int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
-
/* There must not be pseudos at this point. */
- gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
-
- while (nregs-- > 0)
- CLEAR_HARD_REG_BIT (*pset, regno + nregs);
+ gcc_assert (HARD_REGISTER_P (reg));
+ remove_from_hard_reg_set (pset, GET_MODE (reg), REGNO (reg));
}
}
rtx insn;
HARD_REG_SET live;
- REG_SET_TO_HARD_REG_SET (live, b->il.rtl->global_live_at_start);
+ REG_SET_TO_HARD_REG_SET (live, df_get_live_in (b));
insn = BB_HEAD (b);
while (t)
{
basic_block bb;
char *first_obj;
+ df_set_flags (DF_LR_RUN_DCE);
+ df_note_add_problem ();
+ df_analyze ();
+ df_set_flags (DF_NO_INSN_RESCAN);
+
memset (tick, 0, sizeof tick);
gcc_obstack_init (&rename_obstack);
/* Don't clobber traceback for noreturn functions. */
if (frame_pointer_needed)
{
- int i;
-
- for (i = hard_regno_nregs[FRAME_POINTER_REGNUM][Pmode]; i--;)
- SET_HARD_REG_BIT (unavailable, FRAME_POINTER_REGNUM + i);
-
+ add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;)
- SET_HARD_REG_BIT (unavailable, HARD_FRAME_POINTER_REGNUM + i);
+ add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
#endif
}
|| fixed_regs[new_reg + i]
|| global_regs[new_reg + i]
/* Can't use regs which aren't saved by the prologue. */
- || (! regs_ever_live[new_reg + i]
+ || (! df_regs_ever_live_p (new_reg + i)
&& ! call_used_regs[new_reg + i])
#ifdef LEAF_REGISTERS
/* We can't use a non-leaf register if we're in a
do_replace (this, best_new_reg);
tick[best_new_reg] = ++this_tick;
- regs_ever_live[best_new_reg] = 1;
+ df_set_regs_ever_live (best_new_reg, true);
if (dump_file)
fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
}
obstack_free (&rename_obstack, NULL);
+ df_clear_flags (DF_NO_INSN_RESCAN);
+ df_insn_rescan_all ();
if (dump_file)
fputc ('\n', dump_file);
-
- count_or_remove_death_notes (NULL, 1);
- update_life_info (NULL, UPDATE_LIFE_LOCAL,
- PROP_DEATH_NOTES);
}
static void
rtx op1 = orig_op1;
rtx *locI = NULL;
rtx *locB = NULL;
- enum rtx_code index_code;
+ enum rtx_code index_code = SCRATCH;
if (GET_CODE (op0) == SUBREG)
{
{
enum machine_mode oldmode = vd->e[i].mode;
rtx new;
- unsigned int last;
- for (last = i; last < i + hard_regno_nregs[i][mode]; last++)
- if (!TEST_HARD_REG_BIT (reg_class_contents[cl], last))
- return NULL_RTX;
+ if (!in_hard_reg_set_p (reg_class_contents[cl], mode, i))
+ return NULL_RTX;
new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
if (new)
rtx op1 = orig_op1;
rtx *locI = NULL;
rtx *locB = NULL;
- enum rtx_code index_code;
+ enum rtx_code index_code = SCRATCH;
if (GET_CODE (op0) == SUBREG)
{
copyprop_hardreg_forward (void)
{
struct value_data *all_vd;
- bool need_refresh;
basic_block bb;
sbitmap visited;
- need_refresh = false;
-
all_vd = XNEWVEC (struct value_data, last_basic_block);
visited = sbitmap_alloc (last_basic_block);
else
init_value_data (all_vd + bb->index);
- if (copyprop_hardreg_forward_1 (bb, all_vd + bb->index))
- need_refresh = true;
+ copyprop_hardreg_forward_1 (bb, all_vd + bb->index);
}
sbitmap_free (visited);
-
- if (need_refresh)
- {
- if (dump_file)
- fputs ("\n\n", dump_file);
-
- /* ??? Irritatingly, delete_noop_moves does not take a set of blocks
- to scan, so we have to do a life update with no initial set of
- blocks Just In Case. */
- delete_noop_moves ();
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES
- | PROP_SCAN_DEAD_CODE
- | PROP_KILL_DEAD_CODE);
- }
-
free (all_vd);
}
static bool
gate_handle_regrename (void)
{
- return (optimize > 0 && (flag_rename_registers || flag_cprop_registers));
+ return (optimize > 0 && (flag_rename_registers));
}
static unsigned int
rest_of_handle_regrename (void)
{
- if (flag_rename_registers)
- regrename_optimize ();
- if (flag_cprop_registers)
- copyprop_hardreg_forward ();
+ regrename_optimize ();
return 0;
}
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish |
+ TODO_dump_func, /* todo_flags_finish */
+ 'n' /* letter */
+};
+
+static bool
+gate_handle_cprop (void)
+{
+ return (optimize > 0 && (flag_cprop_registers));
+}
+
+
+/* Run the regrename and cprop passes. */
+static unsigned int
+rest_of_handle_cprop (void)
+{
+ copyprop_hardreg_forward ();
+ return 0;
+}
+
+struct tree_opt_pass pass_cprop_hardreg =
+{
+ "cprop_hardreg", /* name */
+ gate_handle_cprop, /* gate */
+ rest_of_handle_cprop, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_RENAME_REGISTERS, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
TODO_dump_func, /* todo_flags_finish */
'n' /* letter */
};