#include "bitmap.h"
#include "hard-reg-set.h"
#include "basic-block.h"
+#include "df.h"
#include "expr.h"
#include "recog.h"
#include "params.h"
#include "output.h"
#include "except.h"
#include "reload.h"
-#include "errors.h"
+#include "toplev.h"
#include "integrate.h"
-#include "df.h"
#include "ggc.h"
#include "ira-int.h"
/* Dump file of the allocator if it is not NULL. */
FILE *ira_dump_file;
-/* Pools for allocnos, copies, allocno live ranges. */
-alloc_pool allocno_pool, copy_pool, allocno_live_range_pool;
-
/* The number of elements in the following array. */
int ira_spilled_reg_stack_slots_num;
of given mode starting with given hard register. */
HARD_REG_SET ira_reg_mode_hard_regset[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
-/* The following two variables are array analogs of the macros
- MEMORY_MOVE_COST and REGISTER_MOVE_COST. */
+/* Array analogous to target hook TARGET_MEMORY_MOVE_COST. */
short int ira_memory_move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][2];
+
+/* Array based on TARGET_REGISTER_MOVE_COST. */
move_table *ira_register_move_cost[MAX_MACHINE_MODE];
/* Similar to may_move_in_cost but it is calculated in IRA instead of
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
{
ira_memory_move_cost[mode][cl][0] =
- MEMORY_MOVE_COST ((enum machine_mode) mode,
- (enum reg_class) cl, 0);
+ memory_move_cost ((enum machine_mode) mode,
+ (enum reg_class) cl, false);
ira_memory_move_cost[mode][cl][1] =
- MEMORY_MOVE_COST ((enum machine_mode) mode,
- (enum reg_class) cl, 1);
+ memory_move_cost ((enum machine_mode) mode,
+ (enum reg_class) cl, true);
/* Costs for NO_REGS are used in cost calculation on the
1st pass when the preferred register classes are not
known yet. In this case we take the best scenario. */
{
int i, j, n, cl;
bool set_p;
- const enum reg_class *cover_classes;
+ const reg_class_t *cover_classes;
HARD_REG_SET temp_hard_regset2;
static enum reg_class classes[LIM_REG_CLASSES + 1];
\f
+/* Return nonzero if REGNO is a particularly bad choice for reloading X. */
+static bool
+ira_bad_reload_regno_1 (int regno, rtx x)
+{
+ int x_regno;
+ ira_allocno_t a;
+ enum reg_class pref;
+
+ /* We only deal with pseudo regs. */
+ if (! x || GET_CODE (x) != REG)
+ return false;
+
+ x_regno = REGNO (x);
+ if (x_regno < FIRST_PSEUDO_REGISTER)
+ return false;
+
+ /* If the pseudo prefers REGNO explicitly, then do not consider
+ REGNO a bad spill choice. */
+ pref = reg_preferred_class (x_regno);
+ if (reg_class_size[pref] == 1)
+ return !TEST_HARD_REG_BIT (reg_class_contents[pref], regno);
+
+ /* If the pseudo conflicts with REGNO, then we consider REGNO a
+ poor choice for a reload regno. */
+ a = ira_regno_allocno_map[x_regno];
+ if (TEST_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), regno))
+ return true;
+
+ return false;
+}
+
+/* Return nonzero if REGNO is a particularly bad choice for reloading
+ IN or OUT. */
+bool
+ira_bad_reload_regno (int regno, rtx in, rtx out)
+{
+ return (ira_bad_reload_regno_1 (regno, in)
+ || ira_bad_reload_regno_1 (regno, out));
+}
+
/* Function specific hard registers that can not be used for the
register allocation. */
HARD_REG_SET ira_no_alloc_regs;
return for_each_rtx (&insn, insn_contains_asm_1, NULL);
}
-/* Set up regs_asm_clobbered. */
+/* Add register clobbers from asm statements. */
static void
-compute_regs_asm_clobbered (char *regs_asm_clobbered)
+compute_regs_asm_clobbered (void)
{
basic_block bb;
- memset (regs_asm_clobbered, 0, sizeof (char) * FIRST_PSEUDO_REGISTER);
-
FOR_EACH_BB (bb)
{
rtx insn;
+ hard_regno_nregs[dregno][mode] - 1;
for (i = dregno; i <= end; ++i)
- regs_asm_clobbered[i] = 1;
+ SET_HARD_REG_BIT(crtl->asm_clobbers, i);
}
}
}
void
ira_setup_eliminable_regset (void)
{
- /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
- asm. Unlike regs_ever_live, elements of this array corresponding
- to eliminable regs (like the frame pointer) are set if an asm
- sets them. */
- char *regs_asm_clobbered
- = (char *) alloca (FIRST_PSEUDO_REGISTER * sizeof (char));
#ifdef ELIMINABLE_REGS
int i;
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
CLEAR_HARD_REG_SET (eliminable_regset);
- compute_regs_asm_clobbered (regs_asm_clobbered);
+ compute_regs_asm_clobbered ();
+
/* Build the regset of all eliminable registers and show we can't
use those that we already know won't be eliminated. */
#ifdef ELIMINABLE_REGS
= (! targetm.can_eliminate (eliminables[i].from, eliminables[i].to)
|| (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
- if (! regs_asm_clobbered[eliminables[i].from])
+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, eliminables[i].from))
{
SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
df_set_regs_ever_live (eliminables[i].from, true);
}
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- if (! regs_asm_clobbered[HARD_FRAME_POINTER_REGNUM])
+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
{
SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
if (need_fp)
#endif
#else
- if (! regs_asm_clobbered[FRAME_POINTER_REGNUM])
+ if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
{
SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
if (need_fp)
x = XEXP (note, 0);
- if (! function_invariant_p (x)
- || ! flag_pic
- /* A function invariant is often CONSTANT_P but may
- include a register. We promise to only pass CONSTANT_P
- objects to LEGITIMATE_PIC_OPERAND_P. */
- || (CONSTANT_P (x) && LEGITIMATE_PIC_OPERAND_P (x)))
+ if (! CONSTANT_P (x)
+ || ! flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
{
/* It can happen that a REG_EQUIV note contains a MEM
that is not a legitimate memory operand. As later
if (reg_equiv_init_size < max_regno)
{
- reg_equiv_init
- = (rtx *) ggc_realloc (reg_equiv_init, max_regno * sizeof (rtx));
+ reg_equiv_init = GGC_RESIZEVEC (rtx, reg_equiv_init, max_regno);
while (reg_equiv_init_size < max_regno)
reg_equiv_init[reg_equiv_init_size++] = NULL_RTX;
for (i = FIRST_PSEUDO_REGISTER; i < reg_equiv_init_size; i++)
FOR_EACH_BB (bb)
{
/* We don't use LIVE info in IRA. */
- regset r = DF_LR_IN (bb);
+ bitmap r = DF_LR_IN (bb);
if (REGNO_REG_SET_P (r, from))
{
recorded_label_ref = 0;
reg_equiv = XCNEWVEC (struct equivalence, max_regno);
- reg_equiv_init = GGC_CNEWVEC (rtx, max_regno);
+ reg_equiv_init = ggc_alloc_cleared_vec_rtx (max_regno);
reg_equiv_init_size = max_regno;
init_alias_analysis ();
if (dump_file)
print_insn_chains (dump_file);
}
-
\f
+/* Allocate memory for reg_equiv_memory_loc. */
+static void
+init_reg_equiv_memory_loc (void)
+{
+ max_regno = max_reg_num ();
+
+ /* And the reg_equiv_memory_loc array. */
+ VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
+ memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
+ sizeof (rtx) * max_regno);
+ reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec);
+}
/* All natural loops. */
struct loops ira_loops;
record_loop_exits ();
current_loops = &ira_loops;
+ init_reg_equiv_memory_loc ();
+
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "Building IRA IR\n");
loops_p = ira_build (optimize
#endif
delete_trivially_dead_insns (get_insns (), max_reg_num ());
- max_regno = max_reg_num ();
- /* And the reg_equiv_memory_loc array. */
- VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
- memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
- sizeof (rtx) * max_regno);
- reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec);
+ init_reg_equiv_memory_loc ();
if (max_regno != max_regno_before_ira)
{