+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.
#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. */
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
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
/* 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. */
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
/* 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)
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. */
/* 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. */
/* 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)
: 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. */
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) \
#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. */
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. */
&& 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);
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
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;
}
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];
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;
#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. */
#ifndef REGISTER_MOVE_COST
#define REGISTER_MOVE_COST(x, y) 2
#endif
-
-#ifndef MEMORY_MOVE_COST
-#define MEMORY_MOVE_COST(x) 4
-#endif
\f
/* 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). */
&& ((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)
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
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