ia64.c (ia64_register_move_cost): Add mode arguemnt.

* config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt.
        Reorganize.  Handle ADDL like GR, add GR_AND_BR.  Handle TFmode.
        (ia64_secondary_reload_class): Need GR between AR/BR and anything.
        Need GR between FR and not GR_AND_FR.
        * config/ia64/ia64-protos.h (ia64_register_move_cost): Update.
        * config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move
        AR regs before GR regs.
        (REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.
        (PREFERRED_RELOAD_CLASS): Tweak for reordered classes.
        (REGISTER_MOVE_COST): Update.
        (MEMORY_MOVE_COST): Add GR_AND_FR_REGS.

From-SVN: r45125
This commit is contained in:
Richard Henderson 2001-08-23 00:44:03 -07:00 committed by Richard Henderson
parent 26a952a8a4
commit 7109d28642
4 changed files with 118 additions and 60 deletions

View File

@ -1,3 +1,17 @@
2001-08-23 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.c (ia64_register_move_cost): Add mode arguemnt.
Reorganize. Handle ADDL like GR, add GR_AND_BR. Handle TFmode.
(ia64_secondary_reload_class): Need GR between AR/BR and anything.
Need GR between FR and not GR_AND_FR.
* config/ia64/ia64-protos.h (ia64_register_move_cost): Update.
* config/ia64/ia64.h (reg_class): Add GR_AND_BR_REGS, move
AR regs before GR regs.
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update.
(PREFERRED_RELOAD_CLASS): Tweak for reordered classes.
(REGISTER_MOVE_COST): Update.
(MEMORY_MOVE_COST): Add GR_AND_FR_REGS.
2001-08-23 Richard Henderson <rth@redhat.com>
* regclass.c (init_reg_sets_1): Don't assume cost 2 within

View File

@ -119,7 +119,8 @@ extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *));
extern void ia64_encode_section_info PARAMS((tree));
#endif /* TREE_CODE */
extern int ia64_register_move_cost PARAMS((enum reg_class, enum reg_class));
extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class,
enum reg_class));
extern int ia64_epilogue_uses PARAMS((int));
extern void emit_safe_across_calls PARAMS((FILE *));
extern void ia64_init_builtins PARAMS((void));

View File

@ -3551,45 +3551,73 @@ ia64_print_operand (file, x, code)
}
/* Calulate the cost of moving data from a register in class FROM to
one in class TO. */
one in class TO, using MODE. */
int
ia64_register_move_cost (from, to)
ia64_register_move_cost (mode, from, to)
enum machine_mode mode;
enum reg_class from, to;
{
int from_hard, to_hard;
int from_gr, to_gr;
int from_fr, to_fr;
int from_pr, to_pr;
/* ADDL_REGS is the same as GR_REGS for movement purposes. */
if (to == ADDL_REGS)
to = GR_REGS;
if (from == ADDL_REGS)
from = GR_REGS;
from_hard = (from == BR_REGS || from == AR_M_REGS || from == AR_I_REGS);
to_hard = (to == BR_REGS || to == AR_M_REGS || to == AR_I_REGS);
from_gr = (from == GENERAL_REGS);
to_gr = (to == GENERAL_REGS);
from_fr = (from == FR_REGS);
to_fr = (to == FR_REGS);
from_pr = (from == PR_REGS);
to_pr = (to == PR_REGS);
/* All costs are symmetric, so reduce cases by putting the
lower number class as the destination. */
if (from < to)
{
enum reg_class tmp = to;
to = from, from = tmp;
}
if (from_hard && to_hard)
return 8;
else if ((from_hard && !to_gr) || (!from_gr && to_hard))
return 6;
/* Moving from FR<->GR in TFmode must be more expensive than 2,
so that we get secondary memory reloads. Between FR_REGS,
we have to make this at least as expensive as MEMORY_MOVE_COST
to avoid spectacularly poor register class preferencing. */
if (mode == TFmode)
{
if (to != GR_REGS || from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
else
return 3;
}
/* Moving between PR registers takes two insns. */
else if (from_pr && to_pr)
return 3;
/* Moving between PR and anything but GR is impossible. */
else if ((from_pr && !to_gr) || (!from_gr && to_pr))
return 6;
switch (to)
{
case PR_REGS:
/* Moving between PR registers takes two insns. */
if (from == PR_REGS)
return 3;
/* Moving between PR and anything but GR is impossible. */
if (from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
break;
/* ??? Moving from FR<->GR must be more expensive than 2, so that we get
secondary memory reloads for TFmode moves. Unfortunately, we don't
have the mode here, so we can't check that. */
/* Moreover, we have to make this at least as high as MEMORY_MOVE_COST
to avoid spectacularly poor register class preferencing for TFmode. */
else if (from_fr != to_fr)
return 5;
case BR_REGS:
/* Moving between BR and anything but GR is impossible. */
if (from != GR_REGS && from != GR_AND_BR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
break;
case AR_I_REGS:
case AR_M_REGS:
/* Moving between AR and anything but GR is impossible. */
if (from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
break;
case GR_REGS:
case FR_REGS:
case GR_AND_FR_REGS:
case GR_AND_BR_REGS:
case ALL_REGS:
break;
default:
abort ();
}
return 2;
}
@ -3613,17 +3641,21 @@ ia64_secondary_reload_class (class, mode, x)
switch (class)
{
case BR_REGS:
/* ??? This is required because of a bad gcse/cse/global interaction.
We end up with two pseudos with overlapping lifetimes both of which
are equiv to the same constant, and both which need to be in BR_REGS.
This results in a BR_REGS to BR_REGS copy which doesn't exist. To
reproduce, return NO_REGS here, and compile divdi3 in libgcc2.c.
This seems to be a cse bug. cse_basic_block_end changes depending
on the path length, which means the qty_first_reg check in
make_regs_eqv can give different answers at different times. */
/* ??? At some point I'll probably need a reload_indi pattern to handle
this. */
if (BR_REGNO_P (regno))
case AR_M_REGS:
case AR_I_REGS:
/* ??? BR<->BR register copies can happen due to a bad gcse/cse/global
interaction. We end up with two pseudos with overlapping lifetimes
both of which are equiv to the same constant, and both which need
to be in BR_REGS. This seems to be a cse bug. cse_basic_block_end
changes depending on the path length, which means the qty_first_reg
check in make_regs_eqv can give different answers at different times.
At some point I'll probably need a reload_indi pattern to handle
this.
We can also get GR_AND_FR_REGS to BR_REGS/AR_REGS copies, where we
wound up with a FP register from GR_AND_FR_REGS. Extend that to all
non-general registers for good measure. */
if (regno >= 0 && ! GENERAL_REGNO_P (regno))
return GR_REGS;
/* This is needed if a pseudo used as a call_operand gets spilled to a
@ -3633,6 +3665,10 @@ ia64_secondary_reload_class (class, mode, x)
break;
case FR_REGS:
/* Need to go through general regsters to get to other class regs. */
if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
return GR_REGS;
/* This can happen when a paradoxical subreg is an operand to the
muldi3 pattern. */
/* ??? This shouldn't be necessary after instruction scheduling is

View File

@ -907,12 +907,13 @@ enum reg_class
NO_REGS,
PR_REGS,
BR_REGS,
AR_M_REGS,
AR_I_REGS,
ADDL_REGS,
GR_REGS,
FR_REGS,
GR_AND_BR_REGS,
GR_AND_FR_REGS,
AR_M_REGS,
AR_I_REGS,
ALL_REGS,
LIM_REG_CLASSES
};
@ -925,8 +926,9 @@ enum reg_class
/* An initializer containing the names of the register classes as C string
constants. These names are used in writing some of the debugging dumps. */
#define REG_CLASS_NAMES \
{ "NO_REGS", "PR_REGS", "BR_REGS", "ADDL_REGS", "GR_REGS", "FR_REGS", \
"GR_AND_FR_REGS", "AR_M_REGS", "AR_I_REGS", "ALL_REGS" }
{ "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \
"ADDL_REGS", "GR_REGS", "FR_REGS", \
"GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" }
/* An initializer containing the contents of the register classes, as integers
which are bit masks. The Nth integer specifies the contents of class N.
@ -946,6 +948,14 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00FF }, \
/* AR_M_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0C00 }, \
/* AR_I_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x7000 }, \
/* ADDL_REGS. */ \
{ 0x0000000F, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
@ -958,18 +968,14 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x0000 }, \
/* GR_AND_BR_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x03FF }, \
/* GR_AND_FR_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x0300 }, \
/* AR_M_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0C00 }, \
/* AR_I_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x7000 }, \
/* ALL_REGS. */ \
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
@ -1044,7 +1050,8 @@ enum reg_class
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
(CLASS == FR_REGS && GET_CODE (X) == MEM && MEM_VOLATILE_P (X) ? NO_REGS \
: CLASS == FR_REGS && GET_CODE (X) == CONST_DOUBLE ? NO_REGS \
: GET_RTX_CLASS (GET_CODE (X)) != 'o' && CLASS > GR_AND_FR_REGS ? NO_REGS \
: GET_RTX_CLASS (GET_CODE (X)) != 'o' \
&& (CLASS == AR_M_REGS || CLASS == AR_I_REGS) ? NO_REGS \
: CLASS)
/* You should define this macro to indicate to the reload phase that it may
@ -1882,15 +1889,15 @@ do { \
#define ADDRESS_COST(ADDRESS) 0
/* A C expression for the cost of moving data from a register in class FROM to
one in class TO. */
one in class TO, using MODE. */
#define REGISTER_MOVE_COST(MODE, FROM, TO) \
ia64_register_move_cost((FROM), (TO))
#define REGISTER_MOVE_COST ia64_register_move_cost
/* A C expression for the cost of moving data of mode M between a
register and memory. */
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS ? 4 : 10)
((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \
|| (CLASS) == GR_AND_FR_REGS ? 4 : 10)
/* A C expression for the cost of a branch instruction. A value of 1 is the
default; other values are interpreted relative to that. Used by the