Change MEMORY_MOVE_COST defs and uses to be able to take register class into account.
Change MEMORY_MOVE_COST defs and uses to be able to take register class into account. Change mips def to actually do so, others to just ignore extra args. Doc changes too. From-SVN: r18621
This commit is contained in:
parent
8b1616ad12
commit
cbd5b9a22d
|
@ -1,3 +1,22 @@
|
|||
Mon Mar 16 12:12:36 1998 Ken Raeburn <raeburn@cygnus.com>
|
||||
|
||||
* reload.h (MEMORY_MOVE_COST): Define here if not already defined;
|
||||
if HAVE_SECONDARY_RELOADS, factor in copying cost.
|
||||
(memory_move_secondary_cost): Declare.
|
||||
* regclass.c (MEMORY_MOVE_COST): Don't define default here.
|
||||
(memory_move_secondary_cost) [HAVE_SECONDARY_RELOADS]: New
|
||||
function.
|
||||
(regclass, record_reg_classes, copy_cost, record_address_regs):
|
||||
Pass register class and direction of move to MEMORY_MOVE_COST.
|
||||
* reload1.c (MEMORY_MOVE_COST): Don't define default here.
|
||||
(emit_reload_insns, reload_cse_simplify_set): Pass register class
|
||||
and direction of move to MEMORY_MOVE_COST.
|
||||
* 1750a.c, a29k.h, alpha.h, arc.h, arm.h, dsp16xx.h, i386.h,
|
||||
m32r.h, m88k.h, rs6000.h (MEMORY_MOVE_COST): Add extra ignored
|
||||
arguments to definition, even in comments.
|
||||
* mips.h (MEMORY_MOVE_COST): Add extra arguments; add
|
||||
memory_move_secondary_cost result to cpu-specific cost.
|
||||
|
||||
Mon Mar 16 11:16:50 1998 Jim Wilson <wilson@cygnus.com>
|
||||
|
||||
* README.gnat: New file.
|
||||
|
|
|
@ -910,7 +910,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
|
|||
|
||||
#define REGISTER_MOVE_COST(FROM,TO) 2
|
||||
|
||||
#define MEMORY_MOVE_COST(M) 4
|
||||
#define MEMORY_MOVE_COST(M,C,I) 4
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
|
||||
|
|
|
@ -681,7 +681,7 @@ extern struct rtx_def *a29k_get_reloaded_address ();
|
|||
this higher. In addition, we need to keep it more expensive than the
|
||||
most expensive register-register copy. */
|
||||
|
||||
#define MEMORY_MOVE_COST(MODE) 6
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) 6
|
||||
|
||||
/* A C statement (sans semicolon) to update the integer variable COST
|
||||
based on the relationship between INSN that is dependent on
|
||||
|
|
|
@ -789,7 +789,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
|
|||
On the Alpha, bump this up a bit. */
|
||||
|
||||
extern int alpha_memory_latency;
|
||||
#define MEMORY_MOVE_COST(MODE) (2*alpha_memory_latency)
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) (2*alpha_memory_latency)
|
||||
|
||||
/* Provide the cost of a branch. Exact meaning under development. */
|
||||
#define BRANCH_COST 5
|
||||
|
|
|
@ -1102,7 +1102,7 @@ arc_select_cc_mode (OP, X, Y)
|
|||
/* Compute the cost of moving data between registers and memory. */
|
||||
/* Memory is 3 times as expensive as registers.
|
||||
??? Is that the right way to look at it? */
|
||||
#define MEMORY_MOVE_COST(MODE) \
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
|
||||
(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
|
||||
|
||||
/* The cost of a branch insn. */
|
||||
|
|
|
@ -1624,7 +1624,7 @@ extern struct rtx_def *legitimize_pic_address ();
|
|||
return arm_rtx_costs (X, CODE, OUTER_CODE);
|
||||
|
||||
/* Moves to and from memory are quite expensive */
|
||||
#define MEMORY_MOVE_COST(MODE) 10
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) 10
|
||||
|
||||
/* All address computations that can be done are free, but rtx cost returns
|
||||
the same for practically all of them. So we weight the different types
|
||||
|
|
|
@ -1556,7 +1556,7 @@ extern struct dsp16xx_frame_info current_frame_info;
|
|||
|
||||
/* A C expression for the cost of moving data of mode MODE between
|
||||
a register and memory. A value of 2 is the default. */
|
||||
#define MEMORY_MOVE_COST(MODE) \
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN_P) \
|
||||
(GET_MODE_CLASS(MODE) == MODE_INT && MODE == QImode ? 12 \
|
||||
: 16)
|
||||
|
||||
|
|
|
@ -2079,7 +2079,7 @@ while (0)
|
|||
between two registers, you should define this macro to express the
|
||||
relative cost. */
|
||||
|
||||
/* #define MEMORY_MOVE_COST(M) 2 */
|
||||
/* #define MEMORY_MOVE_COST(M,C,I) 2 */
|
||||
|
||||
/* A C expression for the cost of a branch instruction. A value of 1
|
||||
is the default; other values are interpreted relative to that. */
|
||||
|
|
|
@ -1268,7 +1268,7 @@ m32r_select_cc_mode (OP, X, Y)
|
|||
/* Compute the cost of moving data between registers and memory. */
|
||||
/* Memory is 3 times as expensive as registers.
|
||||
??? Is that the right way to look at it? */
|
||||
#define MEMORY_MOVE_COST(MODE) \
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN_P) \
|
||||
(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
|
||||
|
||||
/* The cost of a branch insn. */
|
||||
|
|
|
@ -1690,7 +1690,7 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
|
|||
|
||||
/* A C expressions returning the cost of moving data of MODE from a register
|
||||
to or from memory. This is more costly than between registers. */
|
||||
#define MEMORY_MOVE_COST(MODE) 4
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) 4
|
||||
|
||||
/* Provide the cost of a branch. Exact meaning under development. */
|
||||
#define BRANCH_COST (TARGET_88100 ? 1 : 2)
|
||||
|
|
|
@ -3534,8 +3534,9 @@ while (0)
|
|||
: 12)
|
||||
|
||||
/* ??? Fix this to be right for the R8000. */
|
||||
#define MEMORY_MOVE_COST(MODE) \
|
||||
((mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000) ? 6 : 4)
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,TO_P) \
|
||||
(((mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000) ? 6 : 4) \
|
||||
+ memory_move_secondary_cost ((MODE), (CLASS), (TO_P)))
|
||||
|
||||
/* A C expression for the cost of a branch instruction. A value of
|
||||
1 is the default; other values are interpreted relative to that. */
|
||||
|
|
|
@ -800,7 +800,7 @@ extern int rs6000_debug_arg; /* debug argument handling */
|
|||
|
||||
On the RS/6000, bump this up a bit. */
|
||||
|
||||
#define MEMORY_MOVE_COST(MODE) \
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
|
||||
((GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
&& (rs6000_cpu == PROCESSOR_RIOS1 || rs6000_cpu == PROCESSOR_PPC601) \
|
||||
? 3 : 2) \
|
||||
|
|
|
@ -42,10 +42,6 @@ Boston, MA 02111-1307, USA. */
|
|||
#define REGISTER_MOVE_COST(x, y) 2
|
||||
#endif
|
||||
|
||||
#ifndef MEMORY_MOVE_COST
|
||||
#define MEMORY_MOVE_COST(x) 4
|
||||
#endif
|
||||
|
||||
/* If we have auto-increment or auto-decrement and we can have secondary
|
||||
reloads, we are not allowed to use classes requiring secondary
|
||||
reloads for pseudos auto-incremented since reload can't handle it. */
|
||||
|
@ -431,6 +427,50 @@ init_regs ()
|
|||
init_reg_modes ();
|
||||
}
|
||||
|
||||
#ifdef HAVE_SECONDARY_RELOADS
|
||||
/* Compute extra cost of moving registers to/from memory due to reloads.
|
||||
Only needed if secondary reloads are required for memory moves. */
|
||||
int
|
||||
memory_move_secondary_cost (mode, class, in)
|
||||
enum machine_mode mode;
|
||||
enum reg_class class;
|
||||
int in;
|
||||
{
|
||||
enum reg_class altclass;
|
||||
int partial_cost = 0;
|
||||
rtx mem;
|
||||
|
||||
/* We need a memory reference to feed to SECONDARY... macros. */
|
||||
mem = gen_rtx (MEM, mode, stack_pointer_rtx);
|
||||
|
||||
if (in)
|
||||
altclass = SECONDARY_INPUT_RELOAD_CLASS (class, mode, mem);
|
||||
else
|
||||
altclass = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, mem);
|
||||
if (altclass == NO_REGS)
|
||||
return 0;
|
||||
|
||||
if (in)
|
||||
partial_cost = REGISTER_MOVE_COST (altclass, class);
|
||||
else
|
||||
partial_cost = REGISTER_MOVE_COST (class, altclass);
|
||||
|
||||
if (class == altclass)
|
||||
/* This isn't simply a copy-to-temporary situation. Can't guess
|
||||
what it is, so MEMORY_MOVE_COST really ought not to be calling
|
||||
here in that case.
|
||||
|
||||
I'm tempted to put in an abort here, but returning this will
|
||||
probably only give poor estimates, which is what we would've
|
||||
had before this code anyways. */
|
||||
return partial_cost;
|
||||
|
||||
/* Check if the secondary reload register will also need a
|
||||
secondary reload. */
|
||||
return memory_move_secondary_cost (mode, altclass, in) + partial_cost;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return a machine mode that is legitimate for hard reg REGNO and large
|
||||
enough to save nregs. If we can't find one, return VOIDmode. */
|
||||
|
||||
|
@ -773,7 +813,8 @@ regclass (f, nregs)
|
|||
&& GET_CODE (XEXP (note, 0)) == MEM)
|
||||
{
|
||||
costs[REGNO (SET_DEST (set))].mem_cost
|
||||
-= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)))
|
||||
-= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
|
||||
GENERAL_REGS, 1)
|
||||
* loop_cost);
|
||||
record_address_regs (XEXP (SET_SRC (set), 0),
|
||||
BASE_REG_CLASS, loop_cost * 2);
|
||||
|
@ -1290,7 +1331,8 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
|
|||
a bit cheaper since we won't need an extra insn to
|
||||
load it. */
|
||||
|
||||
pp->mem_cost = MEMORY_MOVE_COST (mode) - allows_mem;
|
||||
pp->mem_cost = (MEMORY_MOVE_COST (mode, classes[i], 1)
|
||||
- allows_mem);
|
||||
|
||||
/* If we have assigned a class to this register in our
|
||||
first pass, add a cost to this alternative corresponding
|
||||
|
@ -1328,7 +1370,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
|
|||
constant that could be placed into memory. */
|
||||
|
||||
else if (CONSTANT_P (op) && allows_mem)
|
||||
alt_cost += MEMORY_MOVE_COST (mode);
|
||||
alt_cost += MEMORY_MOVE_COST (mode, classes[i], 1);
|
||||
else
|
||||
alt_fail = 1;
|
||||
}
|
||||
|
@ -1447,7 +1489,7 @@ copy_cost (x, mode, class, to_p)
|
|||
else (constants). */
|
||||
|
||||
if (GET_CODE (x) == MEM || class == NO_REGS)
|
||||
return MEMORY_MOVE_COST (mode);
|
||||
return MEMORY_MOVE_COST (mode, class, to_p);
|
||||
|
||||
else if (GET_CODE (x) == REG)
|
||||
return move_cost[(int) REGNO_REG_CLASS (REGNO (x))][(int) class];
|
||||
|
@ -1613,7 +1655,7 @@ record_address_regs (x, class, scale)
|
|||
register struct costs *pp = &costs[REGNO (x)];
|
||||
register int i;
|
||||
|
||||
pp->mem_cost += (MEMORY_MOVE_COST (Pmode) * scale) / 2;
|
||||
pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
|
||||
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
pp->cost[i] += (may_move_cost[i][(int) class] * scale) / 2;
|
||||
|
|
11
gcc/reload.h
11
gcc/reload.h
|
@ -34,6 +34,17 @@ Boston, MA 02111-1307, USA. */
|
|||
#define HAVE_SECONDARY_RELOADS
|
||||
#endif
|
||||
|
||||
/* If MEMORY_MOVE_COST isn't defined, give it a default here. */
|
||||
#ifndef MEMORY_MOVE_COST
|
||||
#ifdef HAVE_SECONDARY_RELOADS
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
|
||||
(4 + memory_move_secondary_cost ((MODE), (CLASS), (IN)))
|
||||
#else
|
||||
#define MEMORY_MOVE_COST(MODE,CLASS,IN) 4
|
||||
#endif
|
||||
#endif
|
||||
extern int memory_move_secondary_cost PROTO ((enum machine_mode, enum reg_class, int));
|
||||
|
||||
/* See reload.c and reload1.c for comments on these variables. */
|
||||
|
||||
/* Maximum number of reloads we can need. */
|
||||
|
|
|
@ -76,10 +76,6 @@ Boston, MA 02111-1307, USA. */
|
|||
#ifndef REGISTER_MOVE_COST
|
||||
#define REGISTER_MOVE_COST(x, y) 2
|
||||
#endif
|
||||
|
||||
#ifndef MEMORY_MOVE_COST
|
||||
#define MEMORY_MOVE_COST(x) 4
|
||||
#endif
|
||||
|
||||
/* During reload_as_needed, element N contains a REG rtx for the hard reg
|
||||
into which reg N has been reloaded (perhaps for a previous insn). */
|
||||
|
@ -6141,7 +6137,8 @@ emit_reload_insns (insn)
|
|||
&& ((REGNO_REG_CLASS (regno) != reload_reg_class[j]
|
||||
&& (REGISTER_MOVE_COST (REGNO_REG_CLASS (regno),
|
||||
reload_reg_class[j])
|
||||
>= MEMORY_MOVE_COST (mode)))
|
||||
>= MEMORY_MOVE_COST (mode, REGNO_REG_CLASS (regno),
|
||||
1)))
|
||||
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|
||||
|| (SECONDARY_INPUT_RELOAD_CLASS (reload_reg_class[j],
|
||||
mode, oldequiv)
|
||||
|
@ -8204,13 +8201,15 @@ reload_cse_simplify_set (set, insn)
|
|||
if (side_effects_p (src) || true_regnum (src) >= 0)
|
||||
return 0;
|
||||
|
||||
dclass = REGNO_REG_CLASS (dreg);
|
||||
|
||||
/* If memory loads are cheaper than register copies, don't change
|
||||
them. */
|
||||
if (GET_CODE (src) == MEM && MEMORY_MOVE_COST (GET_MODE (src)) < 2)
|
||||
if (GET_CODE (src) == MEM
|
||||
&& MEMORY_MOVE_COST (GET_MODE (src), dclass, 1) < 2)
|
||||
return 0;
|
||||
|
||||
dest_mode = GET_MODE (SET_DEST (set));
|
||||
dclass = REGNO_REG_CLASS (dreg);
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
{
|
||||
if (i != dreg
|
||||
|
|
20
gcc/tm.texi
20
gcc/tm.texi
|
@ -4512,14 +4512,26 @@ allow reload to verify that the constraints are met. You should do this
|
|||
if the @samp{mov@var{m}} pattern's constraints do not allow such copying.
|
||||
|
||||
@findex MEMORY_MOVE_COST
|
||||
@item MEMORY_MOVE_COST (@var{m})
|
||||
A C expression for the cost of moving data of mode @var{m} between a
|
||||
register and memory. A value of 4 is the default; this cost is relative
|
||||
to those in @code{REGISTER_MOVE_COST}.
|
||||
@item MEMORY_MOVE_COST (@var{mode}, @var{class}, @var{in})
|
||||
A C expression for the cost of moving data of mode @var{mode} between a
|
||||
register of class @var{class} and memory; @var{in} is zero if the value
|
||||
is to be written to memory, non-zero if it is to be read in. If this
|
||||
macro is not defined, the default cost is assumed to be 4, plus any costs
|
||||
that would be incurred copying via a secondary reload register, if
|
||||
needed. This cost is relative to those in @code{REGISTER_MOVE_COST}.
|
||||
|
||||
If moving between registers and memory is more expensive than between
|
||||
two registers, you should define this macro to express the relative cost.
|
||||
|
||||
If a secondary reload register would be required for @var{class}, but the
|
||||
reload mechanism is more complex than copying via an intermediate, this
|
||||
macro should be defined to reflect the actual cost of the move.
|
||||
|
||||
The function @code{memory_move_secondary_cost}, which is defined if
|
||||
secondary reloads are needed, will compute the costs due to copying; you
|
||||
can use this function if you need to take other factors into account as
|
||||
well, or if the default base value of 4 is not correct for your machine.
|
||||
|
||||
@findex BRANCH_COST
|
||||
@item BRANCH_COST
|
||||
A C expression for the cost of a branch instruction. A value of 1 is
|
||||
|
|
Loading…
Reference in New Issue