/* Compute different info about registers.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009, 2010 Free Software Foundation, Inc.
+ 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
and are also considered fixed. */
char global_regs[FIRST_PSEUDO_REGISTER];
+/* Declaration for the global register. */
+static tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER];
+
/* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used
in dataflow more conveniently. */
regset regs_invalidated_by_call_regset;
+/* Same information as FIXED_REG_SET but in regset form. */
+regset fixed_reg_set_regset;
+
/* The bitmap_obstack is used to hold some static variables that
should not be reset after each function is compiled. */
static bitmap_obstack persistent_obstack;
memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order);
#endif
memcpy (reg_names, initial_reg_names, sizeof reg_names);
+
+ SET_HARD_REG_SET (accessible_reg_set);
+ SET_HARD_REG_SET (operand_reg_set);
}
/* Initialize may_move_cost and friends for mode M. */
static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER];
#endif
static const char *saved_reg_names[FIRST_PSEUDO_REGISTER];
+static HARD_REG_SET saved_accessible_reg_set;
+static HARD_REG_SET saved_operand_reg_set;
/* Save the register information. */
void
/* And similarly for reg_names. */
gcc_assert (sizeof reg_names == sizeof saved_reg_names);
memcpy (saved_reg_names, reg_names, sizeof reg_names);
+ COPY_HARD_REG_SET (saved_accessible_reg_set, accessible_reg_set);
+ COPY_HARD_REG_SET (saved_operand_reg_set, operand_reg_set);
}
/* Restore the register information. */
#endif
memcpy (reg_names, saved_reg_names, sizeof reg_names);
+ COPY_HARD_REG_SET (accessible_reg_set, saved_accessible_reg_set);
+ COPY_HARD_REG_SET (operand_reg_set, saved_operand_reg_set);
}
/* After switches have been processed, which perhaps alter
}
else
CLEAR_REG_SET (regs_invalidated_by_call_regset);
+ if (!fixed_reg_set_regset)
+ fixed_reg_set_regset = ALLOC_REG_SET (&persistent_obstack);
+ else
+ CLEAR_REG_SET (fixed_reg_set_regset);
+ AND_HARD_REG_SET (operand_reg_set, accessible_reg_set);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
+ /* As a special exception, registers whose class is NO_REGS are
+ not accepted by `register_operand'. The reason for this change
+ is to allow the representation of special architecture artifacts
+ (such as a condition code register) without extending the rtl
+ definitions. Since registers of class NO_REGS cannot be used
+ as registers in any case where register classes are examined,
+ it is better to apply this exception in a target-independent way. */
+ if (REGNO_REG_CLASS (i) == NO_REGS)
+ CLEAR_HARD_REG_BIT (operand_reg_set, i);
+
+ /* If a register is too limited to be treated as a register operand,
+ then it should never be allocated to a pseudo. */
+ if (!TEST_HARD_REG_BIT (operand_reg_set, i))
+ {
+ fixed_regs[i] = 1;
+ call_used_regs[i] = 1;
+ }
+
/* call_used_regs must include fixed_regs. */
gcc_assert (!fixed_regs[i] || call_used_regs[i]);
#ifdef CALL_REALLY_USED_REGISTERS
#endif
if (fixed_regs[i])
- SET_HARD_REG_BIT (fixed_reg_set, i);
+ {
+ SET_HARD_REG_BIT (fixed_reg_set, i);
+ SET_REGNO_REG_SET (fixed_reg_set_regset, i);
+ }
if (call_used_regs[i])
SET_HARD_REG_BIT (call_used_reg_set, i);
SET_HARD_REG_BIT (ok_regs, j);
for (i = 0; i < N_REG_CLASSES; i++)
- if (((unsigned) CLASS_MAX_NREGS ((enum reg_class) i,
- (enum machine_mode) m)
+ if ((targetm.class_max_nregs ((reg_class_t) i, (enum machine_mode) m)
<= reg_class_size[i])
&& hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
{
}
/* Compute cost of moving registers to/from memory. */
+
int
-memory_move_cost (enum machine_mode mode, enum reg_class rclass, bool in)
+memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in)
{
return targetm.memory_move_cost (mode, rclass, in);
}
/* Mark register number I as global. */
void
-globalize_reg (int i)
+globalize_reg (tree decl, int i)
{
+ location_t loc = DECL_SOURCE_LOCATION (decl);
+
#ifdef STACK_REGS
if (IN_RANGE (i, FIRST_STACK_REG, LAST_STACK_REG))
{
#endif
if (fixed_regs[i] == 0 && no_global_reg_vars)
- error ("global register variable follows a function definition");
+ error_at (loc, "global register variable follows a function definition");
if (global_regs[i])
{
- warning (0, "register used for two global register variables");
+ warning_at (loc, 0,
+ "register of %qD used for multiple global register variables",
+ decl);
+ inform (DECL_SOURCE_LOCATION (global_regs_decl[i]),
+ "conflicts with %qD", global_regs_decl[i]);
return;
}
if (call_used_regs[i] && ! fixed_regs[i])
- warning (0, "call-clobbered register used for global register variable");
+ warning_at (loc, 0, "call-clobbered register used for global register variable");
global_regs[i] = 1;
+ global_regs_decl[i] = decl;
/* If we're globalizing the frame pointer, we need to set the
appropriate regs_invalidated_by_call bit, even if it's already