From: Ken Raeburn Date: Mon, 16 Mar 1998 11:56:25 +0000 (+0000) Subject: Change MEMORY_MOVE_COST defs and uses to be able to take register class into account. X-Git-Tag: prereleases/egcs-1.1-prerelease~2094 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=cbd5b9a22dbba1046ca3968919449339ea7265c6;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 532625af90c5..8f95e8751cdb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +Mon Mar 16 12:12:36 1998 Ken Raeburn + + * 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 * README.gnat: New file. diff --git a/gcc/config/1750a/1750a.h b/gcc/config/1750a/1750a.h index ad6c4be9c2e6..6c5e9e3dfcab 100644 --- a/gcc/config/1750a/1750a.h +++ b/gcc/config/1750a/1750a.h @@ -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. */ diff --git a/gcc/config/a29k/a29k.h b/gcc/config/a29k/a29k.h index 71c270068bef..d65beb4ff281 100644 --- a/gcc/config/a29k/a29k.h +++ b/gcc/config/a29k/a29k.h @@ -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 diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 3e52db740ad1..be3030ea1993 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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 diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 3d7f2b2910f5..c4696ea5542b 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -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. */ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 7c28c646ce11..0adf6dc6eabf 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -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 diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h index 1c0f4dd53085..61e6bf873efd 100644 --- a/gcc/config/dsp16xx/dsp16xx.h +++ b/gcc/config/dsp16xx/dsp16xx.h @@ -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) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 53c08b03b197..b910e77fd654 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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. */ diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 79233e5d5605..d438b4954880 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -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. */ diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h index e35b87e70d77..f0dac24a0dd7 100644 --- a/gcc/config/m88k/m88k.h +++ b/gcc/config/m88k/m88k.h @@ -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) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 92368f65eb4c..4de5f5c66a0e 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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. */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 0982a641fbae..cdc4bdc748d3 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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) \ diff --git a/gcc/regclass.c b/gcc/regclass.c index 3432c79124f0..4cc02080c9fa 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -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; diff --git a/gcc/reload.h b/gcc/reload.h index 14197299608a..d86542fa5053 100644 --- a/gcc/reload.h +++ b/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. */ diff --git a/gcc/reload1.c b/gcc/reload1.c index f416a8704df9..e843ceabe925 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -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 diff --git a/gcc/tm.texi b/gcc/tm.texi index 00311bf792b9..d8fb72407751 100644 --- a/gcc/tm.texi +++ b/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