Add support for -mreg-alloc=<xxx>
From-SVN: r8040
This commit is contained in:
parent
0be5d99ff2
commit
f5316dfe88
@ -74,8 +74,120 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
|
||||
/* Test and compare insns in i386.md store the information needed to
|
||||
generate branch and scc insns here. */
|
||||
|
||||
struct rtx_def *i386_compare_op0, *i386_compare_op1;
|
||||
struct rtx_def *i386_compare_op0 = NULL_RTX;
|
||||
struct rtx_def *i386_compare_op1 = NULL_RTX;
|
||||
struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
|
||||
|
||||
/* Register allocation order */
|
||||
char *i386_reg_alloc_order = (char *)0;
|
||||
static char regs_allocated[FIRST_PSEUDO_REGISTER];
|
||||
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
sense on a particular target machine. You can define a macro
|
||||
`OVERRIDE_OPTIONS' to take account of this. This macro, if
|
||||
defined, is executed once just after all the command options have
|
||||
been parsed.
|
||||
|
||||
Don't use this macro to turn on various extra optimizations for
|
||||
`-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
|
||||
|
||||
void
|
||||
override_options ()
|
||||
{
|
||||
int ch, i, regno;
|
||||
|
||||
#ifdef SUBTARGET_OVERRIDE_OPTIONS
|
||||
SUBTARGET_OVERRIDE_OPTIONS;
|
||||
#endif
|
||||
|
||||
/* Validate registers in register allocation order */
|
||||
if (i386_reg_alloc_order)
|
||||
{
|
||||
for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'a': regno = 0; break;
|
||||
case 'd': regno = 1; break;
|
||||
case 'c': regno = 2; break;
|
||||
case 'b': regno = 3; break;
|
||||
case 'S': regno = 4; break;
|
||||
case 'D': regno = 5; break;
|
||||
case 'B': regno = 6; break;
|
||||
|
||||
default: fatal ("Register '%c' is unknown", ch);
|
||||
}
|
||||
|
||||
if (regs_allocated[regno])
|
||||
fatal ("Register '%c' was already specified in the allocation order", ch);
|
||||
|
||||
regs_allocated[regno] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A C statement (sans semicolon) to choose the order in which to
|
||||
allocate hard registers for pseudo-registers local to a basic
|
||||
block.
|
||||
|
||||
Store the desired register order in the array `reg_alloc_order'.
|
||||
Element 0 should be the register to allocate first; element 1, the
|
||||
next register; and so on.
|
||||
|
||||
The macro body should not assume anything about the contents of
|
||||
`reg_alloc_order' before execution of the macro.
|
||||
|
||||
On most machines, it is not necessary to define this macro. */
|
||||
|
||||
void
|
||||
order_regs_for_local_alloc ()
|
||||
{
|
||||
int i, ch, order, regno;
|
||||
|
||||
/* User specified the register allocation order */
|
||||
if (i386_reg_alloc_order)
|
||||
{
|
||||
for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'a': regno = 0; break;
|
||||
case 'd': regno = 1; break;
|
||||
case 'c': regno = 2; break;
|
||||
case 'b': regno = 3; break;
|
||||
case 'S': regno = 4; break;
|
||||
case 'D': regno = 5; break;
|
||||
case 'B': regno = 6; break;
|
||||
}
|
||||
|
||||
reg_alloc_order[order++] = regno;
|
||||
}
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
{
|
||||
if (!regs_allocated[i])
|
||||
reg_alloc_order[order++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* If users did not specify a register allocation order, favor eax
|
||||
normally except if cse is following jumps, then favor edx so
|
||||
that function returns are cse'ed */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
reg_alloc_order[i] = i;
|
||||
|
||||
if (optimize && flag_cse_follow_jumps && !leaf_function_p ())
|
||||
{
|
||||
reg_alloc_order[0] = 1; /* edx */
|
||||
reg_alloc_order[1] = 2; /* ecx */
|
||||
reg_alloc_order[2] = 0; /* eax */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Output an insn whose source is a 386 integer register. SRC is the
|
||||
rtx for the register, and TEMPLATE is the op-code template. SRC may
|
||||
|
@ -158,16 +158,34 @@ extern int target_flags;
|
||||
SUBTARGET_SWITCHES \
|
||||
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
|
||||
|
||||
/* This is meant to be redefined in the host dependent files */
|
||||
/* This macro is similar to `TARGET_SWITCHES' but defines names of
|
||||
command options that have values. Its definition is an
|
||||
initializer with a subgrouping for each command option.
|
||||
|
||||
Each subgrouping contains a string constant, that defines the
|
||||
fixed part of the option name, and the address of a variable. The
|
||||
variable, type `char *', is set to the variable part of the given
|
||||
option if the fixed part matches. The actual option name is made
|
||||
by appending `-m' to the specified name. */
|
||||
#define TARGET_OPTIONS \
|
||||
{ { "reg-alloc=", &i386_reg_alloc_order }, \
|
||||
SUBTARGET_OPTIONS }
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
sense on a particular target machine. You can define a macro
|
||||
`OVERRIDE_OPTIONS' to take account of this. This macro, if
|
||||
defined, is executed once just after all the command options have
|
||||
been parsed.
|
||||
|
||||
Don't use this macro to turn on various extra optimizations for
|
||||
`-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
|
||||
|
||||
#define OVERRIDE_OPTIONS override_options ()
|
||||
|
||||
/* These are meant to be redefined in the host dependent files */
|
||||
#define SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_OPTIONS
|
||||
|
||||
#define OVERRIDE_OPTIONS \
|
||||
{ \
|
||||
SUBTARGET_OVERRIDE_OPTIONS \
|
||||
}
|
||||
|
||||
/* This is meant to be redefined in the host dependent files */
|
||||
#define SUBTARGET_OVERRIDE_OPTIONS
|
||||
|
||||
/* target machine storage layout */
|
||||
|
||||
@ -313,11 +331,24 @@ extern int target_flags;
|
||||
functions, and a slightly slower compiler. Users complained about the code
|
||||
generated by allocating edx first, so restore the 'natural' order of things. */
|
||||
|
||||
#if 0
|
||||
#define REG_ALLOC_ORDER \
|
||||
/*dx,cx,ax,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
|
||||
{ 1, 2, 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
|
||||
#endif
|
||||
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
|
||||
|
||||
/* A C statement (sans semicolon) to choose the order in which to
|
||||
allocate hard registers for pseudo-registers local to a basic
|
||||
block.
|
||||
|
||||
Store the desired register order in the array `reg_alloc_order'.
|
||||
Element 0 should be the register to allocate first; element 1, the
|
||||
next register; and so on.
|
||||
|
||||
The macro body should not assume anything about the contents of
|
||||
`reg_alloc_order' before execution of the macro.
|
||||
|
||||
On most machines, it is not necessary to define this macro. */
|
||||
|
||||
#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
|
||||
|
||||
/* Macro to conditionally modify fixed_regs/call_used_regs. */
|
||||
#define CONDITIONAL_REGISTER_USAGE \
|
||||
@ -509,7 +540,6 @@ enum reg_class
|
||||
reg number REGNO. This could be a conditional expression
|
||||
or could index an array. */
|
||||
|
||||
extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
|
||||
#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
|
||||
|
||||
/* When defined, the compiler allows registers explicitly used in the
|
||||
@ -641,6 +671,32 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
|
||||
#define CLASS_MAX_NREGS(CLASS, MODE) \
|
||||
(FLOAT_CLASS_P (CLASS) ? 1 : \
|
||||
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
|
||||
|
||||
/* A C expression whose value is nonzero if pseudos that have been
|
||||
assigned to registers of class CLASS would likely be spilled
|
||||
because registers of CLASS are needed for spill registers.
|
||||
|
||||
The default value of this macro returns 1 if CLASS has exactly one
|
||||
register and zero otherwise. On most machines, this default
|
||||
should be used. Only define this macro to some other expression
|
||||
if pseudo allocated by `local-alloc.c' end up in memory because
|
||||
their hard registers were needed for spill regisers. If this
|
||||
macro returns nonzero for those classes, those pseudos will only
|
||||
be allocated by `global.c', which knows how to reallocate the
|
||||
pseudo to another register. If there would not be another
|
||||
register available for reallocation, you should not change the
|
||||
definition of this macro since the only effect of such a
|
||||
definition would be to slow down register allocation. */
|
||||
|
||||
#define CLASS_LIKELY_SPILLED_P(CLASS) \
|
||||
(((CLASS) == AREG) \
|
||||
|| ((CLASS) == DREG) \
|
||||
|| ((CLASS) == CREG) \
|
||||
|| ((CLASS) == BREG) \
|
||||
|| ((CLASS) == AD_REGS) \
|
||||
|| ((CLASS) == SIREG) \
|
||||
|| ((CLASS) == DIREG))
|
||||
|
||||
|
||||
/* Stack layout; function entry, exit and calling. */
|
||||
|
||||
@ -1296,7 +1352,6 @@ while (0)
|
||||
stored from the compare operation. Note that we can't use "rtx" here
|
||||
since it hasn't been defined! */
|
||||
|
||||
extern struct rtx_def *i386_compare_op0, *i386_compare_op1;
|
||||
extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
@ -1643,6 +1698,8 @@ extern char *qi_high_reg_name[];
|
||||
#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
|
||||
|
||||
/* Functions in i386.c */
|
||||
extern void override_options ();
|
||||
extern void order_regs_for_local_alloc ();
|
||||
extern void output_op_from_reg ();
|
||||
extern void output_to_reg ();
|
||||
extern char *singlemove_string ();
|
||||
@ -1676,9 +1733,18 @@ extern void restore_386_machine_status ();
|
||||
extern void clear_386_stack_locals ();
|
||||
extern struct rtx_def *assign_386_stack_local ();
|
||||
|
||||
/* Variables in i386.c */
|
||||
extern char *i386_reg_alloc_order; /* register allocation order */
|
||||
extern char *hi_reg_name[]; /* names for 16 bit regs */
|
||||
extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
|
||||
extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */
|
||||
extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
|
||||
extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */
|
||||
extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */
|
||||
|
||||
/* External variables used */
|
||||
extern int optimize; /* optimization level */
|
||||
extern int obey_regdecls; /* TRUE if stupid register allocation */
|
||||
extern int optimize; /* optimization level */
|
||||
extern int obey_regdecls; /* TRUE if stupid register allocation */
|
||||
|
||||
/* External functions used */
|
||||
extern struct rtx_def *force_operand ();
|
||||
|
Loading…
Reference in New Issue
Block a user