mirror of git://gcc.gnu.org/git/gcc.git
Makefile.in (cse.o): Depend on TARGET_H.
* Makefile.in (cse.o): Depend on TARGET_H. * cse.c (rtx_cost): Use targetm.rtx_costs. * system.h (CONST_COSTS RTX_COSTS DEFAULT_RTX_COSTS): Poison. * doc/tm.texi: Update. * target.h (targetm.rtx_costs): New. * target-def.h (TARGET_RTX_COSTS): New. * hooks.c (hook_bool_rtx_int_int_intp_false): New. * hooks.h: Update. * config/alpha/alpha.c (alpha_rtx_cost_data): New. (alpha_rtx_costs, TARGET_RTX_COSTS): New. * config/alpha/alpha.h (PROCESSOR_MAX): New. (CONST_COSTS, RTX_COSTS): Remove. * config/arc/arc.c, config/arc/arc.h, config/c4x/c4x.c, config/c4x/c4x.h, config/cris/cris.c, config/cris/cris.h, config/d30v/d30v.c, config/d30v/d30v.h, config/dsp16xx/dsp16xx.c, config/dsp16xx/dsp16xx.h, config/frv/frv.c, config/frv/frv.h, config/h8300/h8300.c, config/h8300/h8300.h, config/i370/i370.c, config/i370/i370.h, config/i386/i386.c, config/i386/i386.h, config/i960/i960.c, config/i960/i960.h, config/ia64/ia64.c, config/ia64/ia64.h, config/m32r/m32r.c, config/m32r/m32r.h, config/m68k/m68k.c, config/m68k/m68k.h, config/m88k/m88k.c, config/m88k/m88k.h, config/mcore/mcore.c, config/mcore/mcore.h, config/mips/mips.c, config/mips/mips.h, config/mn10200/mn10200.c, config/mn10200/mn10200.h, config/mn10300/mn10300.c, config/mn10300/mn10300.h, config/ns32k/ns32k.c, config/ns32k/ns32k.h, config/pa/pa.c, config/pa/pa.h, config/pdp11/pdp11.c, config/pdp11/pdp11.h, config/romp/romp.c, config/romp/romp.h, config/rs6000/rs6000.c, config/rs6000/rs6000.h, config/s390/s390.c, config/s390/s390.h, config/sh/sh.c, config/sh/sh.h, config/stormy16/stormy16.c, config/stormy16/stormy16.h, config/v850/v850.c, config/v850/v850.h, config/xtensa/xtensa.c, config/xtensa/xtensa.h (CONST_COSTS, RTX_COSTS): Move code ... (foo_rtx_costs, TARGET_RTX_COSTS): ... here. * config/arm/arm.c (arm_rtx_costs_1): Rename from arm_rtx_costs. (arm_rtx_costs, TARGET_RTX_COSTS): New. * config/arm/arm-protos.h: Update. * config/arm/arm.h (DEFAULT_RTX_COSTS): Remove. * config/avr/avr.h (CONST_COSTS): Move code ... * config/avr/avr.c (avr_rtx_costs): ... here. (default_rtx_costs): Make static. * config/avr/avr-protos.h: Update. * config/h8300/h8300.c (const_costs): Make static. (h8300_and_costs, h8300_shift_costs): Likewise. * config/h8300/h8300-protos.h: Update. * config/ip2k/ip2k.h (DEFAULT_RTX_COSTS): Remove. (CONST_COSTS): Move code ... * config/ip2k/ip2k.c (ip2k_rtx_costs): ... here. Rename from default_rtx_costs; update for signature change. * config/ip2k/ip2k-protos.h: Update. * config/m68hc11/m68hc11.h (RTX_COSTS): Remove. (CONST_COSTS): Move code ... * config/m68hc11/m68hc11.c (m68hc11_rtx_costs): ... here. (TARGET_RTX_COSTS): New. (m68hc11_rtx_costs_1): Rename from m68hc11_rtx_costs; make static. * config/m68hc11/m68hc11-protos.h: Update. * config/m68k/m68k.c (const_int_cost): Make static. * config/m68k/m68k-protos.h: Update. * config/mcore/mcore.c (mcore_const_costs): Make static. (mcore_and_cost, mcore_ior_cost): Likewise. * config/mcore/mcore-protos.h: Update. * config/mmix/mmix.c (mmix_rtx_costs, TARGET_RTX_COSTS): New. (mmix_rtx_cost_recalculated): Remove. * config/mmix/mmix.h (DEFAULT_RTX_COSTS): Remove. * config/mmix/mmix-protos.h: Update. * config/sh/sh.c (shiftcosts): Make static. (addsubcosts, andcosts, multcosts): Likewise. * config/sh/sh-protos.h: Update. * config/sparc/sparc.c (TARGET_RTX_COSTS): New. (sparc_rtx_costs): Make static; update for change in signature. * config/sparc/sparc.h (RTX_COSTS_CASES, RTX_COSTS): Remove. * config/sparc/sparc-protos.h: Update. * config/v850/v850.c (const_costs): Make static. * config/v850/v850-protos.h: Update. * config/vax/vax.h (RTX_COSTS): Remove. (CONST_COSTS): Move code ... * config/vax/vax.c (vax_rtx_costs_1): ... here; rename from vax_rtx_cost. (vax_rtx_costs, TARGET_RTX_COSTS): New. From-SVN: r61954
This commit is contained in:
parent
5ca9898002
commit
3c50106f69
|
@ -1,3 +1,100 @@
|
|||
2003-01-27 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* Makefile.in (cse.o): Depend on TARGET_H.
|
||||
* cse.c (rtx_cost): Use targetm.rtx_costs.
|
||||
* system.h (CONST_COSTS RTX_COSTS DEFAULT_RTX_COSTS): Poison.
|
||||
* doc/tm.texi: Update.
|
||||
|
||||
* target.h (targetm.rtx_costs): New.
|
||||
* target-def.h (TARGET_RTX_COSTS): New.
|
||||
* hooks.c (hook_bool_rtx_int_int_intp_false): New.
|
||||
* hooks.h: Update.
|
||||
|
||||
* config/alpha/alpha.c (alpha_rtx_cost_data): New.
|
||||
(alpha_rtx_costs, TARGET_RTX_COSTS): New.
|
||||
* config/alpha/alpha.h (PROCESSOR_MAX): New.
|
||||
(CONST_COSTS, RTX_COSTS): Remove.
|
||||
|
||||
* config/arc/arc.c, config/arc/arc.h, config/c4x/c4x.c,
|
||||
config/c4x/c4x.h, config/cris/cris.c, config/cris/cris.h,
|
||||
config/d30v/d30v.c, config/d30v/d30v.h, config/dsp16xx/dsp16xx.c,
|
||||
config/dsp16xx/dsp16xx.h, config/frv/frv.c, config/frv/frv.h,
|
||||
config/h8300/h8300.c, config/h8300/h8300.h, config/i370/i370.c,
|
||||
config/i370/i370.h, config/i386/i386.c, config/i386/i386.h,
|
||||
config/i960/i960.c, config/i960/i960.h, config/ia64/ia64.c,
|
||||
config/ia64/ia64.h, config/m32r/m32r.c, config/m32r/m32r.h,
|
||||
config/m68k/m68k.c, config/m68k/m68k.h, config/m88k/m88k.c,
|
||||
config/m88k/m88k.h, config/mcore/mcore.c, config/mcore/mcore.h,
|
||||
config/mips/mips.c, config/mips/mips.h, config/mn10200/mn10200.c,
|
||||
config/mn10200/mn10200.h, config/mn10300/mn10300.c,
|
||||
config/mn10300/mn10300.h, config/ns32k/ns32k.c, config/ns32k/ns32k.h,
|
||||
config/pa/pa.c, config/pa/pa.h, config/pdp11/pdp11.c,
|
||||
config/pdp11/pdp11.h, config/romp/romp.c, config/romp/romp.h,
|
||||
config/rs6000/rs6000.c, config/rs6000/rs6000.h, config/s390/s390.c,
|
||||
config/s390/s390.h, config/sh/sh.c, config/sh/sh.h,
|
||||
config/stormy16/stormy16.c, config/stormy16/stormy16.h,
|
||||
config/v850/v850.c, config/v850/v850.h,
|
||||
config/xtensa/xtensa.c, config/xtensa/xtensa.h
|
||||
(CONST_COSTS, RTX_COSTS): Move code ...
|
||||
(foo_rtx_costs, TARGET_RTX_COSTS): ... here.
|
||||
|
||||
* config/arm/arm.c (arm_rtx_costs_1): Rename from arm_rtx_costs.
|
||||
(arm_rtx_costs, TARGET_RTX_COSTS): New.
|
||||
* config/arm/arm-protos.h: Update.
|
||||
* config/arm/arm.h (DEFAULT_RTX_COSTS): Remove.
|
||||
|
||||
* config/avr/avr.h (CONST_COSTS): Move code ...
|
||||
* config/avr/avr.c (avr_rtx_costs): ... here.
|
||||
(default_rtx_costs): Make static.
|
||||
* config/avr/avr-protos.h: Update.
|
||||
|
||||
* config/h8300/h8300.c (const_costs): Make static.
|
||||
(h8300_and_costs, h8300_shift_costs): Likewise.
|
||||
* config/h8300/h8300-protos.h: Update.
|
||||
|
||||
* config/ip2k/ip2k.h (DEFAULT_RTX_COSTS): Remove.
|
||||
(CONST_COSTS): Move code ...
|
||||
* config/ip2k/ip2k.c (ip2k_rtx_costs): ... here. Rename from
|
||||
default_rtx_costs; update for signature change.
|
||||
* config/ip2k/ip2k-protos.h: Update.
|
||||
|
||||
* config/m68hc11/m68hc11.h (RTX_COSTS): Remove.
|
||||
(CONST_COSTS): Move code ...
|
||||
* config/m68hc11/m68hc11.c (m68hc11_rtx_costs): ... here.
|
||||
(TARGET_RTX_COSTS): New.
|
||||
(m68hc11_rtx_costs_1): Rename from m68hc11_rtx_costs; make static.
|
||||
* config/m68hc11/m68hc11-protos.h: Update.
|
||||
|
||||
* config/m68k/m68k.c (const_int_cost): Make static.
|
||||
* config/m68k/m68k-protos.h: Update.
|
||||
|
||||
* config/mcore/mcore.c (mcore_const_costs): Make static.
|
||||
(mcore_and_cost, mcore_ior_cost): Likewise.
|
||||
* config/mcore/mcore-protos.h: Update.
|
||||
|
||||
* config/mmix/mmix.c (mmix_rtx_costs, TARGET_RTX_COSTS): New.
|
||||
(mmix_rtx_cost_recalculated): Remove.
|
||||
* config/mmix/mmix.h (DEFAULT_RTX_COSTS): Remove.
|
||||
* config/mmix/mmix-protos.h: Update.
|
||||
|
||||
* config/sh/sh.c (shiftcosts): Make static.
|
||||
(addsubcosts, andcosts, multcosts): Likewise.
|
||||
* config/sh/sh-protos.h: Update.
|
||||
|
||||
* config/sparc/sparc.c (TARGET_RTX_COSTS): New.
|
||||
(sparc_rtx_costs): Make static; update for change in signature.
|
||||
* config/sparc/sparc.h (RTX_COSTS_CASES, RTX_COSTS): Remove.
|
||||
* config/sparc/sparc-protos.h: Update.
|
||||
|
||||
* config/v850/v850.c (const_costs): Make static.
|
||||
* config/v850/v850-protos.h: Update.
|
||||
|
||||
* config/vax/vax.h (RTX_COSTS): Remove.
|
||||
(CONST_COSTS): Move code ...
|
||||
* config/vax/vax.c (vax_rtx_costs_1): ... here; rename
|
||||
from vax_rtx_cost.
|
||||
(vax_rtx_costs, TARGET_RTX_COSTS): New.
|
||||
|
||||
2003-01-27 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Remove. Really.
|
||||
|
|
|
@ -1543,8 +1543,9 @@ cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_
|
|||
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
|
||||
output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
|
||||
cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
|
||||
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h \
|
||||
function.h $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) except.h
|
||||
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
|
||||
output.h function.h $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \
|
||||
except.h $(TARGET_H)
|
||||
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
|
||||
hard-reg-set.h flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) \
|
||||
$(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h
|
||||
|
|
|
@ -123,6 +123,54 @@ extern GTY(()) int alpha_this_gpdisp_sequence_number;
|
|||
int alpha_this_literal_sequence_number;
|
||||
int alpha_this_gpdisp_sequence_number;
|
||||
|
||||
/* Costs of various operations on the different architectures. */
|
||||
|
||||
struct alpha_rtx_cost_data
|
||||
{
|
||||
unsigned char fp_add;
|
||||
unsigned char fp_mult;
|
||||
unsigned char fp_div_sf;
|
||||
unsigned char fp_div_df;
|
||||
unsigned char int_mult_si;
|
||||
unsigned char int_mult_di;
|
||||
unsigned char int_shift;
|
||||
unsigned char int_cmov;
|
||||
};
|
||||
|
||||
static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] =
|
||||
{
|
||||
{ /* EV4 */
|
||||
COSTS_N_INSNS (6), /* fp_add */
|
||||
COSTS_N_INSNS (6), /* fp_mult */
|
||||
COSTS_N_INSNS (34), /* fp_div_sf */
|
||||
COSTS_N_INSNS (63), /* fp_div_df */
|
||||
COSTS_N_INSNS (23), /* int_mult_si */
|
||||
COSTS_N_INSNS (23), /* int_mult_di */
|
||||
COSTS_N_INSNS (2), /* int_shift */
|
||||
COSTS_N_INSNS (2), /* int_cmov */
|
||||
},
|
||||
{ /* EV5 */
|
||||
COSTS_N_INSNS (4), /* fp_add */
|
||||
COSTS_N_INSNS (4), /* fp_mult */
|
||||
COSTS_N_INSNS (15), /* fp_div_sf */
|
||||
COSTS_N_INSNS (22), /* fp_div_df */
|
||||
COSTS_N_INSNS (8), /* int_mult_si */
|
||||
COSTS_N_INSNS (12), /* int_mult_di */
|
||||
COSTS_N_INSNS (1) + 1, /* int_shift */
|
||||
COSTS_N_INSNS (1), /* int_cmov */
|
||||
},
|
||||
{ /* EV6 */
|
||||
COSTS_N_INSNS (4), /* fp_add */
|
||||
COSTS_N_INSNS (4), /* fp_mult */
|
||||
COSTS_N_INSNS (12), /* fp_div_sf */
|
||||
COSTS_N_INSNS (15), /* fp_div_df */
|
||||
COSTS_N_INSNS (7), /* int_mult_si */
|
||||
COSTS_N_INSNS (7), /* int_mult_di */
|
||||
COSTS_N_INSNS (1), /* int_shift */
|
||||
COSTS_N_INSNS (2), /* int_cmov */
|
||||
},
|
||||
};
|
||||
|
||||
/* Declarations of static functions. */
|
||||
static bool alpha_function_ok_for_sibcall
|
||||
PARAMS ((tree, tree));
|
||||
|
@ -144,6 +192,8 @@ static int some_small_symbolic_operand_1
|
|||
PARAMS ((rtx *, void *));
|
||||
static int split_small_symbolic_operand_1
|
||||
PARAMS ((rtx *, void *));
|
||||
static bool alpha_rtx_costs
|
||||
PARAMS ((rtx, int, int, int *));
|
||||
static void alpha_set_memflags_1
|
||||
PARAMS ((rtx, int, int, int));
|
||||
static rtx alpha_emit_set_const_1
|
||||
|
@ -319,6 +369,9 @@ static void unicosmk_unique_section PARAMS ((tree, int));
|
|||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
|
||||
#endif
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS alpha_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Parse target option strings. */
|
||||
|
@ -2474,6 +2527,150 @@ alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
|
|||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
alpha_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
bool float_mode_p = FLOAT_MODE_P (mode);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
/* If this is an 8-bit constant, return zero since it can be used
|
||||
nearly anywhere with no cost. If it is a valid operand for an
|
||||
ADD or AND, likewise return 0 if we know it will be used in that
|
||||
context. Otherwise, return 2 since it might be used there later.
|
||||
All other constants take at least two insns. */
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) >= 0 && INTVAL (x) < 256)
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (x == CONST0_RTX (mode))
|
||||
*total = 0;
|
||||
else if ((outer_code == PLUS && add_operand (x, VOIDmode))
|
||||
|| (outer_code == AND && and_operand (x, VOIDmode)))
|
||||
*total = 0;
|
||||
else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode))
|
||||
*total = 2;
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode))
|
||||
*total = COSTS_N_INSNS (outer_code != MEM);
|
||||
else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode))
|
||||
*total = COSTS_N_INSNS (1 + (outer_code != MEM));
|
||||
else if (tls_symbolic_operand_type (x))
|
||||
/* Estimate of cost for call_pal rduniq. */
|
||||
*total = COSTS_N_INSNS (15);
|
||||
else
|
||||
/* Otherwise we do a load from the GOT. */
|
||||
*total = COSTS_N_INSNS (alpha_memory_latency);
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
if (float_mode_p)
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_add;
|
||||
else if (GET_CODE (XEXP (x, 0)) == MULT
|
||||
&& const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
|
||||
{
|
||||
*total = (rtx_cost (XEXP (XEXP (x, 0), 0), outer_code)
|
||||
+ rtx_cost (XEXP (x, 1), outer_code) + 2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case MULT:
|
||||
if (float_mode_p)
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_mult;
|
||||
else if (mode == DImode)
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].int_mult_di;
|
||||
else
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].int_mult_si;
|
||||
return false;
|
||||
|
||||
case ASHIFT:
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (x, 1)) <= 3)
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].int_shift;
|
||||
return false;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
if (float_mode_p)
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_add;
|
||||
else
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].int_cmov;
|
||||
return false;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
if (!float_mode_p)
|
||||
*total = COSTS_N_INSNS (70); /* ??? */
|
||||
else if (mode == SFmode)
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_div_sf;
|
||||
else
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_div_df;
|
||||
return false;
|
||||
|
||||
case MEM:
|
||||
*total = COSTS_N_INSNS (alpha_memory_latency);
|
||||
return true;
|
||||
|
||||
case NEG:
|
||||
if (! float_mode_p)
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case ABS:
|
||||
if (! float_mode_p)
|
||||
{
|
||||
*total = COSTS_N_INSNS (1) + alpha_rtx_cost_data[alpha_cpu].int_cmov;
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case FLOAT:
|
||||
case UNSIGNED_FLOAT:
|
||||
case FIX:
|
||||
case UNSIGNED_FIX:
|
||||
case FLOAT_EXTEND:
|
||||
case FLOAT_TRUNCATE:
|
||||
*total = alpha_rtx_cost_data[alpha_cpu].fp_add;
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* REF is an alignable memory location. Place an aligned SImode
|
||||
reference into *PALIGNED_MEM and the number of bits to shift into
|
||||
*PBITNUM. SCRATCH is a free register for use in reloading out
|
||||
|
|
|
@ -112,9 +112,12 @@ Boston, MA 02111-1307, USA. */
|
|||
mirrors this list, so changes to alpha.md must be made at the same time. */
|
||||
|
||||
enum processor_type
|
||||
{PROCESSOR_EV4, /* 2106[46]{a,} */
|
||||
{
|
||||
PROCESSOR_EV4, /* 2106[46]{a,} */
|
||||
PROCESSOR_EV5, /* 21164{a,pc,} */
|
||||
PROCESSOR_EV6}; /* 21264 */
|
||||
PROCESSOR_EV6, /* 21264 */
|
||||
PROCESSOR_MAX
|
||||
};
|
||||
|
||||
extern enum processor_type alpha_cpu;
|
||||
|
||||
|
@ -1543,162 +1546,6 @@ do { \
|
|||
/* Define this to be nonzero if shift instructions ignore all but the low-order
|
||||
few bits. */
|
||||
#define SHIFT_COUNT_TRUNCATED 1
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch.
|
||||
|
||||
If this is an 8-bit constant, return zero since it can be used
|
||||
nearly anywhere with no cost. If it is a valid operand for an
|
||||
ADD or AND, likewise return 0 if we know it will be used in that
|
||||
context. Otherwise, return 2 since it might be used there later.
|
||||
All other constants take at least two insns. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (RTX) >= 0 && INTVAL (RTX) < 256) \
|
||||
return 0; \
|
||||
case CONST_DOUBLE: \
|
||||
if ((RTX) == CONST0_RTX (GET_MODE (RTX))) \
|
||||
return 0; \
|
||||
else if (((OUTER_CODE) == PLUS && add_operand (RTX, VOIDmode)) \
|
||||
|| ((OUTER_CODE) == AND && and_operand (RTX, VOIDmode))) \
|
||||
return 0; \
|
||||
else if (add_operand (RTX, VOIDmode) || and_operand (RTX, VOIDmode)) \
|
||||
return 2; \
|
||||
else \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case CONST: \
|
||||
case SYMBOL_REF: \
|
||||
case LABEL_REF: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case PROCESSOR_EV5: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
default: abort(); \
|
||||
}
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case PLUS: case MINUS: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
return COSTS_N_INSNS (6); \
|
||||
case PROCESSOR_EV5: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (4); \
|
||||
default: abort(); \
|
||||
} \
|
||||
else if (GET_CODE (XEXP (X, 0)) == MULT \
|
||||
&& const48_operand (XEXP (XEXP (X, 0), 1), VOIDmode)) \
|
||||
return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \
|
||||
+ rtx_cost (XEXP (X, 1), OUTER_CODE)); \
|
||||
break; \
|
||||
case MULT: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
return COSTS_N_INSNS (6); \
|
||||
return COSTS_N_INSNS (23); \
|
||||
case PROCESSOR_EV5: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
else if (GET_MODE (X) == DImode) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
else \
|
||||
return COSTS_N_INSNS (8); \
|
||||
case PROCESSOR_EV6: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
else \
|
||||
return COSTS_N_INSNS (7); \
|
||||
default: abort(); \
|
||||
} \
|
||||
case ASHIFT: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& INTVAL (XEXP (X, 1)) <= 3) \
|
||||
break; \
|
||||
/* ... fall through ... */ \
|
||||
case ASHIFTRT: case LSHIFTRT: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case PROCESSOR_EV5: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
default: abort(); \
|
||||
} \
|
||||
case IF_THEN_ELSE: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case PROCESSOR_EV5: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
default: abort(); \
|
||||
} \
|
||||
case DIV: case UDIV: case MOD: case UMOD: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
if (GET_MODE (X) == SFmode) \
|
||||
return COSTS_N_INSNS (34); \
|
||||
else if (GET_MODE (X) == DFmode) \
|
||||
return COSTS_N_INSNS (63); \
|
||||
else \
|
||||
return COSTS_N_INSNS (70); \
|
||||
case PROCESSOR_EV5: \
|
||||
if (GET_MODE (X) == SFmode) \
|
||||
return COSTS_N_INSNS (15); \
|
||||
else if (GET_MODE (X) == DFmode) \
|
||||
return COSTS_N_INSNS (22); \
|
||||
else \
|
||||
return COSTS_N_INSNS (70); /* ??? */ \
|
||||
case PROCESSOR_EV6: \
|
||||
if (GET_MODE (X) == SFmode) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
else if (GET_MODE (X) == DFmode) \
|
||||
return COSTS_N_INSNS (15); \
|
||||
else \
|
||||
return COSTS_N_INSNS (70); /* ??? */ \
|
||||
default: abort(); \
|
||||
} \
|
||||
case MEM: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case PROCESSOR_EV5: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
default: abort(); \
|
||||
} \
|
||||
case NEG: case ABS: \
|
||||
if (! FLOAT_MODE_P (GET_MODE (X))) \
|
||||
break; \
|
||||
/* ... fall through ... */ \
|
||||
case FLOAT: case UNSIGNED_FLOAT: case FIX: case UNSIGNED_FIX: \
|
||||
case FLOAT_EXTEND: case FLOAT_TRUNCATE: \
|
||||
switch (alpha_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_EV4: \
|
||||
return COSTS_N_INSNS (6); \
|
||||
case PROCESSOR_EV5: \
|
||||
case PROCESSOR_EV6: \
|
||||
return COSTS_N_INSNS (4); \
|
||||
default: abort(); \
|
||||
}
|
||||
|
||||
/* Control the assembler format that we output. */
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ static void arc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
static void arc_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void arc_encode_section_info PARAMS ((tree, int));
|
||||
static void arc_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
||||
static bool arc_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
|
@ -114,7 +115,10 @@ static void arc_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
|||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
|
||||
#undef TARGET_ASM_INTERNAL_LABEL
|
||||
#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
|
||||
#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS arc_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -2376,3 +2380,61 @@ arc_internal_label (stream, prefix, labelno)
|
|||
arc_ccfsm_at_label (prefix, labelno);
|
||||
default_internal_label (stream, prefix, labelno);
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
arc_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code;
|
||||
int outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* Small integers are as cheap as registers. 4 byte values can
|
||||
be fetched as immediate constants - let's give that the cost
|
||||
of an extra insn. */
|
||||
case CONST_INT:
|
||||
if (SMALL_INT (INTVAL (x)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
rtx high, low;
|
||||
split_double (x, &high, &low);
|
||||
*total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
|
||||
+ !SMALL_INT (INTVAL (low)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Encourage synth_mult to find a synthetic multiply when reasonable.
|
||||
If we need more than 12 insns to do a multiply, then go out-of-line,
|
||||
since the call overhead will be < 10% of the cost of the multiply. */
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
if (TARGET_SHIFTER)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
*total = COSTS_N_INSNS (16);
|
||||
else
|
||||
*total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -995,34 +995,6 @@ arc_select_cc_mode (OP, X, Y)
|
|||
|
||||
/* Costs. */
|
||||
|
||||
/* An insn is define to cost 4 "units", and we work from there.
|
||||
COSTS_N_INSNS (N) is defined as (N) * 4 - 2 so that seems reasonable.
|
||||
Some values are supposed to be defined relative to each other and thus
|
||||
aren't necessarily related to COSTS_N_INSNS. */
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
/* Small integers are as cheap as registers. 4 byte values can be fetched
|
||||
as immediate constants - let's give that the cost of an extra insn. */
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT : \
|
||||
if (SMALL_INT (INTVAL (X))) \
|
||||
return 0; \
|
||||
/* fall through */ \
|
||||
case CONST : \
|
||||
case LABEL_REF : \
|
||||
case SYMBOL_REF : \
|
||||
return 4; \
|
||||
case CONST_DOUBLE : \
|
||||
{ \
|
||||
rtx high, low; \
|
||||
split_double (X, &high, &low); \
|
||||
return 4 * (!SMALL_INT (INTVAL (high)) \
|
||||
+ !SMALL_INT (INTVAL (low))); \
|
||||
}
|
||||
|
||||
/* Compute the cost of an address. */
|
||||
#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : arc_address_cost (ADDR))
|
||||
|
||||
|
@ -1041,22 +1013,6 @@ arc_select_cc_mode (OP, X, Y)
|
|||
expensive than reg->reg moves. */
|
||||
#define BRANCH_COST 2
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. The purpose for the cost of MULT is to encourage
|
||||
`synth_mult' to find a synthetic multiply when reasonable.
|
||||
|
||||
If we need more than 12 insns to do a multiply, then go out-of-line,
|
||||
since the call overhead will be < 10% of the cost of the multiply. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case ASHIFT : \
|
||||
case ASHIFTRT : \
|
||||
case LSHIFTRT : \
|
||||
if (TARGET_SHIFTER) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
if (GET_CODE (XEXP ((X), 1)) != CONST_INT) \
|
||||
return COSTS_N_INSNS (16); \
|
||||
return COSTS_N_INSNS (INTVAL (XEXP ((X), 1)));
|
||||
|
||||
/* Nonzero if access to memory by bytes is slow and undesirable.
|
||||
For RISC chips, it means that access to memory by bytes is no
|
||||
better than access by words when possible, so grab a whole word
|
||||
|
|
|
@ -57,7 +57,6 @@ extern int thumb_legitimate_address_p PARAMS ((enum machine_mode, rtx,
|
|||
int));
|
||||
extern int thumb_legitimate_offset_p PARAMS ((enum machine_mode,
|
||||
HOST_WIDE_INT));
|
||||
extern int arm_rtx_costs PARAMS ((rtx, RTX_CODE, RTX_CODE));
|
||||
extern int const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
||||
extern int neg_const_double_rtx_ok_for_fpu PARAMS ((rtx));
|
||||
|
||||
|
|
|
@ -140,6 +140,9 @@ static void arm_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
|||
static void arm_output_mi_thunk PARAMS ((FILE *, tree,
|
||||
HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree));
|
||||
static int arm_rtx_costs_1 PARAMS ((rtx, enum rtx_code,
|
||||
enum rtx_code));
|
||||
static bool arm_rtx_costs PARAMS ((rtx, int, int, int*));
|
||||
|
||||
#undef Hint
|
||||
#undef Mmode
|
||||
|
@ -213,6 +216,9 @@ static void arm_output_mi_thunk PARAMS ((FILE *, tree,
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS arm_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Obstack for minipool constant handling. */
|
||||
|
@ -2909,8 +2915,8 @@ thumb_legitimate_offset_p (mode, val)
|
|||
#define COSTS_N_INSNS(N) ((N) * 4 - 2)
|
||||
#endif
|
||||
|
||||
int
|
||||
arm_rtx_costs (x, code, outer)
|
||||
static inline int
|
||||
arm_rtx_costs_1 (x, code, outer)
|
||||
rtx x;
|
||||
enum rtx_code code;
|
||||
enum rtx_code outer;
|
||||
|
@ -3294,6 +3300,16 @@ arm_rtx_costs (x, code, outer)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
arm_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
*total = arm_rtx_costs_1 (x, code, outer_code);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
arm_adjust_cost (insn, link, dep, cost)
|
||||
rtx insn;
|
||||
|
|
|
@ -2138,9 +2138,6 @@ typedef struct
|
|||
( (X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
|
||||
|| (X) == arg_pointer_rtx)
|
||||
|
||||
#define DEFAULT_RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
return arm_rtx_costs (X, CODE, OUTER_CODE);
|
||||
|
||||
/* Moves to and from memory are quite expensive */
|
||||
#define MEMORY_MOVE_COST(M, CLASS, IN) \
|
||||
(TARGET_ARM ? 10 : \
|
||||
|
|
|
@ -114,8 +114,6 @@ extern const char * output_reload_inhi PARAMS ((rtx insn, rtx *operands,
|
|||
int *len));
|
||||
extern const char * output_reload_insisf PARAMS ((rtx insn, rtx *operands,
|
||||
int *len));
|
||||
extern int default_rtx_costs PARAMS ((rtx X, RTX_CODE code,
|
||||
RTX_CODE outer_code));
|
||||
extern enum reg_class secondary_input_reload_class PARAMS ((enum reg_class,
|
||||
enum machine_mode,
|
||||
rtx));
|
||||
|
|
|
@ -71,6 +71,8 @@ static unsigned int avr_section_type_flags PARAMS ((tree, const char *, int));
|
|||
|
||||
static void avr_asm_out_ctor PARAMS ((rtx, int));
|
||||
static void avr_asm_out_dtor PARAMS ((rtx, int));
|
||||
static int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
static bool avr_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Allocate registers from r25 to r8 for parameters for function calls */
|
||||
#define FIRST_CUM_REG 26
|
||||
|
@ -227,6 +229,8 @@ int avr_case_values_threshold = 30000;
|
|||
#define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
|
||||
#undef TARGET_SECTION_TYPE_FLAGS
|
||||
#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS avr_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -4978,7 +4982,7 @@ order_regs_for_local_alloc ()
|
|||
/* Calculate the cost of X code of the expression in which it is contained,
|
||||
found in OUTER_CODE */
|
||||
|
||||
int
|
||||
static int
|
||||
default_rtx_costs (X, code, outer_code)
|
||||
rtx X;
|
||||
enum rtx_code code;
|
||||
|
@ -5037,6 +5041,56 @@ default_rtx_costs (X, code, outer_code)
|
|||
return cost;
|
||||
}
|
||||
|
||||
static bool
|
||||
avr_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
int cst;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (outer_code == PLUS
|
||||
|| outer_code == IOR
|
||||
|| outer_code == AND
|
||||
|| outer_code == MINUS
|
||||
|| outer_code == SET
|
||||
|| INTVAL (x) == 0)
|
||||
{
|
||||
*total = 2;
|
||||
return true;
|
||||
}
|
||||
if (outer_code == COMPARE
|
||||
&& INTVAL (x) >= 0
|
||||
&& INTVAL (x) <= 255)
|
||||
{
|
||||
*total = 2;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST_DOUBLE:
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
default:
|
||||
cst = default_rtx_costs (x, code, outer_code);
|
||||
if (cst > 0)
|
||||
{
|
||||
*total = cst;
|
||||
return true;
|
||||
}
|
||||
else if (cst < 0)
|
||||
*total += -cst;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the cost of a memory address */
|
||||
|
||||
int
|
||||
|
|
|
@ -1521,59 +1521,6 @@ do { \
|
|||
is a suitable definition for this macro on machines where anything
|
||||
`CONSTANT_P' is valid. */
|
||||
|
||||
#define CONST_COSTS(x,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (OUTER_CODE == PLUS \
|
||||
|| OUTER_CODE == IOR \
|
||||
|| OUTER_CODE == AND \
|
||||
|| OUTER_CODE == MINUS \
|
||||
|| OUTER_CODE == SET \
|
||||
|| INTVAL (x) == 0) \
|
||||
return 2; \
|
||||
if (OUTER_CODE == COMPARE \
|
||||
&& INTVAL (x) >= 0 \
|
||||
&& INTVAL (x) <= 255) \
|
||||
return 2; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 4; \
|
||||
case CONST_DOUBLE: \
|
||||
return 4;
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain `case' labels for
|
||||
expression codes `const_int', `const', `symbol_ref', `label_ref'
|
||||
and `const_double'. Each case must ultimately reach a `return'
|
||||
statement to return the relative cost of the use of that kind of
|
||||
constant value in an expression. The cost may depend on the
|
||||
precise value of the constant, which is available for examination
|
||||
in X, and the rtx code of the expression in which it is contained,
|
||||
found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
|
||||
#define DEFAULT_RTX_COSTS(x, code, outer_code) \
|
||||
{ \
|
||||
int cst = default_rtx_costs (x, code, outer_code); \
|
||||
if (cst>0) \
|
||||
return cst; \
|
||||
else if (cst<0) \
|
||||
total += -cst; \
|
||||
break; \
|
||||
}
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
`COSTS_N_INSNS (N)' to specify a cost equal to N fast
|
||||
instructions. OUTER_CODE is the code of the expression in which X
|
||||
is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost
|
||||
assumptions are adequate for the target machine. */
|
||||
|
||||
#define ADDRESS_COST(ADDRESS) avr_address_cost (ADDRESS)
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
|
|
|
@ -197,6 +197,7 @@ static void c4x_asm_named_section PARAMS ((const char *, unsigned int));
|
|||
static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
static void c4x_encode_section_info PARAMS ((tree, int));
|
||||
static void c4x_globalize_label PARAMS ((FILE *, const char *));
|
||||
static bool c4x_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_BYTE_OP
|
||||
|
@ -227,6 +228,9 @@ static void c4x_globalize_label PARAMS ((FILE *, const char *));
|
|||
#undef TARGET_ASM_GLOBALIZE_LABEL
|
||||
#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS c4x_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Override command line options.
|
||||
|
@ -5062,3 +5066,98 @@ c4x_globalize_label (stream, name)
|
|||
default_globalize_label (stream, name);
|
||||
c4x_global_label (name);
|
||||
}
|
||||
|
||||
#define SHIFT_CODE_P(C) \
|
||||
((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT)
|
||||
#define LOGICAL_CODE_P(C) \
|
||||
((C) == NOT || (C) == AND || (C) == IOR || (C) == XOR)
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
c4x_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
HOST_WIDE_INT val;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
/* Some small integers are effectively free for the C40. We should
|
||||
also consider if we are using the small memory model. With
|
||||
the big memory model we require an extra insn for a constant
|
||||
loaded from memory. */
|
||||
|
||||
case CONST_INT:
|
||||
val = INTVAL (x);
|
||||
if (c4x_J_constant (x))
|
||||
*total = 0;
|
||||
else if (! TARGET_C3X
|
||||
&& outer_code == AND
|
||||
&& (val == 255 || val == 65535))
|
||||
*total = 0;
|
||||
else if (! TARGET_C3X
|
||||
&& (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
|
||||
&& (val == 16 || val == 24))
|
||||
*total = 0;
|
||||
else if (TARGET_C3X && SHIFT_CODE_P (outer_code))
|
||||
*total = 3;
|
||||
else if (LOGICAL_CODE_P (outer_code)
|
||||
? c4x_L_constant (x) : c4x_I_constant (x))
|
||||
*total = 2;
|
||||
else
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (c4x_H_constant (x))
|
||||
*total = 2;
|
||||
else if (GET_MODE (x) == QFmode)
|
||||
*total = 4;
|
||||
else
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
/* ??? Note that we return true, rather than false so that rtx_cost
|
||||
doesn't include the constant costs. Otherwise expand_mult will
|
||||
think that it is cheaper to synthesize a multiply rather than to
|
||||
use a multiply instruction. I think this is because the algorithm
|
||||
synth_mult doesn't take into account the loading of the operands,
|
||||
whereas the calculation of mult_cost does. */
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
|
||||
|| TARGET_MPYI ? 1 : 14);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
|
||||
? 15 : 50);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1461,103 +1461,10 @@ CUMULATIVE_ARGS;
|
|||
|
||||
/* Descripting Relative Cost of Operations. */
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE.
|
||||
|
||||
Note that we return, rather than break so that rtx_cost doesn't
|
||||
include CONST_COSTS otherwise expand_mult will think that it is
|
||||
cheaper to synthesize a multiply rather than to use a multiply
|
||||
instruction. I think this is because the algorithm synth_mult
|
||||
doesn't take into account the loading of the operands, whereas the
|
||||
calculation of mult_cost does.
|
||||
*/
|
||||
|
||||
|
||||
#define RTX_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case MULT: \
|
||||
return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \
|
||||
|| TARGET_MPYI ? 1 : 14); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \
|
||||
? 15 : 50);
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch.
|
||||
|
||||
An insn is assumed to cost 4 units.
|
||||
COSTS_N_INSNS (N) is defined as (N) * 4 - 2.
|
||||
|
||||
Some small integers are effectively free for the C40. We should
|
||||
also consider if we are using the small memory model. With
|
||||
the big memory model we require an extra insn for a constant
|
||||
loaded from memory.
|
||||
|
||||
This is used by expand_binop to decide whether to force a constant
|
||||
into a register. If the cost is greater than 2 and the constant
|
||||
is used within a short loop, it gets forced into a register.
|
||||
Ideally, there should be some weighting as to how mnay times it is used
|
||||
within the loop. */
|
||||
|
||||
#define SHIFT_CODE_P(C) ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT)
|
||||
|
||||
#define LOGICAL_CODE_P(C) ((C) == NOT || (C) == AND \
|
||||
|| (C) == IOR || (C) == XOR)
|
||||
|
||||
#define NON_COMMUTATIVE_CODE_P ((C) == MINUS || (C) == COMPARE)
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (c4x_J_constant (RTX)) \
|
||||
return 0; \
|
||||
if (! TARGET_C3X \
|
||||
&& OUTER_CODE == AND \
|
||||
&& GET_CODE (RTX) == CONST_INT \
|
||||
&& (INTVAL (RTX) == 255 || INTVAL (RTX) == 65535)) \
|
||||
return 0; \
|
||||
if (! TARGET_C3X \
|
||||
&& (OUTER_CODE == ASHIFTRT || OUTER_CODE == LSHIFTRT) \
|
||||
&& GET_CODE (RTX) == CONST_INT \
|
||||
&& (INTVAL (RTX) == 16 || INTVAL (RTX) == 24)) \
|
||||
return 0; \
|
||||
if (TARGET_C3X && SHIFT_CODE_P (OUTER_CODE)) \
|
||||
return 3; \
|
||||
if (LOGICAL_CODE_P (OUTER_CODE) \
|
||||
? c4x_L_constant (RTX) : c4x_I_constant (RTX)) \
|
||||
return 2; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 4; \
|
||||
case CONST_DOUBLE: \
|
||||
if (c4x_H_constant (RTX)) \
|
||||
return 2; \
|
||||
if (GET_MODE (RTX) == QFmode) \
|
||||
return 4; \
|
||||
else \
|
||||
return 8;
|
||||
|
||||
/* Compute the cost of an address. This is meant to approximate the size
|
||||
and/or execution delay of an insn using that address. If the cost is
|
||||
approximated by the RTL complexity, including CONST_COSTS above, as
|
||||
is usually the case for CISC machines, this macro should not be defined.
|
||||
For aggressively RISCy machines, only one insn format is allowed, so
|
||||
this macro should be a constant. The value of this macro only matters
|
||||
for valid addresses. We handle the most common address without
|
||||
a call to c4x_address_cost. */
|
||||
and/or execution delay of an insn using that address. The value of this
|
||||
macro only matters for valid addresses. We handle the most common address
|
||||
without a call to c4x_address_cost. */
|
||||
|
||||
#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : c4x_address_cost (ADDR))
|
||||
|
||||
|
|
|
@ -2082,6 +2082,115 @@ cris_simple_epilogue ()
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
cris_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (x);
|
||||
if (val == 0)
|
||||
*total = 0;
|
||||
else if (val < 32 && val >= -32)
|
||||
*total = 1;
|
||||
/* Eight or 16 bits are a word and cycle more expensive. */
|
||||
else if (val <= 32767 && val >= -32768)
|
||||
*total = 2;
|
||||
/* A 32 bit constant (or very seldom, unsigned 16 bits) costs
|
||||
another word. FIXME: This isn't linear to 16 bits. */
|
||||
else
|
||||
*total = 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
case LABEL_REF:
|
||||
*total = 6;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
/* For PIC, we need a prefix (if it isn't already there),
|
||||
and the PIC register. For a global PIC symbol, we also
|
||||
need a read of the GOT. */
|
||||
if (flag_pic)
|
||||
if (cris_got_symbol (x))
|
||||
*total = 2 + 4 + 6;
|
||||
else
|
||||
*total = 2 + 6;
|
||||
else
|
||||
*total = 6;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (x != CONST0_RTX (GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x)))
|
||||
*total = 12;
|
||||
else
|
||||
/* Make 0.0 cheap, else test-insns will not be used. */
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
/* Identify values that are no powers of two. Powers of 2 are
|
||||
taken care of already and those values should not be changed. */
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
|| exact_log2 (INTVAL (XEXP (x, 1)) < 0))
|
||||
{
|
||||
/* If we have a multiply insn, then the cost is between
|
||||
1 and 2 "fast" instructions. */
|
||||
if (TARGET_HAS_MUL_INSNS)
|
||||
{
|
||||
*total = COSTS_N_INSNS (1) + COSTS_N_INSNS (1) / 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Estimate as 4 + 4 * #ofbits. */
|
||||
*total = COSTS_N_INSNS (132);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
case DIV:
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
|| exact_log2 (INTVAL (XEXP (X, 1)) < 0))
|
||||
{
|
||||
/* Estimate this as 4 + 8 * #of bits. */
|
||||
*total = COSTS_N_INSNS (260);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case AND:
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
/* Two constants may actually happen before optimization. */
|
||||
&& GET_CODE (XEXP (x, 0)) != CONST_INT
|
||||
&& !CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'I'))
|
||||
{
|
||||
*total = (rtx_cost (XEXP (x, 0), outer_code) + 2
|
||||
+ 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case ZERO_EXTEND: case SIGN_EXTEND:
|
||||
*total = rtx_cost (XEXP (x, 0), outer_code);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* The ADDRESS_COST worker. */
|
||||
|
||||
int
|
||||
|
|
|
@ -1336,73 +1336,6 @@ struct cum_args {int regs;};
|
|||
|
||||
/* Node: Costs */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (RTX) == 0) \
|
||||
return 0; \
|
||||
if (INTVAL (RTX) < 32 && INTVAL (RTX) >= -32) \
|
||||
return 1; \
|
||||
/* Eight or 16 bits are a word and cycle more expensive. */ \
|
||||
if (INTVAL (RTX) <= 32767 && INTVAL (RTX) >= -32768) \
|
||||
return 2; \
|
||||
/* A 32 bit constant (or very seldom, unsigned 16 bits) costs \
|
||||
another word. FIXME: This isn't linear to 16 bits. */ \
|
||||
return 4; \
|
||||
case LABEL_REF: \
|
||||
return 6; \
|
||||
case CONST: \
|
||||
case SYMBOL_REF: \
|
||||
/* For PIC, we need a prefix (if it isn't already there), \
|
||||
and the PIC register. For a global PIC symbol, we also need a \
|
||||
read of the GOT. */ \
|
||||
return \
|
||||
flag_pic ? (cris_got_symbol (RTX) ? (2 + 4 + 6) : (2 + 6)) : 6; \
|
||||
case CONST_DOUBLE: \
|
||||
if (RTX != CONST0_RTX (GET_MODE (RTX) == VOIDmode ? DImode \
|
||||
: GET_MODE (RTX))) \
|
||||
return 12; \
|
||||
/* Make 0.0 cheap, else test-insns will not be used. */ \
|
||||
return 0;
|
||||
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MULT: \
|
||||
/* Identify values that are no powers of two. Powers of 2 are \
|
||||
taken care of already and those values should not be \
|
||||
changed. */ \
|
||||
if (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
|| exact_log2 (INTVAL (XEXP (X, 1)) < 0)) \
|
||||
{ \
|
||||
/* If we have a multiply insn, then the cost is between \
|
||||
1 and 2 "fast" instructions. */ \
|
||||
if (TARGET_HAS_MUL_INSNS) \
|
||||
return COSTS_N_INSNS (1) + COSTS_N_INSNS (1) /2; \
|
||||
\
|
||||
/* Estimate as 4 + 4 * #ofbits. */ \
|
||||
return COSTS_N_INSNS (132); \
|
||||
} \
|
||||
break; \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
case DIV: \
|
||||
if (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
|| exact_log2 (INTVAL (XEXP (X, 1)) < 0)) \
|
||||
/* Estimate this as 4 + 8 * #of bits. */ \
|
||||
return COSTS_N_INSNS (260); \
|
||||
\
|
||||
case AND: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
/* Two constants may actually happen before optimization. */ \
|
||||
&& GET_CODE (XEXP (X, 0)) != CONST_INT \
|
||||
&& !CONST_OK_FOR_LETTER_P (INTVAL (XEXP (X, 1)), 'I')) \
|
||||
return \
|
||||
rtx_cost (XEXP (X, 0), OUTER_CODE) + 2 \
|
||||
+ 2 * GET_MODE_NUNITS (GET_MODE (XEXP (X, 0))); \
|
||||
\
|
||||
case ZERO_EXTEND: case SIGN_EXTEND: \
|
||||
/* Same as move. If embedded in other insn, cost is 0. */ \
|
||||
return rtx_cost (XEXP (X, 0), OUTER_CODE);
|
||||
|
||||
#define ADDRESS_COST(X) cris_address_cost (X)
|
||||
|
||||
/* FIXME: Need to define REGISTER_MOVE_COST when more register classes are
|
||||
|
|
|
@ -54,6 +54,7 @@ static void d30v_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
static void d30v_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static int d30v_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
static int d30v_issue_rate PARAMS ((void));
|
||||
static bool d30v_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Define the information needed to generate branch and scc insns. This is
|
||||
stored from the compare operation. */
|
||||
|
@ -99,6 +100,9 @@ enum reg_class reg_class_from_letter[256];
|
|||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE d30v_issue_rate
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS d30v_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
|
@ -3505,3 +3509,23 @@ d30v_return_addr ()
|
|||
{
|
||||
return get_hard_reg_initial_val (Pmode, GPR_LINK);
|
||||
}
|
||||
|
||||
static bool
|
||||
d30v_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code;
|
||||
int outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
|
||||
? 1 : 2);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2426,55 +2426,6 @@ do { \
|
|||
|
||||
/* Describing Relative Costs of Operations */
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs of
|
||||
constant RTL expressions. It must contain `case' labels for expression
|
||||
codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'.
|
||||
Each case must ultimately reach a `return' statement to return the relative
|
||||
cost of the use of that kind of constant value in an expression. The cost
|
||||
may depend on the precise value of the constant, which is available for
|
||||
examination in X, and the rtx code of the expression in which it is
|
||||
contained, found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained with
|
||||
`GET_CODE (X)'. */
|
||||
|
||||
/* On the d30v, consider operatnds that fit in a short instruction very
|
||||
cheap. However, at this time, it causes cse to generate incorrect
|
||||
code, so disable it for now. */
|
||||
#if 0
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (IN_RANGE_P (INTVAL (X), 0, 31)) \
|
||||
return 0; \
|
||||
else if ((OUTER_CODE) == LEU && (OUTER_CODE) == LTU \
|
||||
&& (OUTER_CODE) == GEU && (OUTER_CODE) == GTU) \
|
||||
return IN_RANGE_P (INTVAL (X), 32, 63) ? 0 : COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return IN_RANGE_P (INTVAL (X), -31, -1) ? 0 : COSTS_N_INSNS (2); \
|
||||
case SYMBOL_REF: \
|
||||
case LABEL_REF: \
|
||||
case CONST: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case CONST_DOUBLE: \
|
||||
return COSTS_N_INSNS ((GET_MODE (X) == SFmode) ? 2 : 4);
|
||||
#else
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE)
|
||||
#endif
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be
|
||||
used, for example, to indicate how costly a multiply instruction is. In
|
||||
writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify
|
||||
a cost equal to N fast instructions. OUTER_CODE is the code of the
|
||||
expression in which X is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost assumptions are
|
||||
adequate for the target machine. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MULT: \
|
||||
return COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT \
|
||||
&& exact_log2 (INTVAL (XEXP (x, 1))) >= 0) \
|
||||
? 1 : 2);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains ADDRESS.
|
||||
If not defined, the cost is computed from the ADDRESS expression and the
|
||||
`CONST_COSTS' values.
|
||||
|
|
|
@ -151,8 +151,10 @@ static const char *const lshift_right_asm_first[] =
|
|||
static int reg_save_size PARAMS ((void));
|
||||
static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
|
||||
static bool dsp16xx_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
|
||||
#undef TARGET_ASM_BYTE_OP
|
||||
#define TARGET_ASM_BYTE_OP "\tint\t"
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
|
@ -165,6 +167,9 @@ static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||
#define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS dsp16xx_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
int
|
||||
|
@ -2569,3 +2574,88 @@ signed_comparison_operator (op, mode)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
dsp16xx_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code;
|
||||
int outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
*total = (unsigned HOST_WIDE_INT) INTVAL (x) < 65536 ? 0 : 2;
|
||||
return true;
|
||||
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
*total = COSTS_N_INSNS (GET_MODE (x) == QImode ? 2 : 4);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
*total = COSTS_N_INSNS (38);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (GET_MODE (x) == QImode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (38);
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
|
||||
{
|
||||
*total = 1;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*total = COSTS_N_INSNS (38);
|
||||
return true;
|
||||
}
|
||||
|
||||
case NEG:
|
||||
case NOT:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT number = INTVAL (XEXP (x, 1));
|
||||
if (number == 1 || number == 4 || number == 8
|
||||
|| number == 16)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if (TARGET_BMU)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (num_1600_core_shifts (number));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (TARGET_BMU)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (15);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1431,76 +1431,6 @@ extern struct dsp16xx_frame_info current_frame_info;
|
|||
|
||||
/* DESCRIBING RELATIVE COSTS OF OPERATIONS */
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. */
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
return (unsigned) INTVAL (RTX) < 65536 ? 0 : 2; \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
case CONST: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
\
|
||||
case CONST_DOUBLE: \
|
||||
return COSTS_N_INSNS (2);
|
||||
|
||||
/* Like CONST_COSTS but applies to nonconstant RTL expressions.
|
||||
This can be used, for example to indicate how costly a multiply
|
||||
instruction is. */
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MEM: \
|
||||
return GET_MODE (X) == QImode ? COSTS_N_INSNS (2) : \
|
||||
COSTS_N_INSNS (4); \
|
||||
case DIV: \
|
||||
case MOD: \
|
||||
return COSTS_N_INSNS (38); \
|
||||
case MULT: \
|
||||
if (GET_MODE (X) == QImode) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (38); \
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \
|
||||
{ \
|
||||
return (1 + \
|
||||
rtx_cost (XEXP (X, 0), CODE) + \
|
||||
rtx_cost (XEXP (X, 1), CODE)); \
|
||||
} \
|
||||
else \
|
||||
return COSTS_N_INSNS (38); \
|
||||
\
|
||||
case AND: case IOR: case XOR: \
|
||||
return (1 + \
|
||||
rtx_cost (XEXP (X, 0), CODE) + \
|
||||
rtx_cost (XEXP (X, 1), CODE)); \
|
||||
\
|
||||
case NEG: case NOT: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
if (GET_CODE (XEXP (X,1)) == CONST_INT) \
|
||||
{ \
|
||||
int number = INTVAL(XEXP (X,1)); \
|
||||
if (number == 1 || number == 4 || number == 8 || \
|
||||
number == 16) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else \
|
||||
{ \
|
||||
if (TARGET_BMU) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (num_1600_core_shifts(number)); \
|
||||
} \
|
||||
} \
|
||||
if (TARGET_BMU) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else \
|
||||
return COSTS_N_INSNS (15);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
address. */
|
||||
#define ADDRESS_COST(ADDR) dsp16xx_address_cost (ADDR)
|
||||
|
|
|
@ -283,6 +283,7 @@ static rtx frv_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int)
|
|||
static bool frv_in_small_data_p PARAMS ((tree));
|
||||
static void frv_asm_output_mi_thunk
|
||||
PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
|
||||
static bool frv_rtx_costs PARAMS ((rtx, int, int, int*));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||
|
@ -301,6 +302,8 @@ static void frv_asm_output_mi_thunk
|
|||
#define TARGET_EXPAND_BUILTIN frv_expand_builtin
|
||||
#undef TARGET_IN_SMALL_DATA_P
|
||||
#define TARGET_IN_SMALL_DATA_P frv_in_small_data_p
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS frv_rtx_costs
|
||||
|
||||
#undef TARGET_ASM_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
|
||||
|
@ -9788,3 +9791,65 @@ frv_in_small_data_p (decl)
|
|||
return symbol_ref_small_data_p (XEXP (DECL_RTL (decl), 0))
|
||||
&& size > 0 && size <= g_switch_value;
|
||||
}
|
||||
|
||||
static bool
|
||||
frv_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
/* Make 12 bit integers really cheap. */
|
||||
if (IN_RANGE_P (INTVAL (x), -2048, 2047))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST_DOUBLE:
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
case NOT:
|
||||
case NEG:
|
||||
case COMPARE:
|
||||
if (GET_MODE (x) == SImode)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if (GET_MODE (x) == DImode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (GET_MODE (x) == SImode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (6); /* guess */
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (18);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2541,65 +2541,6 @@ __asm__("\n" \
|
|||
|
||||
/* Describing Relative Costs of Operations. */
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs of
|
||||
constant RTL expressions. It must contain `case' labels for expression
|
||||
codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'.
|
||||
Each case must ultimately reach a `return' statement to return the relative
|
||||
cost of the use of that kind of constant value in an expression. The cost
|
||||
may depend on the precise value of the constant, which is available for
|
||||
examination in X, and the rtx code of the expression in which it is
|
||||
contained, found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained with
|
||||
`GET_CODE (X)'. */
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
case CONST_DOUBLE: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
case CONST_INT: \
|
||||
/* Make 12 bit integers really cheap */ \
|
||||
return IN_RANGE_P (INTVAL (X), -2048, 2047) ? 0 : COSTS_N_INSNS (2); \
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be
|
||||
used, for example, to indicate how costly a multiply instruction is. In
|
||||
writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify
|
||||
a cost equal to N fast instructions. OUTER_CODE is the code of the
|
||||
expression in which X is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost assumptions are
|
||||
adequate for the target machine. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
case NOT: \
|
||||
case NEG: \
|
||||
case COMPARE: \
|
||||
if (GET_MODE (X) == SImode) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else if (GET_MODE (X) == DImode) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (3); /* guess */ \
|
||||
\
|
||||
case MULT: \
|
||||
if (GET_MODE (X) == SImode) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (6); /* guess */ \
|
||||
\
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
return COSTS_N_INSNS (18);
|
||||
|
||||
/* A C expression for the cost of moving data from a register in class FROM to
|
||||
one in class TO. The classes are expressed using the enumeration values
|
||||
such as `GENERAL_REGS'. A value of 4 is the default; other values are
|
||||
|
|
|
@ -34,9 +34,6 @@ extern unsigned int compute_a_shift_length PARAMS ((rtx, rtx *));
|
|||
extern const char *emit_a_rotate PARAMS ((enum rtx_code, rtx *));
|
||||
extern const char *output_simode_bld PARAMS ((int, rtx[]));
|
||||
extern void print_operand_address PARAMS ((FILE *, rtx));
|
||||
extern int const_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
extern int h8300_and_costs PARAMS ((rtx));
|
||||
extern int h8300_shift_costs PARAMS ((rtx));
|
||||
extern void print_operand PARAMS ((FILE *, rtx, int));
|
||||
extern void final_prescan_insn PARAMS ((rtx, rtx *, int));
|
||||
extern int do_movsi PARAMS ((rtx[]));
|
||||
|
|
|
@ -69,6 +69,10 @@ static void h8300_asm_named_section PARAMS ((const char *, unsigned int));
|
|||
static void h8300_encode_label PARAMS ((tree));
|
||||
static void h8300_encode_section_info PARAMS ((tree, int));
|
||||
static const char *h8300_strip_name_encoding PARAMS ((const char *));
|
||||
static int const_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
static int h8300_and_costs PARAMS ((rtx));
|
||||
static int h8300_shift_costs PARAMS ((rtx));
|
||||
static bool h8300_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* CPU_TYPE, says what cpu we're compiling for. */
|
||||
int cpu_type;
|
||||
|
@ -113,6 +117,9 @@ const char *h8_push_op, *h8_pop_op, *h8_mov_op;
|
|||
#undef TARGET_INSERT_ATTRIBUTES
|
||||
#define TARGET_INSERT_ATTRIBUTES h8300_insert_attributes
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS h8300_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* See below where shifts are handled for explanation of this enum. */
|
||||
|
@ -1097,7 +1104,7 @@ function_arg (cum, mode, type, named)
|
|||
|
||||
/* Return the cost of the rtx R with code CODE. */
|
||||
|
||||
int
|
||||
static int
|
||||
const_costs (r, c, outer_code)
|
||||
rtx r;
|
||||
enum rtx_code c;
|
||||
|
@ -1144,7 +1151,7 @@ const_costs (r, c, outer_code)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
h8300_and_costs (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -1164,7 +1171,7 @@ h8300_and_costs (x)
|
|||
return compute_logical_op_length (GET_MODE (x), operands);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
h8300_shift_costs (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -1181,6 +1188,49 @@ h8300_shift_costs (x)
|
|||
operands[3] = x;
|
||||
return compute_a_shift_length (NULL, operands);
|
||||
}
|
||||
|
||||
static bool
|
||||
h8300_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case AND:
|
||||
*total = COSTS_N_INSNS (h8300_and_costs (x));
|
||||
return true;
|
||||
|
||||
/* We say that MOD and DIV are so expensive because otherwise we'll
|
||||
generate some really horrible code for division of a power of two. */
|
||||
case MOD:
|
||||
case DIV:
|
||||
*total = 60;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = 20;
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = COSTS_N_INSNS (h8300_shift_costs (x));
|
||||
return true;
|
||||
|
||||
case ROTATE:
|
||||
case ROTATERT:
|
||||
if (GET_MODE (x) == HImode)
|
||||
*total = 2;
|
||||
else
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
default:
|
||||
*total = const_costs (x, code, outer_code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Documentation for the machine specific operand escapes:
|
||||
|
||||
|
|
|
@ -1010,39 +1010,8 @@ struct cum_arg
|
|||
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
|
||||
LENGTH += h8300_adjust_insn_length (INSN, LENGTH);
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define DEFAULT_RTX_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
return (const_costs (RTX, CODE, OUTER_CODE));
|
||||
|
||||
#define BRANCH_COST 0
|
||||
|
||||
/* We say that MOD and DIV are so cheap because otherwise we'll
|
||||
generate some really horrible code for division of a power of two. */
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
|
||||
#define RTX_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case AND: \
|
||||
return COSTS_N_INSNS (h8300_and_costs (RTX)); \
|
||||
case MOD: \
|
||||
case DIV: \
|
||||
return 60; \
|
||||
case MULT: \
|
||||
return 20; \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (h8300_shift_costs (RTX)); \
|
||||
case ROTATE: \
|
||||
case ROTATERT: \
|
||||
if (GET_MODE (RTX) == HImode) return 2; \
|
||||
return 8;
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
|
||||
/* Here we define machine-dependent flags and fields in cc_status
|
||||
|
|
|
@ -112,6 +112,7 @@ static int mvs_hash_alias PARAMS ((const char *));
|
|||
#endif
|
||||
static void i370_encode_section_info PARAMS ((tree, int));
|
||||
static void i370_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
||||
static bool i370_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* ===================================================== */
|
||||
/* defines and functions specific to the HLASM assembler */
|
||||
|
@ -317,6 +318,8 @@ static const unsigned char ebcasc[256] =
|
|||
#define TARGET_ENCODE_SECTION_INFO i370_encode_section_info
|
||||
#undef TARGET_ASM_INTERNAL_LABEL
|
||||
#define TARGET_ASM_INTERNAL_LABEL i370_internal_label
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS i370_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -1613,3 +1616,35 @@ i370_internal_label (stream, prefix, labelno)
|
|||
|
||||
default_internal_label (stream, prefix, labelno);
|
||||
}
|
||||
|
||||
static bool
|
||||
i370_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code;
|
||||
int outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if ((unsigned HOST_WIDE_INT) INTVAL (x) < 0xfff)
|
||||
{
|
||||
*total = 1;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -901,21 +901,6 @@ enum reg_class
|
|||
|
||||
#define FUNCTION_MODE QImode
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX whose
|
||||
rtx-code is CODE. The body of this macro is a portion of a switch
|
||||
statement. If the code is computed here, return it with a return
|
||||
statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTERCODE) \
|
||||
case CONST_INT: \
|
||||
if ((unsigned) INTVAL (RTX) < 0xfff) return 1; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 2; \
|
||||
case CONST_DOUBLE: \
|
||||
return 4;
|
||||
|
||||
/* A C statement (sans semicolon) to update the integer variable COST
|
||||
based on the relationship between INSN that is dependent on
|
||||
DEP_INSN through the dependence LINK. The default is to make no
|
||||
|
|
|
@ -50,6 +50,14 @@ Boston, MA 02111-1307, USA. */
|
|||
#define CHECK_STACK_LIMIT (-1)
|
||||
#endif
|
||||
|
||||
/* Return index of given mode in mult and division cost tables. */
|
||||
#define MODE_INDEX(mode) \
|
||||
((mode) == QImode ? 0 \
|
||||
: (mode) == HImode ? 1 \
|
||||
: (mode) == SImode ? 2 \
|
||||
: (mode) == DImode ? 3 \
|
||||
: 4)
|
||||
|
||||
/* Processor costs (relative to an add) */
|
||||
static const
|
||||
struct processor_costs size_cost = { /* costs for tunning for size */
|
||||
|
@ -872,6 +880,7 @@ static int ix86_value_regno PARAMS ((enum machine_mode));
|
|||
static bool ix86_ms_bitfield_layout_p PARAMS ((tree));
|
||||
static tree ix86_handle_struct_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||
static int extended_reg_mentioned_1 PARAMS ((rtx *, void *));
|
||||
static bool ix86_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
|
||||
static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
|
||||
|
@ -988,6 +997,9 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS ix86_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
|
@ -14458,6 +14470,257 @@ ix86_memory_move_cost (mode, class, in)
|
|||
}
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
ix86_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
if (TARGET_64BIT && !x86_64_sign_extended_value (x))
|
||||
*total = 3;
|
||||
else if (TARGET_64BIT && !x86_64_zero_extended_value (x))
|
||||
*total = 2;
|
||||
else if (flag_pic && SYMBOLIC_CONST (x))
|
||||
*total = 1;
|
||||
else
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (mode == VOIDmode)
|
||||
*total = 0;
|
||||
else
|
||||
switch (standard_80387_constant_p (x))
|
||||
{
|
||||
case 1: /* 0.0 */
|
||||
*total = 1;
|
||||
break;
|
||||
case 2: /* 1.0 */
|
||||
*total = 2;
|
||||
break;
|
||||
default:
|
||||
/* Start with (MEM (SYMBOL_REF)), since that's where
|
||||
it'll probably end up. Add a penalty for size. */
|
||||
*total = (COSTS_N_INSNS (1)
|
||||
+ (flag_pic != 0)
|
||||
+ (mode == SFmode ? 0 : mode == DFmode ? 1 : 2));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
case ZERO_EXTEND:
|
||||
/* The zero extensions is often completely free on x86_64, so make
|
||||
it as cheap as possible. */
|
||||
if (TARGET_64BIT && mode == DImode
|
||||
&& GET_MODE (XEXP (x, 0)) == SImode)
|
||||
*total = 1;
|
||||
else if (TARGET_ZERO_EXTEND_WITH_AND)
|
||||
*total = COSTS_N_INSNS (ix86_cost->add);
|
||||
else
|
||||
*total = COSTS_N_INSNS (ix86_cost->movzx);
|
||||
return false;
|
||||
|
||||
case SIGN_EXTEND:
|
||||
*total = COSTS_N_INSNS (ix86_cost->movsx);
|
||||
return false;
|
||||
|
||||
case ASHIFT:
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& (GET_MODE (XEXP (x, 0)) != DImode || TARGET_64BIT))
|
||||
{
|
||||
HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
|
||||
if (value == 1)
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->add);
|
||||
return false;
|
||||
}
|
||||
if ((value == 2 || value == 3)
|
||||
&& !TARGET_DECOMPOSE_LEA
|
||||
&& ix86_cost->lea <= ix86_cost->shift_const)
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->lea);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case ROTATE:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
case ROTATERT:
|
||||
if (!TARGET_64BIT && GET_MODE (XEXP (x, 0)) == DImode)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
if (INTVAL (XEXP (x, 1)) > 32)
|
||||
*total = COSTS_N_INSNS(ix86_cost->shift_const + 2);
|
||||
else
|
||||
*total = COSTS_N_INSNS(ix86_cost->shift_const * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == AND)
|
||||
*total = COSTS_N_INSNS(ix86_cost->shift_var * 2);
|
||||
else
|
||||
*total = COSTS_N_INSNS(ix86_cost->shift_var * 6 + 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
*total = COSTS_N_INSNS (ix86_cost->shift_const);
|
||||
else
|
||||
*total = COSTS_N_INSNS (ix86_cost->shift_var);
|
||||
}
|
||||
return false;
|
||||
|
||||
case MULT:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
*total = COSTS_N_INSNS (ix86_cost->fmul);
|
||||
else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
|
||||
int nbits;
|
||||
|
||||
for (nbits = 0; value != 0; value >>= 1)
|
||||
nbits++;
|
||||
|
||||
*total = COSTS_N_INSNS (ix86_cost->mult_init[MODE_INDEX (mode)]
|
||||
+ nbits * ix86_cost->mult_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is arbitrary */
|
||||
*total = COSTS_N_INSNS (ix86_cost->mult_init[MODE_INDEX (mode)]
|
||||
+ 7 * ix86_cost->mult_bit);
|
||||
}
|
||||
return false;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
*total = COSTS_N_INSNS (ix86_cost->fdiv);
|
||||
else
|
||||
*total = COSTS_N_INSNS (ix86_cost->divide[MODE_INDEX (mode)]);
|
||||
return false;
|
||||
|
||||
case PLUS:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
*total = COSTS_N_INSNS (ix86_cost->fadd);
|
||||
else if (!TARGET_DECOMPOSE_LEA
|
||||
&& GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (Pmode))
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
|
||||
&& CONSTANT_P (XEXP (x, 1)))
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1));
|
||||
if (val == 2 || val == 4 || val == 8)
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->lea);
|
||||
*total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
|
||||
*total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
|
||||
outer_code);
|
||||
*total += rtx_cost (XEXP (x, 1), outer_code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (GET_CODE (XEXP (x, 0)) == MULT
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
|
||||
if (val == 2 || val == 4 || val == 8)
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->lea);
|
||||
*total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
|
||||
*total += rtx_cost (XEXP (x, 1), outer_code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (GET_CODE (XEXP (x, 0)) == PLUS)
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->lea);
|
||||
*total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
|
||||
*total += rtx_cost (XEXP (XEXP (x, 0), 1), outer_code);
|
||||
*total += rtx_cost (XEXP (x, 1), outer_code);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case MINUS:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->fadd);
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
if (!TARGET_64BIT && mode == DImode)
|
||||
{
|
||||
*total = (COSTS_N_INSNS (ix86_cost->add) * 2
|
||||
+ (rtx_cost (XEXP (x, 0), outer_code)
|
||||
<< (GET_MODE (XEXP (x, 0)) != DImode))
|
||||
+ (rtx_cost (XEXP (x, 1), outer_code)
|
||||
<< (GET_MODE (XEXP (x, 1)) != DImode)));
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case NEG:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
{
|
||||
*total = COSTS_N_INSNS (ix86_cost->fchs);
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case NOT:
|
||||
if (!TARGET_64BIT && mode == DImode)
|
||||
*total = COSTS_N_INSNS (ix86_cost->add * 2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (ix86_cost->add);
|
||||
return false;
|
||||
|
||||
case FLOAT_EXTEND:
|
||||
if (!TARGET_SSE_MATH || !VALID_SSE_REG_MODE (mode))
|
||||
*total = 0;
|
||||
return false;
|
||||
|
||||
case ABS:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
*total = COSTS_N_INSNS (ix86_cost->fabs);
|
||||
return false;
|
||||
|
||||
case SQRT:
|
||||
if (FLOAT_MODE_P (mode))
|
||||
*total = COSTS_N_INSNS (ix86_cost->fsqrt);
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
|
||||
static void
|
||||
ix86_svr3_asm_out_constructor (symbol, priority)
|
||||
|
|
|
@ -2585,254 +2585,6 @@ do { \
|
|||
so give the MEM rtx a byte's mode. */
|
||||
#define FUNCTION_MODE QImode
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain `case' labels for
|
||||
expression codes `const_int', `const', `symbol_ref', `label_ref'
|
||||
and `const_double'. Each case must ultimately reach a `return'
|
||||
statement to return the relative cost of the use of that kind of
|
||||
constant value in an expression. The cost may depend on the
|
||||
precise value of the constant, which is available for examination
|
||||
in X, and the rtx code of the expression in which it is contained,
|
||||
found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
if (TARGET_64BIT && !x86_64_sign_extended_value (RTX)) \
|
||||
return 3; \
|
||||
if (TARGET_64BIT && !x86_64_zero_extended_value (RTX)) \
|
||||
return 2; \
|
||||
return flag_pic && SYMBOLIC_CONST (RTX) ? 1 : 0; \
|
||||
\
|
||||
case CONST_DOUBLE: \
|
||||
if (GET_MODE (RTX) == VOIDmode) \
|
||||
return 0; \
|
||||
switch (standard_80387_constant_p (RTX)) \
|
||||
{ \
|
||||
case 1: /* 0.0 */ \
|
||||
return 1; \
|
||||
case 2: /* 1.0 */ \
|
||||
return 2; \
|
||||
default: \
|
||||
/* Start with (MEM (SYMBOL_REF)), since that's where \
|
||||
it'll probably end up. Add a penalty for size. */ \
|
||||
return (COSTS_N_INSNS (1) + (flag_pic != 0) \
|
||||
+ (GET_MODE (RTX) == SFmode ? 0 \
|
||||
: GET_MODE (RTX) == DFmode ? 1 : 2)); \
|
||||
}
|
||||
|
||||
/* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */
|
||||
#define TOPLEVEL_COSTS_N_INSNS(N) \
|
||||
do { total = COSTS_N_INSNS (N); goto egress_rtx_costs; } while (0)
|
||||
|
||||
/* Return index of given mode in mult and division cost tables. */
|
||||
#define MODE_INDEX(mode) \
|
||||
((mode) == QImode ? 0 \
|
||||
: (mode) == HImode ? 1 \
|
||||
: (mode) == SImode ? 2 \
|
||||
: (mode) == DImode ? 3 \
|
||||
: 4)
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
`COSTS_N_INSNS (N)' to specify a cost equal to N fast
|
||||
instructions. OUTER_CODE is the code of the expression in which X
|
||||
is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost
|
||||
assumptions are adequate for the target machine. */
|
||||
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case ZERO_EXTEND: \
|
||||
/* The zero extensions is often completely free on x86_64, so make \
|
||||
it as cheap as possible. */ \
|
||||
if (TARGET_64BIT && GET_MODE (X) == DImode \
|
||||
&& GET_MODE (XEXP (X, 0)) == SImode) \
|
||||
{ \
|
||||
total = 1; goto egress_rtx_costs; \
|
||||
} \
|
||||
else \
|
||||
TOPLEVEL_COSTS_N_INSNS (TARGET_ZERO_EXTEND_WITH_AND ? \
|
||||
ix86_cost->add : ix86_cost->movzx); \
|
||||
break; \
|
||||
case SIGN_EXTEND: \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->movsx); \
|
||||
break; \
|
||||
case ASHIFT: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& (GET_MODE (XEXP (X, 0)) != DImode || TARGET_64BIT)) \
|
||||
{ \
|
||||
HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \
|
||||
if (value == 1) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
|
||||
if ((value == 2 || value == 3) \
|
||||
&& !TARGET_DECOMPOSE_LEA \
|
||||
&& ix86_cost->lea <= ix86_cost->shift_const) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->lea); \
|
||||
} \
|
||||
/* fall through */ \
|
||||
\
|
||||
case ROTATE: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
case ROTATERT: \
|
||||
if (!TARGET_64BIT && GET_MODE (XEXP (X, 0)) == DImode) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
if (INTVAL (XEXP (X, 1)) > 32) \
|
||||
TOPLEVEL_COSTS_N_INSNS(ix86_cost->shift_const + 2); \
|
||||
else \
|
||||
TOPLEVEL_COSTS_N_INSNS(ix86_cost->shift_const * 2); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 1)) == AND) \
|
||||
TOPLEVEL_COSTS_N_INSNS(ix86_cost->shift_var * 2); \
|
||||
else \
|
||||
TOPLEVEL_COSTS_N_INSNS(ix86_cost->shift_var * 6 + 2); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->shift_const); \
|
||||
else \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->shift_var); \
|
||||
} \
|
||||
break; \
|
||||
\
|
||||
case MULT: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fmul); \
|
||||
else if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \
|
||||
int nbits = 0; \
|
||||
\
|
||||
while (value != 0) \
|
||||
{ \
|
||||
nbits++; \
|
||||
value >>= 1; \
|
||||
} \
|
||||
\
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \
|
||||
[MODE_INDEX (GET_MODE (X))] \
|
||||
+ nbits * ix86_cost->mult_bit); \
|
||||
} \
|
||||
else /* This is arbitrary */ \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \
|
||||
[MODE_INDEX (GET_MODE (X))] \
|
||||
+ 7 * ix86_cost->mult_bit); \
|
||||
\
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fdiv); \
|
||||
else \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->divide \
|
||||
[MODE_INDEX (GET_MODE (X))]); \
|
||||
break; \
|
||||
\
|
||||
case PLUS: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fadd); \
|
||||
else if (!TARGET_DECOMPOSE_LEA \
|
||||
&& INTEGRAL_MODE_P (GET_MODE (X)) \
|
||||
&& GET_MODE_BITSIZE (GET_MODE (X)) <= GET_MODE_BITSIZE (Pmode)) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == MULT \
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (X, 0), 0), 1)) == CONST_INT \
|
||||
&& CONSTANT_P (XEXP (X, 1))) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (X, 0), 0), 1));\
|
||||
if (val == 2 || val == 4 || val == 8) \
|
||||
{ \
|
||||
return (COSTS_N_INSNS (ix86_cost->lea) \
|
||||
+ rtx_cost (XEXP (XEXP (X, 0), 1), \
|
||||
(OUTER_CODE)) \
|
||||
+ rtx_cost (XEXP (XEXP (XEXP (X, 0), 0), 0), \
|
||||
(OUTER_CODE)) \
|
||||
+ rtx_cost (XEXP (X, 1), (OUTER_CODE))); \
|
||||
} \
|
||||
} \
|
||||
else if (GET_CODE (XEXP (X, 0)) == MULT \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (X, 0), 1)); \
|
||||
if (val == 2 || val == 4 || val == 8) \
|
||||
{ \
|
||||
return (COSTS_N_INSNS (ix86_cost->lea) \
|
||||
+ rtx_cost (XEXP (XEXP (X, 0), 0), \
|
||||
(OUTER_CODE)) \
|
||||
+ rtx_cost (XEXP (X, 1), (OUTER_CODE))); \
|
||||
} \
|
||||
} \
|
||||
else if (GET_CODE (XEXP (X, 0)) == PLUS) \
|
||||
{ \
|
||||
return (COSTS_N_INSNS (ix86_cost->lea) \
|
||||
+ rtx_cost (XEXP (XEXP (X, 0), 0), (OUTER_CODE)) \
|
||||
+ rtx_cost (XEXP (XEXP (X, 0), 1), (OUTER_CODE)) \
|
||||
+ rtx_cost (XEXP (X, 1), (OUTER_CODE))); \
|
||||
} \
|
||||
} \
|
||||
/* fall through */ \
|
||||
\
|
||||
case MINUS: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fadd); \
|
||||
/* fall through */ \
|
||||
\
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
if (!TARGET_64BIT && GET_MODE (X) == DImode) \
|
||||
return (COSTS_N_INSNS (ix86_cost->add) * 2 \
|
||||
+ (rtx_cost (XEXP (X, 0), (OUTER_CODE)) \
|
||||
<< (GET_MODE (XEXP (X, 0)) != DImode)) \
|
||||
+ (rtx_cost (XEXP (X, 1), (OUTER_CODE)) \
|
||||
<< (GET_MODE (XEXP (X, 1)) != DImode))); \
|
||||
/* fall through */ \
|
||||
\
|
||||
case NEG: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fchs); \
|
||||
/* fall through */ \
|
||||
\
|
||||
case NOT: \
|
||||
if (!TARGET_64BIT && GET_MODE (X) == DImode) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2); \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
|
||||
\
|
||||
case FLOAT_EXTEND: \
|
||||
if (!TARGET_SSE_MATH \
|
||||
|| !VALID_SSE_REG_MODE (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (0); \
|
||||
break; \
|
||||
\
|
||||
case ABS: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fabs); \
|
||||
break; \
|
||||
\
|
||||
case SQRT: \
|
||||
if (FLOAT_MODE_P (GET_MODE (X))) \
|
||||
TOPLEVEL_COSTS_N_INSNS (ix86_cost->fsqrt); \
|
||||
break; \
|
||||
\
|
||||
egress_rtx_costs: \
|
||||
break;
|
||||
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
ADDRESS. If not defined, the cost is computed from the ADDRESS
|
||||
expression and the `CONST_COSTS' values.
|
||||
|
|
|
@ -50,6 +50,7 @@ static void i960_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
static void i960_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void i960_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree));
|
||||
static bool i960_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Save the operands last given to a compare for use when we
|
||||
generate a scc or bcc insn. */
|
||||
|
@ -107,6 +108,9 @@ static int ret_label = 0;
|
|||
#undef TARGET_CAN_ASM_OUTPUT_MI_THUNK
|
||||
#define TARGET_CAN_ASM_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS i960_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Override conflicting target switch options.
|
||||
|
@ -2856,3 +2860,52 @@ i960_output_mi_thunk (file, thunk, delta, vcall_offset, function)
|
|||
assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
i960_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* Constants that can be (non-ldconst) insn operands are cost 0.
|
||||
Constants that can be non-ldconst operands in rare cases are cost 1.
|
||||
Other constants have higher costs.
|
||||
|
||||
Must check for OUTER_CODE of SET for power2_operand, because
|
||||
reload_cse_move2add calls us with OUTER_CODE of PLUS to decide
|
||||
when to replace set with add. */
|
||||
|
||||
case CONST_INT:
|
||||
if ((INTVAL (x) >= 0 && INTVAL (x) < 32)
|
||||
|| (outer_code == SET && power2_operand (x, VOIDmode)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
else if (INTVAL (x) >= -31 && INTVAL (x) < 0)
|
||||
{
|
||||
*total = 1;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = (TARGET_C_SERIES ? 6 : 8);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode)
|
||||
|| x == CONST1_RTX (DFmode) || x == CONST1_RTX (SFmode))
|
||||
*total = 1;
|
||||
else
|
||||
*total = 12;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1154,36 +1154,6 @@ extern struct rtx_def *i960_compare_op0, *i960_compare_op1;
|
|||
#define TARGET_MEM_FUNCTIONS 1
|
||||
#endif
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
/* Constants that can be (non-ldconst) insn operands are cost 0. Constants
|
||||
that can be non-ldconst operands in rare cases are cost 1. Other constants
|
||||
have higher costs. */
|
||||
|
||||
/* Must check for OUTER_CODE of SET for power2_operand, because
|
||||
reload_cse_move2add calls us with OUTER_CODE of PLUS to decide when
|
||||
to replace set with add. */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if ((INTVAL (RTX) >= 0 && INTVAL (RTX) < 32) \
|
||||
|| (OUTER_CODE == SET && power2_operand (RTX, VOIDmode))) \
|
||||
return 0; \
|
||||
else if (INTVAL (RTX) >= -31 && INTVAL (RTX) < 0) \
|
||||
return 1; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return (TARGET_C_SERIES ? 6 : 8); \
|
||||
case CONST_DOUBLE: \
|
||||
if ((RTX) == CONST0_RTX (DFmode) || (RTX) == CONST0_RTX (SFmode) \
|
||||
|| (RTX) == CONST1_RTX (DFmode) || (RTX) == CONST1_RTX (SFmode))\
|
||||
return 1; \
|
||||
return 12;
|
||||
|
||||
/* The i960 offers addressing modes which are "as cheap as a register".
|
||||
See i960.c (or gcc.texinfo) for details. */
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ static rtx gen_fr_spill_x PARAMS ((rtx, rtx, rtx));
|
|||
static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
|
||||
|
||||
static enum machine_mode hfa_element_mode PARAMS ((tree, int));
|
||||
static bool ia64_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
static void fix_range PARAMS ((const char *));
|
||||
static struct machine_function * ia64_init_machine_status PARAMS ((void));
|
||||
static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
|
||||
|
@ -314,6 +315,9 @@ static const struct attribute_spec ia64_attribute_table[] =
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS ia64_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
|
||||
|
@ -3972,6 +3976,85 @@ ia64_print_operand (file, x, code)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
/* ??? This is incomplete. */
|
||||
|
||||
static bool
|
||||
ia64_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
switch (outer_code)
|
||||
{
|
||||
case SET:
|
||||
*total = CONST_OK_FOR_J (INTVAL (x)) ? 0 : COSTS_N_INSNS (1);
|
||||
return true;
|
||||
case PLUS:
|
||||
if (CONST_OK_FOR_I (INTVAL (x)))
|
||||
*total = 0;
|
||||
else if (CONST_OK_FOR_J (INTVAL (x)))
|
||||
*total = 1;
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
default:
|
||||
if (CONST_OK_FOR_K (INTVAL (x)) || CONST_OK_FOR_L (INTVAL (x)))
|
||||
*total = 0;
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
|
||||
case CONST_DOUBLE:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
/* For multiplies wider than HImode, we have to go to the FPU,
|
||||
which normally involves copies. Plus there's the latency
|
||||
of the multiply itself, and the latency of the instructions to
|
||||
transfer integer regs to FP regs. */
|
||||
/* ??? Check for FP mode. */
|
||||
if (GET_MODE_SIZE (GET_MODE (x)) > 2)
|
||||
*total = COSTS_N_INSNS (10);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
/* We make divide expensive, so that divide-by-constant will be
|
||||
optimized to a multiply. */
|
||||
*total = COSTS_N_INSNS (60);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the cost of moving data from a register in class FROM to
|
||||
one in class TO, using MODE. */
|
||||
|
||||
|
|
|
@ -1673,62 +1673,6 @@ do { \
|
|||
|
||||
/* Describing Relative Costs of Operations */
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs of
|
||||
constant RTL expressions. */
|
||||
|
||||
/* ??? This is incomplete. */
|
||||
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if ((X) == const0_rtx) \
|
||||
return 0; \
|
||||
switch (OUTER_CODE) \
|
||||
{ \
|
||||
case SET: \
|
||||
return CONST_OK_FOR_J (INTVAL (X)) ? 0 : COSTS_N_INSNS (1); \
|
||||
case PLUS: \
|
||||
if (CONST_OK_FOR_I (INTVAL (X))) \
|
||||
return 0; \
|
||||
if (CONST_OK_FOR_J (INTVAL (X))) \
|
||||
return 1; \
|
||||
return COSTS_N_INSNS (1); \
|
||||
default: \
|
||||
if (CONST_OK_FOR_K (INTVAL (X)) || CONST_OK_FOR_L (INTVAL (X))) \
|
||||
return 0; \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} \
|
||||
case CONST_DOUBLE: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case CONST: \
|
||||
case SYMBOL_REF: \
|
||||
case LABEL_REF: \
|
||||
return COSTS_N_INSNS (3);
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. */
|
||||
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MULT: \
|
||||
/* For multiplies wider than HImode, we have to go to the FPU, \
|
||||
which normally involves copies. Plus there's the latency \
|
||||
of the multiply itself, and the latency of the instructions to \
|
||||
transfer integer regs to FP regs. */ \
|
||||
if (GET_MODE_SIZE (GET_MODE (X)) > 2) \
|
||||
return COSTS_N_INSNS (10); \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
/* We make divide expensive, so that divide-by-constant will be \
|
||||
optimized to a multiply. */ \
|
||||
return COSTS_N_INSNS (60);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains ADDRESS.
|
||||
If not defined, the cost is computed from the ADDRESS expression and the
|
||||
`CONST_COSTS' values. */
|
||||
|
|
|
@ -43,7 +43,6 @@ extern int ip2k_address_cost PARAMS ((rtx));
|
|||
extern int ip2k_extra_constraint PARAMS ((rtx, int));
|
||||
extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode, rtx));
|
||||
extern int adjust_insn_length PARAMS ((rtx insn, int len));
|
||||
extern int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
extern void asm_output_char PARAMS ((FILE *, rtx));
|
||||
extern void asm_output_short PARAMS ((FILE *, rtx));
|
||||
extern void asm_output_byte PARAMS ((FILE *, int));
|
||||
|
|
|
@ -78,6 +78,8 @@ static tree ip2k_handle_progmem_attribute PARAMS ((tree *, tree, tree, int,
|
|||
bool *));
|
||||
static tree ip2k_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int,
|
||||
bool *));
|
||||
static bool ip2k_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
const struct attribute_spec ip2k_attribute_table[];
|
||||
|
||||
|
||||
|
@ -100,6 +102,9 @@ const struct attribute_spec ip2k_attribute_table[];
|
|||
#undef TARGET_ATTRIBUTE_TABLE
|
||||
#define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS ip2k_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Commands in the functions prologues in the compiled file. */
|
||||
|
@ -3273,23 +3278,34 @@ asm_file_end (file)
|
|||
|
||||
/* Cost functions. */
|
||||
|
||||
/* Calculate the cost of X code of the expression in which it is contained,
|
||||
found in OUTER_CODE. */
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
int
|
||||
default_rtx_costs (x, code, outer_code)
|
||||
static bool
|
||||
ip2k_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
enum rtx_code code;
|
||||
enum rtx_code outer_code;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
int extra_cost = 0;
|
||||
int total;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
case CONST_DOUBLE:
|
||||
case LABEL_REF:
|
||||
*total = 0;
|
||||
return true;
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
return ip2k_address_cost (XEXP (x, 0));
|
||||
*total = ip2k_address_cost (XEXP (x, 0));
|
||||
return true;
|
||||
|
||||
case ROTATE:
|
||||
case ROTATERT:
|
||||
|
@ -3311,45 +3327,47 @@ default_rtx_costs (x, code, outer_code)
|
|||
/* Sign-preserving shifts require 2 extra instructions. */
|
||||
if (code == ASHIFT)
|
||||
cost += COSTS_N_INSNS (2);
|
||||
return cost;
|
||||
|
||||
*total = cost;
|
||||
return true;
|
||||
}
|
||||
total = rtx_cost (XEXP (x, 0), code);
|
||||
total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8);
|
||||
return total;
|
||||
*total = rtx_cost (XEXP (x, 0), code);
|
||||
*total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8);
|
||||
return true;
|
||||
|
||||
case MINUS:
|
||||
case PLUS:
|
||||
case AND:
|
||||
case XOR:
|
||||
case IOR:
|
||||
total = rtx_cost (XEXP (x, 0), code)
|
||||
+ rtx_cost (XEXP (x, 1), code);
|
||||
total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3);
|
||||
return total;
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3);
|
||||
return false;
|
||||
|
||||
case MOD:
|
||||
case DIV:
|
||||
if (mode == QImode)
|
||||
return COSTS_N_INSNS (20);
|
||||
if (mode == HImode)
|
||||
return COSTS_N_INSNS (60);
|
||||
*total = COSTS_N_INSNS (20);
|
||||
else if (mode == HImode)
|
||||
*total = COSTS_N_INSNS (60);
|
||||
else if (mode == SImode)
|
||||
return COSTS_N_INSNS (180);
|
||||
*total = COSTS_N_INSNS (180);
|
||||
else
|
||||
return COSTS_N_INSNS (540);
|
||||
*total = COSTS_N_INSNS (540);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
/* These costs are OK, but should really handle subtle cases
|
||||
where we're using sign or zero extended args as these are
|
||||
*much* cheaper than those given below! */
|
||||
if (mode == QImode)
|
||||
return COSTS_N_INSNS (4);
|
||||
if (mode == HImode)
|
||||
return COSTS_N_INSNS (12);
|
||||
if (mode == SImode)
|
||||
return COSTS_N_INSNS (36);
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else if (mode == HImode)
|
||||
*total = COSTS_N_INSNS (12);
|
||||
else if (mode == SImode)
|
||||
*total = COSTS_N_INSNS (36);
|
||||
else
|
||||
return COSTS_N_INSNS (108);
|
||||
*total = COSTS_N_INSNS (108);
|
||||
return true;
|
||||
|
||||
case NEG:
|
||||
case SIGN_EXTEND:
|
||||
|
@ -3359,20 +3377,25 @@ default_rtx_costs (x, code, outer_code)
|
|||
case NOT:
|
||||
case COMPARE:
|
||||
case ABS:
|
||||
total = rtx_cost (XEXP (x, 0), code);
|
||||
return total + extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2);
|
||||
*total = extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2);
|
||||
return false;
|
||||
|
||||
case TRUNCATE:
|
||||
case ZERO_EXTEND:
|
||||
if (outer_code == SET)
|
||||
return rtx_cost (XEXP (x, 0), code)
|
||||
+ COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2);
|
||||
{
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2);
|
||||
{
|
||||
*total = -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
return rtx_cost (XEXP (x, 0), code)
|
||||
+ COSTS_N_INSNS (2);
|
||||
*total = rtx_cost (XEXP (x, 0), code) + COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case EQ:
|
||||
case NE:
|
||||
|
@ -3384,11 +3407,12 @@ default_rtx_costs (x, code, outer_code)
|
|||
case GT:
|
||||
case LE:
|
||||
case GE:
|
||||
return rtx_cost (XEXP (x, 0), code)
|
||||
+ rtx_cost (XEXP (x, 1), code);
|
||||
*total = 0;
|
||||
return false;
|
||||
|
||||
default:
|
||||
return COSTS_N_INSNS (4);
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1765,44 +1765,6 @@ do { \
|
|||
is a suitable definition for this macro on machines where anything
|
||||
`CONSTANT_P' is valid. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
return 0; \
|
||||
case CONST: \
|
||||
return 8; \
|
||||
case LABEL_REF: \
|
||||
return 0; \
|
||||
case SYMBOL_REF: \
|
||||
return 8; \
|
||||
case CONST_DOUBLE: \
|
||||
return 0;
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain `case' labels for
|
||||
expression codes `const_int', `const', `symbol_ref', `label_ref'
|
||||
and `const_double'. Each case must ultimately reach a `return'
|
||||
statement to return the relative cost of the use of that kind of
|
||||
constant value in an expression. The cost may depend on the
|
||||
precise value of the constant, which is available for examination
|
||||
in X, and the rtx code of the expression in which it is contained,
|
||||
found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
|
||||
#define DEFAULT_RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
return default_rtx_costs ((X), (CODE), (OUTER_CODE))
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
`COSTS_N_INSNS (N)' to specify a cost equal to N fast
|
||||
instructions. OUTER_CODE is the code of the expression in which X
|
||||
is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost
|
||||
assumptions are adequate for the target machine. */
|
||||
|
||||
#define ADDRESS_COST(ADDRESS) ip2k_address_cost (ADDRESS)
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
|
|
|
@ -80,6 +80,7 @@ static void m32r_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
|
|||
static void m32r_encode_section_info PARAMS ((tree, int));
|
||||
static const char *m32r_strip_name_encoding PARAMS ((const char *));
|
||||
static void init_idents PARAMS ((void));
|
||||
static bool m32r_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ATTRIBUTE_TABLE
|
||||
|
@ -113,6 +114,9 @@ static void init_idents PARAMS ((void));
|
|||
#undef TARGET_STRIP_NAME_ENCODING
|
||||
#define TARGET_STRIP_NAME_ENCODING m32r_strip_name_encoding
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS m32r_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Called by OVERRIDE_OPTIONS to initialize various things. */
|
||||
|
@ -1751,6 +1755,56 @@ m32r_variable_issue (stream, verbose, insn, how_many)
|
|||
|
||||
/* Cost functions. */
|
||||
|
||||
static bool
|
||||
m32r_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* Small integers are as cheap as registers. 4 byte values can be
|
||||
fetched as immediate constants - let's give that the cost of an
|
||||
extra insn. */
|
||||
case CONST_INT:
|
||||
if (INT16_P (INTVAL (x)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
rtx high, low;
|
||||
split_double (x, &high, &low);
|
||||
*total = COSTS_N_INSNS (!INT16_P (INTVAL (high))
|
||||
+ !INT16_P (INTVAL (low)));
|
||||
return true;
|
||||
}
|
||||
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (10);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide the costs of an addressing mode that contains ADDR.
|
||||
If ADDR is not a valid address, its cost is irrelevant.
|
||||
|
||||
|
|
|
@ -1420,36 +1420,6 @@ do { \
|
|||
|
||||
/* Costs. */
|
||||
|
||||
/* ??? I'm quite sure I don't understand enough of the subtleties involved
|
||||
in choosing the right numbers to use here, but there doesn't seem to be
|
||||
enough documentation on this. What I've done is define an insn to cost
|
||||
4 "units" and work from there. COSTS_N_INSNS (N) is defined as (N) * 4 - 2
|
||||
so that seems reasonable. Some values are supposed to be defined relative
|
||||
to each other and thus aren't necessarily related to COSTS_N_INSNS. */
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
/* Small integers are as cheap as registers. 4 byte values can be fetched
|
||||
as immediate constants - let's give that the cost of an extra insn. */
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT : \
|
||||
if (INT16_P (INTVAL (X))) \
|
||||
return 0; \
|
||||
/* fall through */ \
|
||||
case CONST : \
|
||||
case LABEL_REF : \
|
||||
case SYMBOL_REF : \
|
||||
return 4; \
|
||||
case CONST_DOUBLE : \
|
||||
{ \
|
||||
rtx high, low; \
|
||||
split_double (X, &high, &low); \
|
||||
return 4 * (!INT16_P (INTVAL (high)) \
|
||||
+ !INT16_P (INTVAL (low))); \
|
||||
}
|
||||
|
||||
/* Compute the cost of an address. */
|
||||
#define ADDRESS_COST(ADDR) m32r_address_cost (ADDR)
|
||||
|
||||
|
@ -1469,21 +1439,6 @@ do { \
|
|||
we define this as 1. Defining it as 2 had a heavy hit in fp-bit.c. */
|
||||
#define BRANCH_COST ((TARGET_BRANCH_COST) ? 2 : 1)
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. The purpose for the cost of MULT is to encourage
|
||||
`synth_mult' to find a synthetic multiply when reasonable.
|
||||
|
||||
If we need more than 12 insns to do a multiply, then go out-of-line,
|
||||
since the call overhead will be < 10% of the cost of the multiply. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MULT : \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case DIV : \
|
||||
case UDIV : \
|
||||
case MOD : \
|
||||
case UMOD : \
|
||||
return COSTS_N_INSNS (10);
|
||||
|
||||
/* Nonzero if access to memory by bytes is slow and undesirable.
|
||||
For RISC chips, it means that access to memory by bytes is no
|
||||
better than access by words when possible, so grab a whole word
|
||||
|
|
|
@ -89,7 +89,6 @@ extern int m68hc11_memory_move_cost PARAMS((enum machine_mode, enum reg_class,
|
|||
int));
|
||||
extern int m68hc11_register_move_cost PARAMS((enum machine_mode,
|
||||
enum reg_class, enum reg_class));
|
||||
extern int m68hc11_rtx_costs PARAMS((rtx, enum rtx_code, enum rtx_code));
|
||||
extern int m68hc11_address_cost PARAMS((rtx));
|
||||
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ static int register_indirect_p PARAMS((rtx, enum machine_mode, int));
|
|||
static rtx m68hc11_expand_compare PARAMS((enum rtx_code, rtx, rtx));
|
||||
static int must_parenthesize PARAMS ((rtx));
|
||||
static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
|
||||
static int m68hc11_rtx_costs_1 PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
static bool m68hc11_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
static int m68hc11_auto_inc_p PARAMS ((rtx));
|
||||
static tree m68hc11_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));
|
||||
const struct attribute_spec m68hc11_attribute_table[];
|
||||
|
@ -229,6 +231,9 @@ static int nb_soft_regs;
|
|||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO m68hc11_encode_section_info
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS m68hc11_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
int
|
||||
|
@ -5335,8 +5340,8 @@ m68hc11_shift_cost (mode, x, shift)
|
|||
return total;
|
||||
}
|
||||
|
||||
int
|
||||
m68hc11_rtx_costs (x, code, outer_code)
|
||||
static int
|
||||
m68hc11_rtx_costs_1 (x, code, outer_code)
|
||||
rtx x;
|
||||
enum rtx_code code;
|
||||
enum rtx_code outer_code ATTRIBUTE_UNUSED;
|
||||
|
@ -5470,6 +5475,63 @@ m68hc11_rtx_costs (x, code, outer_code)
|
|||
return COSTS_N_INSNS (4);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
m68hc11_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* Constants are cheap. Moving them in registers must be avoided
|
||||
because most instructions do not handle two register operands. */
|
||||
case CONST_INT:
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST_DOUBLE:
|
||||
/* Logical and arithmetic operations with a constant operand are
|
||||
better because they are not supported with two registers. */
|
||||
/* 'clr' is slow */
|
||||
if (outer_code == SET && x == const0_rtx)
|
||||
/* After reload, the reload_cse pass checks the cost to change
|
||||
a SET into a PLUS. Make const0 cheap then. */
|
||||
*total = 1 - reload_completed;
|
||||
else
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
if (outer_code == SET)
|
||||
*total = 1 - reload_completed;
|
||||
|
||||
case ROTATE:
|
||||
case ROTATERT:
|
||||
case ASHIFT:
|
||||
case LSHIFTRT:
|
||||
case ASHIFTRT:
|
||||
case MINUS:
|
||||
case PLUS:
|
||||
case AND:
|
||||
case XOR:
|
||||
case IOR:
|
||||
case UDIV:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case MULT:
|
||||
case NEG:
|
||||
case SIGN_EXTEND:
|
||||
case NOT:
|
||||
case COMPARE:
|
||||
case ZERO_EXTEND:
|
||||
case IF_THEN_ELSE:
|
||||
*total = m68hc11_rtx_costs_1 (x, code, outer_code);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* print_options - called at the start of the code generation for a
|
||||
|
|
|
@ -1391,60 +1391,8 @@ extern unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
|
|||
#define NOTICE_UPDATE_CC(EXP, INSN) \
|
||||
m68hc11_notice_update_cc ((EXP), (INSN))
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX whose rtx-code
|
||||
is CODE. The body of this macro is a portion of a switch statement. If
|
||||
the code is computed here, return it with a return statement. Otherwise,
|
||||
break from the switch.
|
||||
|
||||
Constants are cheap. Moving them in registers must be avoided
|
||||
because most instructions do not handle two register operands. */
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
/* Logical and arithmetic operations with a constant */ \
|
||||
/* operand are better because they are not supported */ \
|
||||
/* with two registers. */ \
|
||||
/* 'clr' is slow */ \
|
||||
if ((OUTER_CODE) == SET && (RTX) == const0_rtx) \
|
||||
/* After reload, the reload_cse pass checks the cost */ \
|
||||
/* to change a SET into a PLUS. Make const0 cheap. */ \
|
||||
return 1 - reload_completed; \
|
||||
else \
|
||||
return 0; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
if ((OUTER_CODE) == SET) \
|
||||
return 1 - reload_completed; \
|
||||
return 0; \
|
||||
case CONST_DOUBLE: \
|
||||
return 0;
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case ROTATE: \
|
||||
case ROTATERT: \
|
||||
case ASHIFT: \
|
||||
case LSHIFTRT: \
|
||||
case ASHIFTRT: \
|
||||
case MINUS: \
|
||||
case PLUS: \
|
||||
case AND: \
|
||||
case XOR: \
|
||||
case IOR: \
|
||||
case UDIV: \
|
||||
case DIV: \
|
||||
case MOD: \
|
||||
case MULT: \
|
||||
case NEG: \
|
||||
case SIGN_EXTEND: \
|
||||
case NOT: \
|
||||
case COMPARE: \
|
||||
case ZERO_EXTEND: \
|
||||
case IF_THEN_ELSE: \
|
||||
return m68hc11_rtx_costs (X, CODE, OUTER_CODE);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
ADDRESS. If not defined, the cost is computed from the ADDRESS
|
||||
expression and the `CONST_COSTS' values. */
|
||||
ADDRESS. */
|
||||
|
||||
#define ADDRESS_COST(RTX) m68hc11_address_cost (RTX)
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ extern int strict_low_part_peephole_ok PARAMS ((enum machine_mode, rtx, rtx));
|
|||
|
||||
/* Functions from m68k.c used in macros. */
|
||||
extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int const_int_cost PARAMS ((rtx));
|
||||
extern int standard_68881_constant_p PARAMS ((rtx));
|
||||
extern int standard_sun_fpa_constant_p PARAMS ((rtx));
|
||||
extern void print_operand_address PARAMS ((FILE *, rtx));
|
||||
|
|
|
@ -73,6 +73,8 @@ static void m68k_hp320_internal_label PARAMS ((FILE *, const char *, unsigned lo
|
|||
static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree));
|
||||
static int m68k_save_reg PARAMS ((unsigned int));
|
||||
static int const_int_cost PARAMS ((rtx));
|
||||
static bool m68k_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
|
||||
/* Alignment to use for loops and jumps */
|
||||
|
@ -139,6 +141,9 @@ int m68k_last_compare_had_fp_operands;
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS m68k_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
|
@ -1708,7 +1713,7 @@ const_method (constant)
|
|||
return MOVL;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
const_int_cost (constant)
|
||||
rtx constant;
|
||||
{
|
||||
|
@ -1730,6 +1735,125 @@ const_int_cost (constant)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
m68k_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
/* Constant zero is super cheap due to clr instruction. */
|
||||
if (x == const0_rtx)
|
||||
*total = 0;
|
||||
else
|
||||
*total = const_int_cost (x);
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 3;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
/* Make 0.0 cheaper than other floating constants to
|
||||
encourage creating tstsf and tstdf insns. */
|
||||
if (outer_code == COMPARE
|
||||
&& (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
|
||||
*total = 4;
|
||||
else
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
/* These are vaguely right for a 68020. */
|
||||
/* The costs for long multiply have been adjusted to work properly
|
||||
in synth_mult on the 68020, relative to an average of the time
|
||||
for add and the time for shift, taking away a little more because
|
||||
sometimes move insns are needed. */
|
||||
/* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms. */
|
||||
#define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : 13)
|
||||
#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5)
|
||||
#define DIVW_COST (TARGET_68020 ? 27 : 12)
|
||||
|
||||
case PLUS:
|
||||
/* An lea costs about three times as much as a simple add. */
|
||||
if (GET_MODE (x) == SImode
|
||||
&& GET_CODE (XEXP (x, 1)) == REG
|
||||
&& GET_CODE (XEXP (x, 0)) == MULT
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
|
||||
&& (INTVAL (XEXP (XEXP (x, 0), 1)) == 2
|
||||
|| INTVAL (XEXP (XEXP (x, 0), 1)) == 4
|
||||
|| INTVAL (XEXP (XEXP (x, 0), 1)) == 8))
|
||||
*total = COSTS_N_INSNS (3); /* lea an@(dx:l:i),am */
|
||||
return false;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
if (TARGET_68060)
|
||||
{
|
||||
*total = COSTS_N_INSNS(1);
|
||||
return true;
|
||||
}
|
||||
if (! TARGET_68020)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
if (INTVAL (XEXP (x, 1)) < 16)
|
||||
*total = COSTS_N_INSNS (2) + INTVAL (XEXP (x, 1)) / 2;
|
||||
else
|
||||
/* We're using clrw + swap for these cases. */
|
||||
*total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / 2;
|
||||
}
|
||||
else
|
||||
*total = COSTS_N_INSNS (10); /* worst case */
|
||||
return true;
|
||||
}
|
||||
/* A shift by a big integer takes an extra instruction. */
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& (INTVAL (XEXP (x, 1)) == 16))
|
||||
{
|
||||
*total = COSTS_N_INSNS (2); /* clrw;swap */
|
||||
return true;
|
||||
}
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& !(INTVAL (XEXP (x, 1)) > 0
|
||||
&& INTVAL (XEXP (x, 1)) <= 8))
|
||||
{
|
||||
*total = COSTS_N_INSNS (3); /* lsr #i,dn */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case MULT:
|
||||
if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
|
||||
|| GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
|
||||
&& GET_MODE (x) == SImode)
|
||||
*total = COSTS_N_INSNS (MULW_COST);
|
||||
else if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
|
||||
*total = COSTS_N_INSNS (MULW_COST);
|
||||
else
|
||||
*total = COSTS_N_INSNS (MULL_COST);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
|
||||
*total = COSTS_N_INSNS (DIVW_COST); /* div.w */
|
||||
else
|
||||
*total = COSTS_N_INSNS (43); /* div.l */
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
output_move_const_into_data_reg (operands)
|
||||
rtx *operands;
|
||||
|
|
|
@ -1520,96 +1520,6 @@ __transfer_from_trampoline () \
|
|||
so give the MEM rtx a byte's mode. */
|
||||
#define FUNCTION_MODE QImode
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
/* Constant zero is super cheap due to clr instruction. */ \
|
||||
if (RTX == const0_rtx) return 0; \
|
||||
/* if ((OUTER_CODE) == SET) */ \
|
||||
return const_int_cost(RTX); \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 3; \
|
||||
case CONST_DOUBLE: \
|
||||
/* Make 0.0 cheaper than other floating constants to \
|
||||
encourage creating tstsf and tstdf insns. */ \
|
||||
if ((OUTER_CODE) == COMPARE \
|
||||
&& ((RTX) == CONST0_RTX (SFmode) \
|
||||
|| (RTX) == CONST0_RTX (DFmode))) \
|
||||
return 4; \
|
||||
return 5;
|
||||
|
||||
/* Compute the cost of various arithmetic operations.
|
||||
These are vaguely right for a 68020. */
|
||||
/* The costs for long multiply have been adjusted to
|
||||
work properly in synth_mult on the 68020,
|
||||
relative to an average of the time for add and the time for shift,
|
||||
taking away a little more because sometimes move insns are needed. */
|
||||
/* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms. */
|
||||
#define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : 13)
|
||||
#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5)
|
||||
#define DIVW_COST (TARGET_68020 ? 27 : 12)
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case PLUS: \
|
||||
/* An lea costs about three times as much as a simple add. */ \
|
||||
if (GET_MODE (X) == SImode \
|
||||
&& GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& GET_CODE (XEXP (X, 0)) == MULT \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& (INTVAL (XEXP (XEXP (X, 0), 1)) == 2 \
|
||||
|| INTVAL (XEXP (XEXP (X, 0), 1)) == 4 \
|
||||
|| INTVAL (XEXP (XEXP (X, 0), 1)) == 8)) \
|
||||
return COSTS_N_INSNS (3); /* lea an@(dx:l:i),am */ \
|
||||
break; \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
if (TARGET_68060) \
|
||||
return COSTS_N_INSNS(1); \
|
||||
if (! TARGET_68020) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
if (INTVAL (XEXP (X, 1)) < 16) \
|
||||
return COSTS_N_INSNS (2) + INTVAL (XEXP (X, 1)) / 2; \
|
||||
else \
|
||||
/* We're using clrw + swap for these cases. */ \
|
||||
return COSTS_N_INSNS (4) + (INTVAL (XEXP (X, 1)) - 16) / 2; \
|
||||
} \
|
||||
return COSTS_N_INSNS (10); /* worst case */ \
|
||||
} \
|
||||
/* A shift by a big integer takes an extra instruction. */ \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& (INTVAL (XEXP (X, 1)) == 16)) \
|
||||
return COSTS_N_INSNS (2); /* clrw;swap */ \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& !(INTVAL (XEXP (X, 1)) > 0 \
|
||||
&& INTVAL (XEXP (X, 1)) <= 8)) \
|
||||
return COSTS_N_INSNS (3); /* lsr #i,dn */ \
|
||||
break; \
|
||||
case MULT: \
|
||||
if ((GET_CODE (XEXP (X, 0)) == ZERO_EXTEND \
|
||||
|| GET_CODE (XEXP (X, 0)) == SIGN_EXTEND) \
|
||||
&& GET_MODE (X) == SImode) \
|
||||
return COSTS_N_INSNS (MULW_COST); \
|
||||
if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
|
||||
return COSTS_N_INSNS (MULW_COST); \
|
||||
else \
|
||||
return COSTS_N_INSNS (MULL_COST); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
|
||||
return COSTS_N_INSNS (DIVW_COST); /* div.w */ \
|
||||
return COSTS_N_INSNS (43); /* div.l */
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ static void m88k_encode_section_info PARAMS ((tree, int));
|
|||
#ifdef AS_BUG_DOT_LABELS
|
||||
static void m88k_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
||||
#endif
|
||||
static bool m88k_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_BYTE_OP
|
||||
|
@ -111,6 +112,9 @@ static void m88k_internal_label PARAMS ((FILE *, const char *, unsigned long));
|
|||
#define TARGET_ASM_INTERNAL_LABEL m88k_internal_label
|
||||
#endif
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS m88k_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Determine what instructions are needed to manufacture the integer VALUE
|
||||
|
@ -3362,3 +3366,66 @@ m88k_internal_label (stream, prefix, labelno)
|
|||
prefix, labelno, INTERNAL_ASM_OP, prefix, labelno);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
m88k_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* We assume that any 16 bit integer can easily be recreated, so we
|
||||
indicate 0 cost, in an attempt to get GCC not to optimize things
|
||||
like comparison against a constant. */
|
||||
case CONST_INT:
|
||||
if (SMALL_INT (x))
|
||||
*total = 0;
|
||||
else if (SMALL_INTVAL (- INTVAL (x)))
|
||||
*total = 2;
|
||||
else if (classify_integer (SImode, INTVAL (x)) != m88k_oru_or)
|
||||
*total = 4;
|
||||
else
|
||||
*total = 7;
|
||||
return true;
|
||||
|
||||
case HIGH:
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
if (flag_pic)
|
||||
*total = (flag_pic == 2) ? 11 : 8;
|
||||
else
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
/* The cost of CONST_DOUBLE is zero (if it can be placed in an insn, it
|
||||
is as good as a register; since it can't be placed in any insn, it
|
||||
won't do anything in cse, but it will cause expand_binop to pass the
|
||||
constant to the define_expands). */
|
||||
case CONST_DOUBLE:
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (38);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1504,39 +1504,6 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
|
|||
state with CC_STATUS_INIT for now. */
|
||||
#define CC_STATUS_INIT m88k_volatile_code = '\0'
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch.
|
||||
|
||||
We assume that any 16 bit integer can easily be recreated, so we
|
||||
indicate 0 cost, in an attempt to get GCC not to optimize things
|
||||
like comparison against a constant.
|
||||
|
||||
The cost of CONST_DOUBLE is zero (if it can be placed in an insn, it
|
||||
is as good as a register; since it can't be placed in any insn, it
|
||||
won't do anything in cse, but it will cause expand_binop to pass the
|
||||
constant to the define_expands). */
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (SMALL_INT (RTX)) \
|
||||
return 0; \
|
||||
else if (SMALL_INTVAL (- INTVAL (RTX))) \
|
||||
return 2; \
|
||||
else if (classify_integer (SImode, INTVAL (RTX)) != m88k_oru_or) \
|
||||
return 4; \
|
||||
return 7; \
|
||||
case HIGH: \
|
||||
return 2; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
if (flag_pic) \
|
||||
return (flag_pic == 2) ? 11 : 8; \
|
||||
return 5; \
|
||||
case CONST_DOUBLE: \
|
||||
return 0;
|
||||
|
||||
/* Provide the costs of an addressing mode that contains ADDR.
|
||||
If ADDR is not a valid address, its cost is irrelevant.
|
||||
REG+REG is made slightly more expensive because it might keep
|
||||
|
@ -1549,19 +1516,6 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
|
|||
GET_CODE (ADDR) != PLUS ? 4 : \
|
||||
(REG_P (XEXP (ADDR, 0)) && REG_P (XEXP (ADDR, 1))) ? 2 : 1)
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MEM: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case MULT: \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (38);
|
||||
|
||||
/* 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,CLASS,IN) 4
|
||||
|
|
|
@ -61,9 +61,6 @@ extern int mcore_expand_insv PARAMS ((rtx *));
|
|||
extern int mcore_modify_comparison PARAMS ((RTX_CODE));
|
||||
extern void mcore_expand_block_move PARAMS ((rtx, rtx, rtx *));
|
||||
extern void mcore_dependent_reorg PARAMS ((rtx));
|
||||
extern int mcore_const_costs PARAMS ((rtx, RTX_CODE));
|
||||
extern int mcore_and_cost PARAMS ((rtx));
|
||||
extern int mcore_ior_cost PARAMS ((rtx));
|
||||
extern const char * mcore_output_andn PARAMS ((rtx, rtx *));
|
||||
extern void mcore_print_operand_address PARAMS ((FILE *, rtx));
|
||||
extern void mcore_print_operand PARAMS ((FILE *, rtx, int));
|
||||
|
|
|
@ -141,6 +141,10 @@ static void mcore_asm_named_section PARAMS ((const char *,
|
|||
static void mcore_unique_section PARAMS ((tree, int));
|
||||
static void mcore_encode_section_info PARAMS ((tree, int));
|
||||
static const char *mcore_strip_name_encoding PARAMS ((const char *));
|
||||
static int mcore_const_costs PARAMS ((rtx, RTX_CODE));
|
||||
static int mcore_and_cost PARAMS ((rtx));
|
||||
static int mcore_ior_cost PARAMS ((rtx));
|
||||
static bool mcore_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||
|
@ -164,6 +168,9 @@ static const char *mcore_strip_name_encoding PARAMS ((const char *));
|
|||
#undef TARGET_STRIP_NAME_ENCODING
|
||||
#define TARGET_STRIP_NAME_ENCODING mcore_strip_name_encoding
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS mcore_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Adjust the stack and return the number of bytes taken to do it. */
|
||||
|
@ -368,7 +375,7 @@ mcore_print_operand (stream, x, code)
|
|||
|
||||
/* What does a constant cost ? */
|
||||
|
||||
int
|
||||
static int
|
||||
mcore_const_costs (exp, code)
|
||||
rtx exp;
|
||||
enum rtx_code code;
|
||||
|
@ -399,7 +406,7 @@ mcore_const_costs (exp, code)
|
|||
have been relaxed. We want to ensure that cse will cse relaxed immeds
|
||||
out. Otherwise we'll get bad code (multiple reloads of the same const). */
|
||||
|
||||
int
|
||||
static int
|
||||
mcore_and_cost (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -426,7 +433,7 @@ mcore_and_cost (x)
|
|||
|
||||
/* What does an or cost - see and_cost(). */
|
||||
|
||||
int
|
||||
static int
|
||||
mcore_ior_cost (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -451,6 +458,48 @@ mcore_ior_cost (x)
|
|||
return 5;
|
||||
}
|
||||
|
||||
static bool
|
||||
mcore_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
*total = mcore_const_costs (x, outer_code);
|
||||
return true;
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 5;
|
||||
return true;
|
||||
case CONST_DOUBLE:
|
||||
*total = 10;
|
||||
return true;
|
||||
|
||||
case AND:
|
||||
*total = COSTS_N_INSNS (mcore_and_cost (x));
|
||||
return true;
|
||||
|
||||
case IOR:
|
||||
*total = COSTS_N_INSNS (mcore_ior_cost (x));
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
case FLOAT:
|
||||
case FIX:
|
||||
*total = COSTS_N_INSNS (100);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if a comparison against a constant can be made more efficient
|
||||
by incrementing/decrementing the constant to get one that is more efficient
|
||||
to load. */
|
||||
|
|
|
@ -1004,37 +1004,10 @@ extern const enum reg_class reg_class_from_letter[];
|
|||
#define Pmode SImode
|
||||
#define FUNCTION_MODE Pmode
|
||||
|
||||
/* The relative costs of various types of constants. Note that cse.c defines
|
||||
REG = 1, SUBREG = 2, any node = (2 + sum of subnodes). */
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
return mcore_const_costs (RTX, OUTER_CODE); \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 5; \
|
||||
case CONST_DOUBLE: \
|
||||
return 10;
|
||||
|
||||
/* provide the cost for an address calculation.
|
||||
All addressing modes cost the same on the MCore. */
|
||||
#define ADDRESS_COST(RTX) 1
|
||||
|
||||
/* Provide the cost of an rtl expression. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case AND: \
|
||||
return COSTS_N_INSNS (mcore_and_cost (X)); \
|
||||
case IOR: \
|
||||
return COSTS_N_INSNS (mcore_ior_cost (X)); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (100); \
|
||||
case FLOAT: \
|
||||
case FIX: \
|
||||
return 100;
|
||||
|
||||
/* Compute extra cost of moving data between one register class
|
||||
and another. All register moves are cheap. */
|
||||
#define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) 2
|
||||
|
|
|
@ -155,6 +155,8 @@ static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx,
|
|||
unsigned HOST_WIDE_INT));
|
||||
static int mips_use_dfa_pipeline_interface PARAMS ((void));
|
||||
static void mips_encode_section_info PARAMS ((tree, int));
|
||||
static bool mips_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
|
||||
/* Structure to be filled in by compute_frame_size with register
|
||||
save masks, and offsets for the current function. */
|
||||
|
@ -670,6 +672,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
|
|||
|
||||
#undef TARGET_VALID_POINTER_MODE
|
||||
#define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS mips_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -2986,6 +2990,337 @@ mips_move_2words (operands, insn)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
mips_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (! TARGET_MIPS16)
|
||||
{
|
||||
/* Always return 0, since we don't have different sized insns,
|
||||
hence different costs according to Richard Kenner. */
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (outer_code == SET)
|
||||
{
|
||||
if (INTVAL (x) >= 0 && INTVAL (x) < 0x100)
|
||||
*total = 0;
|
||||
else if ((INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
|
||||
|| (INTVAL (x) < 0 && INTVAL (x) > -0x100))
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A PLUS could be an address. We don't want to force an address
|
||||
to use a register, so accept any signed 16 bit value without
|
||||
complaint. */
|
||||
if (outer_code == PLUS
|
||||
&& INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A number between 1 and 8 inclusive is efficient for a shift.
|
||||
Otherwise, we will need an extended instruction. */
|
||||
if (outer_code == ASHIFT || outer_code == ASHIFTRT
|
||||
|| outer_code == LSHIFTRT)
|
||||
{
|
||||
if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
|
||||
*total = 0;
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We can use cmpi for an xor with an unsigned 16 bit value. */
|
||||
if (outer_code == XOR
|
||||
&& INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We may be able to use slt or sltu for a comparison with a
|
||||
signed 16 bit value. (The boundary conditions aren't quite
|
||||
right, but this is just a heuristic anyhow.) */
|
||||
if ((outer_code == LT || outer_code == LE
|
||||
|| outer_code == GE || outer_code == GT
|
||||
|| outer_code == LTU || outer_code == LEU
|
||||
|| outer_code == GEU || outer_code == GTU)
|
||||
&& INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Equality comparisons with 0 are cheap. */
|
||||
if ((outer_code == EQ || outer_code == NE)
|
||||
&& INTVAL (x) == 0)
|
||||
return 0;
|
||||
|
||||
/* Otherwise, work out the cost to load the value into a
|
||||
register. */
|
||||
if (INTVAL (x) >= 0 && INTVAL (x) < 0x100)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if ((INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
|
||||
|| (INTVAL (x) < 0 && INTVAL (x) > -0x100))
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case LABEL_REF:
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
{
|
||||
rtx offset = const0_rtx;
|
||||
rtx symref = eliminate_constant_term (XEXP (x, 0), &offset);
|
||||
|
||||
if (TARGET_MIPS16 && mips16_gp_offset_p (x))
|
||||
{
|
||||
/* Treat this like a signed 16 bit CONST_INT. */
|
||||
if (outer_code == PLUS)
|
||||
*total = 0;
|
||||
else if (outer_code == SET)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GET_CODE (symref) == LABEL_REF)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else if (GET_CODE (symref) != SYMBOL_REF)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYMBOL_REF:
|
||||
*total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
{
|
||||
rtx high, low;
|
||||
if (TARGET_MIPS16)
|
||||
{
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
}
|
||||
|
||||
split_double (x, &high, &low);
|
||||
*total = COSTS_N_INSNS ((high == CONST0_RTX (GET_MODE (high))
|
||||
|| low == CONST0_RTX (GET_MODE (low)))
|
||||
? 2 : 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
case MEM:
|
||||
{
|
||||
int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
|
||||
if (simple_memory_operand (x, mode))
|
||||
*total = COSTS_N_INSNS (num_words);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2*num_words);
|
||||
return true;
|
||||
}
|
||||
|
||||
case FFS:
|
||||
*total = COSTS_N_INSNS (6);
|
||||
return true;
|
||||
|
||||
case NOT:
|
||||
*total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1);
|
||||
return true;
|
||||
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
if (mode == DImode && !TARGET_64BIT)
|
||||
{
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
if (mode == DImode && !TARGET_64BIT)
|
||||
{
|
||||
*total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
? 4 : 12);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case ABS:
|
||||
if (mode == SFmode || mode == DFmode)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
if (mode == SFmode || mode == DFmode)
|
||||
{
|
||||
if (TUNE_MIPS3000 || TUNE_MIPS3900)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else if (TUNE_MIPS6000)
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else
|
||||
*total = COSTS_N_INSNS (6);
|
||||
return true;
|
||||
}
|
||||
if (mode == DImode && !TARGET_64BIT)
|
||||
{
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case NEG:
|
||||
if (mode == DImode && !TARGET_64BIT)
|
||||
{
|
||||
*total = 4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case MULT:
|
||||
if (mode == SFmode)
|
||||
{
|
||||
if (TUNE_MIPS3000
|
||||
|| TUNE_MIPS3900
|
||||
|| TUNE_MIPS5000)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else if (TUNE_MIPS6000
|
||||
|| TUNE_MIPS5400
|
||||
|| TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS (5);
|
||||
else
|
||||
*total = COSTS_N_INSNS (7);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mode == DFmode)
|
||||
{
|
||||
if (TUNE_MIPS3000
|
||||
|| TUNE_MIPS3900
|
||||
|| TUNE_MIPS5000)
|
||||
*total = COSTS_N_INSNS (5);
|
||||
else if (TUNE_MIPS6000
|
||||
|| TUNE_MIPS5400
|
||||
|| TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS (6);
|
||||
else
|
||||
*total = COSTS_N_INSNS (8);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TUNE_MIPS3000)
|
||||
*total = COSTS_N_INSNS (12);
|
||||
else if (TUNE_MIPS3900)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS ((mode == DImode) ? 4 : 3);
|
||||
else if (TUNE_MIPS6000)
|
||||
*total = COSTS_N_INSNS (17);
|
||||
else if (TUNE_MIPS5000)
|
||||
*total = COSTS_N_INSNS (5);
|
||||
else
|
||||
*total = COSTS_N_INSNS (10);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
if (mode == SFmode)
|
||||
{
|
||||
if (TUNE_MIPS3000
|
||||
|| TUNE_MIPS3900)
|
||||
*total = COSTS_N_INSNS (12);
|
||||
else if (TUNE_MIPS6000)
|
||||
*total = COSTS_N_INSNS (15);
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS (30);
|
||||
else
|
||||
*total = COSTS_N_INSNS (23);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mode == DFmode)
|
||||
{
|
||||
if (TUNE_MIPS3000
|
||||
|| TUNE_MIPS3900)
|
||||
*total = COSTS_N_INSNS (19);
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS (59);
|
||||
else if (TUNE_MIPS6000)
|
||||
*total = COSTS_N_INSNS (16);
|
||||
else
|
||||
*total = COSTS_N_INSNS (36);
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case UDIV:
|
||||
case UMOD:
|
||||
if (TUNE_MIPS3000
|
||||
|| TUNE_MIPS3900)
|
||||
*total = COSTS_N_INSNS (35);
|
||||
else if (TUNE_MIPS6000)
|
||||
*total = COSTS_N_INSNS (38);
|
||||
else if (TUNE_MIPS5000)
|
||||
*total = COSTS_N_INSNS (36);
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500)
|
||||
*total = COSTS_N_INSNS ((mode == SImode) ? 42 : 74);
|
||||
else
|
||||
*total = COSTS_N_INSNS (69);
|
||||
return true;
|
||||
|
||||
case SIGN_EXTEND:
|
||||
/* A sign extend from SImode to DImode in 64 bit mode is often
|
||||
zero instructions, because the result can often be used
|
||||
directly by another instruction; we'll call it one. */
|
||||
if (TARGET_64BIT && mode == DImode
|
||||
&& GET_MODE (XEXP (x, 0)) == SImode)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case ZERO_EXTEND:
|
||||
if (TARGET_64BIT && mode == DImode
|
||||
&& GET_MODE (XEXP (x, 0)) == SImode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide the costs of an addressing mode that contains ADDR.
|
||||
If ADDR is not a valid address, its cost is irrelevant. */
|
||||
|
||||
|
|
|
@ -3385,316 +3385,6 @@ typedef struct mips_args {
|
|||
#define FUNCTION_MODE (Pmode == DImode ? DImode : SImode)
|
||||
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative
|
||||
costs of constant RTL expressions. It must contain `case'
|
||||
labels for expression codes `const_int', `const', `symbol_ref',
|
||||
`label_ref' and `const_double'. Each case must ultimately reach
|
||||
a `return' statement to return the relative cost of the use of
|
||||
that kind of constant value in an expression. The cost may
|
||||
depend on the precise value of the constant, which is available
|
||||
for examination in X.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
|
||||
#define CONST_COSTS(X,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (! TARGET_MIPS16) \
|
||||
{ \
|
||||
/* Always return 0, since we don't have different sized \
|
||||
instructions, hence different costs according to Richard \
|
||||
Kenner */ \
|
||||
return 0; \
|
||||
} \
|
||||
if ((OUTER_CODE) == SET) \
|
||||
{ \
|
||||
if (INTVAL (X) >= 0 && INTVAL (X) < 0x100) \
|
||||
return 0; \
|
||||
else if ((INTVAL (X) >= 0 && INTVAL (X) < 0x10000) \
|
||||
|| (INTVAL (X) < 0 && INTVAL (X) > -0x100)) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else \
|
||||
return COSTS_N_INSNS (2); \
|
||||
} \
|
||||
/* A PLUS could be an address. We don't want to force an address \
|
||||
to use a register, so accept any signed 16 bit value without \
|
||||
complaint. */ \
|
||||
if ((OUTER_CODE) == PLUS \
|
||||
&& INTVAL (X) >= -0x8000 && INTVAL (X) < 0x8000) \
|
||||
return 0; \
|
||||
/* A number between 1 and 8 inclusive is efficient for a shift. \
|
||||
Otherwise, we will need an extended instruction. */ \
|
||||
if ((OUTER_CODE) == ASHIFT || (OUTER_CODE) == ASHIFTRT \
|
||||
|| (OUTER_CODE) == LSHIFTRT) \
|
||||
{ \
|
||||
if (INTVAL (X) >= 1 && INTVAL (X) <= 8) \
|
||||
return 0; \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} \
|
||||
/* We can use cmpi for an xor with an unsigned 16 bit value. */ \
|
||||
if ((OUTER_CODE) == XOR \
|
||||
&& INTVAL (X) >= 0 && INTVAL (X) < 0x10000) \
|
||||
return 0; \
|
||||
/* We may be able to use slt or sltu for a comparison with a \
|
||||
signed 16 bit value. (The boundary conditions aren't quite \
|
||||
right, but this is just a heuristic anyhow.) */ \
|
||||
if (((OUTER_CODE) == LT || (OUTER_CODE) == LE \
|
||||
|| (OUTER_CODE) == GE || (OUTER_CODE) == GT \
|
||||
|| (OUTER_CODE) == LTU || (OUTER_CODE) == LEU \
|
||||
|| (OUTER_CODE) == GEU || (OUTER_CODE) == GTU) \
|
||||
&& INTVAL (X) >= -0x8000 && INTVAL (X) < 0x8000) \
|
||||
return 0; \
|
||||
/* Equality comparisons with 0 are cheap. */ \
|
||||
if (((OUTER_CODE) == EQ || (OUTER_CODE) == NE) \
|
||||
&& INTVAL (X) == 0) \
|
||||
return 0; \
|
||||
\
|
||||
/* Otherwise, work out the cost to load the value into a \
|
||||
register. */ \
|
||||
if (INTVAL (X) >= 0 && INTVAL (X) < 0x100) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else if ((INTVAL (X) >= 0 && INTVAL (X) < 0x10000) \
|
||||
|| (INTVAL (X) < 0 && INTVAL (X) > -0x100)) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (3); \
|
||||
\
|
||||
case LABEL_REF: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
case CONST: \
|
||||
{ \
|
||||
rtx offset = const0_rtx; \
|
||||
rtx symref = eliminate_constant_term (XEXP (X, 0), &offset); \
|
||||
\
|
||||
if (TARGET_MIPS16 && mips16_gp_offset_p (X)) \
|
||||
{ \
|
||||
/* Treat this like a signed 16 bit CONST_INT. */ \
|
||||
if ((OUTER_CODE) == PLUS) \
|
||||
return 0; \
|
||||
else if ((OUTER_CODE) == SET) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else \
|
||||
return COSTS_N_INSNS (2); \
|
||||
} \
|
||||
\
|
||||
if (GET_CODE (symref) == LABEL_REF) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
if (GET_CODE (symref) != SYMBOL_REF) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
\
|
||||
/* let's be paranoid.... */ \
|
||||
if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
return COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2); \
|
||||
} \
|
||||
\
|
||||
case SYMBOL_REF: \
|
||||
return COSTS_N_INSNS (SYMBOL_REF_FLAG (X) ? 1 : 2); \
|
||||
\
|
||||
case CONST_DOUBLE: \
|
||||
{ \
|
||||
rtx high, low; \
|
||||
if (TARGET_MIPS16) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
split_double (X, &high, &low); \
|
||||
return COSTS_N_INSNS ((high == CONST0_RTX (GET_MODE (high)) \
|
||||
|| low == CONST0_RTX (GET_MODE (low))) \
|
||||
? 2 : 4); \
|
||||
}
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
`COSTS_N_INSNS (N)' to specify a cost equal to N fast instructions.
|
||||
|
||||
This macro is optional; do not define it if the default cost
|
||||
assumptions are adequate for the target machine.
|
||||
|
||||
If -mdebugd is used, change the multiply cost to 2, so multiply by
|
||||
a constant isn't converted to a series of shifts. This helps
|
||||
strength reduction, and also makes it easier to identify what the
|
||||
compiler is doing. */
|
||||
|
||||
/* ??? Fix this to be right for the R8000. */
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MEM: \
|
||||
{ \
|
||||
int num_words = (GET_MODE_SIZE (GET_MODE (X)) > UNITS_PER_WORD) ? 2 : 1; \
|
||||
if (simple_memory_operand (X, GET_MODE (X))) \
|
||||
return COSTS_N_INSNS (num_words); \
|
||||
\
|
||||
return COSTS_N_INSNS (2*num_words); \
|
||||
} \
|
||||
\
|
||||
case FFS: \
|
||||
return COSTS_N_INSNS (6); \
|
||||
\
|
||||
case NOT: \
|
||||
return COSTS_N_INSNS ((GET_MODE (X) == DImode && !TARGET_64BIT) ? 2 : 1); \
|
||||
\
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
if (GET_MODE (X) == DImode && !TARGET_64BIT) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
break; \
|
||||
\
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
if (GET_MODE (X) == DImode && !TARGET_64BIT) \
|
||||
return COSTS_N_INSNS ((GET_CODE (XEXP (X, 1)) == CONST_INT) ? 4 : 12); \
|
||||
\
|
||||
break; \
|
||||
\
|
||||
case ABS: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode || xmode == DFmode) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
\
|
||||
return COSTS_N_INSNS (4); \
|
||||
} \
|
||||
\
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode || xmode == DFmode) \
|
||||
{ \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else if (TUNE_MIPS6000) \
|
||||
return COSTS_N_INSNS (3); \
|
||||
else \
|
||||
return COSTS_N_INSNS (6); \
|
||||
} \
|
||||
\
|
||||
if (xmode == DImode && !TARGET_64BIT) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
\
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case NEG: \
|
||||
if (GET_MODE (X) == DImode && !TARGET_64BIT) \
|
||||
return 4; \
|
||||
\
|
||||
break; \
|
||||
\
|
||||
case MULT: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
{ \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900 \
|
||||
|| TUNE_MIPS5000) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
else if (TUNE_MIPS6000 \
|
||||
|| TUNE_MIPS5400 \
|
||||
|| TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS (5); \
|
||||
else \
|
||||
return COSTS_N_INSNS (7); \
|
||||
} \
|
||||
\
|
||||
if (xmode == DFmode) \
|
||||
{ \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900 \
|
||||
|| TUNE_MIPS5000) \
|
||||
return COSTS_N_INSNS (5); \
|
||||
else if (TUNE_MIPS6000 \
|
||||
|| TUNE_MIPS5400 \
|
||||
|| TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS (6); \
|
||||
else \
|
||||
return COSTS_N_INSNS (8); \
|
||||
} \
|
||||
\
|
||||
if (TUNE_MIPS3000) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
else if (TUNE_MIPS3900) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS ((xmode == DImode) ? 4 : 3); \
|
||||
else if (TUNE_MIPS6000) \
|
||||
return COSTS_N_INSNS (17); \
|
||||
else if (TUNE_MIPS5000) \
|
||||
return COSTS_N_INSNS (5); \
|
||||
else \
|
||||
return COSTS_N_INSNS (10); \
|
||||
} \
|
||||
\
|
||||
case DIV: \
|
||||
case MOD: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
{ \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
else if (TUNE_MIPS6000) \
|
||||
return COSTS_N_INSNS (15); \
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS (30); \
|
||||
else \
|
||||
return COSTS_N_INSNS (23); \
|
||||
} \
|
||||
\
|
||||
if (xmode == DFmode) \
|
||||
{ \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900) \
|
||||
return COSTS_N_INSNS (19); \
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS (59); \
|
||||
else if (TUNE_MIPS6000) \
|
||||
return COSTS_N_INSNS (16); \
|
||||
else \
|
||||
return COSTS_N_INSNS (36); \
|
||||
} \
|
||||
} \
|
||||
/* fall through */ \
|
||||
\
|
||||
case UDIV: \
|
||||
case UMOD: \
|
||||
if (TUNE_MIPS3000 \
|
||||
|| TUNE_MIPS3900) \
|
||||
return COSTS_N_INSNS (35); \
|
||||
else if (TUNE_MIPS6000) \
|
||||
return COSTS_N_INSNS (38); \
|
||||
else if (TUNE_MIPS5000) \
|
||||
return COSTS_N_INSNS (36); \
|
||||
else if (TUNE_MIPS5400 || TUNE_MIPS5500) \
|
||||
return COSTS_N_INSNS ((GET_MODE (X) == SImode) ? 42 : 74); \
|
||||
else \
|
||||
return COSTS_N_INSNS (69); \
|
||||
\
|
||||
case SIGN_EXTEND: \
|
||||
/* A sign extend from SImode to DImode in 64 bit mode is often \
|
||||
zero instructions, because the result can often be used \
|
||||
directly by another instruction; we'll call it one. */ \
|
||||
if (TARGET_64BIT && GET_MODE (X) == DImode \
|
||||
&& GET_MODE (XEXP (X, 0)) == SImode) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
else \
|
||||
return COSTS_N_INSNS (2); \
|
||||
\
|
||||
case ZERO_EXTEND: \
|
||||
if (TARGET_64BIT && GET_MODE (X) == DImode \
|
||||
&& GET_MODE (XEXP (X, 0)) == SImode) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else \
|
||||
return COSTS_N_INSNS (1);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that
|
||||
contains ADDRESS. If not defined, the cost is computed from the
|
||||
form of the ADDRESS expression and the `CONST_COSTS' values.
|
||||
|
|
|
@ -109,8 +109,6 @@ extern void mmix_setup_frame_addresses PARAMS ((void));
|
|||
/* Needs to be ifdef:d for sake of enum rtx_code. */
|
||||
extern enum machine_mode mmix_select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
|
||||
extern void mmix_canonicalize_comparison PARAMS ((enum rtx_code *, rtx *, rtx *));
|
||||
extern int mmix_rtx_cost_recalculated
|
||||
PARAMS ((rtx, enum rtx_code, enum rtx_code, int *));
|
||||
extern int mmix_valid_comparison PARAMS ((enum rtx_code, enum machine_mode, rtx));
|
||||
extern rtx mmix_gen_compare_reg PARAMS ((enum rtx_code, rtx, rtx));
|
||||
#endif
|
||||
|
|
|
@ -134,6 +134,8 @@ static void mmix_target_asm_function_epilogue
|
|||
PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void mmix_asm_output_mi_thunk
|
||||
PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
|
||||
static bool mmix_rtx_costs
|
||||
PARAMS ((rtx, int, int, int *));
|
||||
|
||||
|
||||
/* Target structure macros. Listed by node. See `Using and Porting GCC'
|
||||
|
@ -171,6 +173,9 @@ static void mmix_asm_output_mi_thunk
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS mmix_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Functions that are expansions for target macros.
|
||||
|
@ -1189,19 +1194,19 @@ mmix_reversible_cc_mode (mode)
|
|||
return mode != CC_FPmode;
|
||||
}
|
||||
|
||||
/* DEFAULT_RTX_COSTS. */
|
||||
/* TARGET_RTX_COSTS. */
|
||||
|
||||
int
|
||||
mmix_rtx_cost_recalculated (x, code, outer_code, costp)
|
||||
static bool
|
||||
mmix_rtx_costs (x, code, outer_code, total)
|
||||
rtx x ATTRIBUTE_UNUSED;
|
||||
RTX_CODE code ATTRIBUTE_UNUSED;
|
||||
RTX_CODE outer_code ATTRIBUTE_UNUSED;
|
||||
int *costp ATTRIBUTE_UNUSED;
|
||||
int code ATTRIBUTE_UNUSED;
|
||||
int outer_code ATTRIBUTE_UNUSED;
|
||||
int *total ATTRIBUTE_UNUSED;
|
||||
{
|
||||
/* For the time being, this is just a stub and we'll accept the
|
||||
generic calculations, until we can do measurements, at least.
|
||||
Say we did not modify any calculated costs. */
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ADDRESS_COST. */
|
||||
|
|
|
@ -881,15 +881,6 @@ typedef struct { int regs; int lib; } CUMULATIVE_ARGS;
|
|||
|
||||
/* Node: Costs */
|
||||
|
||||
/* This one takes on both the RTX_COSTS and CONST_COSTS tasks. */
|
||||
#define DEFAULT_RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
{ \
|
||||
int mmix_rtx_cost; \
|
||||
if (mmix_rtx_cost_recalculated (X, CODE, OUTER_CODE, \
|
||||
&mmix_rtx_cost)) \
|
||||
return mmix_rtx_cost; \
|
||||
}
|
||||
|
||||
#define ADDRESS_COST(ADDRESS) mmix_address_cost (ADDRESS)
|
||||
|
||||
/* The special registers can only move to and from general regs, and we
|
||||
|
|
|
@ -65,6 +65,7 @@ rtx zero_dreg;
|
|||
rtx zero_areg;
|
||||
|
||||
static void count_tst_insns PARAMS ((int *));
|
||||
static bool mn10200_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Note whether or not we need an out of line epilogue. */
|
||||
static int out_of_line_epilogue;
|
||||
|
@ -73,6 +74,9 @@ static int out_of_line_epilogue;
|
|||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS mn10200_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Indicate this file was compiled by gcc and what optimization
|
||||
|
@ -1600,3 +1604,59 @@ extendpsi_operand (op, mode)
|
|||
&& XEXP (op, 0) == stack_pointer_rtx
|
||||
&& general_operand (XEXP (op, 1), VOIDmode)));
|
||||
}
|
||||
|
||||
static bool
|
||||
mn10200_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
/* Zeros are extremely cheap. */
|
||||
if (INTVAL (x) == 0)
|
||||
*total = 0;
|
||||
/* If it fits in 8 bits, then it's still relatively cheap. */
|
||||
else if (INT_8_BITS (INTVAL (x)))
|
||||
*total = 1;
|
||||
/* This is the "base" cost, includes constants where either the
|
||||
upper or lower 16bits are all zeros. */
|
||||
else if (INT_16_BITS (INTVAL (x))
|
||||
|| (INTVAL (x) & 0xffff) == 0
|
||||
|| (INTVAL (x) & 0xffff0000) == 0)
|
||||
*total = 2;
|
||||
else
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
/* These are more costly than a CONST_INT, but we can relax them,
|
||||
so they're less costly than a CONST_DOUBLE. */
|
||||
*total = 6;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
/* We don't optimize CONST_DOUBLEs well nor do we relax them well,
|
||||
so their cost is very high. */
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
/* ??? This probably needs more work. The definitions below were first
|
||||
taken from the H8 port, then tweaked slightly to improve code density
|
||||
on various sample codes. */
|
||||
case MOD:
|
||||
case DIV:
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = (GET_MODE (x) == SImode ? 20 : 8);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -730,55 +730,10 @@ struct cum_arg { int nbytes; };
|
|||
addresses generally makes code worse due to register pressure. */
|
||||
#define NO_FUNCTION_CSE
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
/* Zeros are extremely cheap. */ \
|
||||
if (INTVAL (RTX) == 0) \
|
||||
return 0; \
|
||||
/* If it fits in 8 bits, then it's still relatively cheap. */ \
|
||||
if (INT_8_BITS (INTVAL (RTX))) \
|
||||
return 1; \
|
||||
/* This is the "base" cost, includes constants where either the \
|
||||
upper or lower 16bits are all zeros. */ \
|
||||
if (INT_16_BITS (INTVAL (RTX)) \
|
||||
|| (INTVAL (RTX) & 0xffff) == 0 \
|
||||
|| (INTVAL (RTX) & 0xffff0000) == 0) \
|
||||
return 2; \
|
||||
return 4; \
|
||||
/* These are more costly than a CONST_INT, but we can relax them, \
|
||||
so they're less costly than a CONST_DOUBLE. */ \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 6; \
|
||||
/* We don't optimize CONST_DOUBLEs well nor do we relax them well, \
|
||||
so their cost is very high. */ \
|
||||
case CONST_DOUBLE: \
|
||||
return 8;
|
||||
|
||||
/* Make moves between different classes more expensive than moves
|
||||
within the same class. */
|
||||
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) (CLASS1 != CLASS2 ? 4 : 2)
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE.
|
||||
|
||||
?!? This probably needs more work. The definitions below were first
|
||||
taken from the H8 port, then tweaked slightly to improve code density
|
||||
on various sample codes. */
|
||||
|
||||
#define RTX_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case MOD: \
|
||||
case DIV: \
|
||||
return 8; \
|
||||
case MULT: \
|
||||
return (GET_MODE (RTX) == SImode ? 20 : 8);
|
||||
|
||||
/* Nonzero if access to memory by bytes or half words is no faster
|
||||
than accessing full words. */
|
||||
#define SLOW_BYTE_ACCESS 1
|
||||
|
|
|
@ -53,11 +53,18 @@ Boston, MA 02111-1307, USA. */
|
|||
+ 4 * regs_ever_live[7] \
|
||||
+ 16 * (regs_ever_live[14] || regs_ever_live[15] \
|
||||
|| regs_ever_live[16] || regs_ever_live[17]))
|
||||
|
||||
|
||||
static bool mn10300_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS mn10300_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
void
|
||||
|
@ -1324,3 +1331,54 @@ mn10300_address_cost (x, unsig)
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
mn10300_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
/* Zeros are extremely cheap. */
|
||||
if (INTVAL (x) == 0 && outer_code == SET)
|
||||
*total = 0;
|
||||
/* If it fits in 8 bits, then it's still relatively cheap. */
|
||||
else if (INT_8_BITS (INTVAL (x)))
|
||||
*total = 1;
|
||||
/* This is the "base" cost, includes constants where either the
|
||||
upper or lower 16bits are all zeros. */
|
||||
else if (INT_16_BITS (INTVAL (x))
|
||||
|| (INTVAL (x) & 0xffff) == 0
|
||||
|| (INTVAL (x) & 0xffff0000) == 0)
|
||||
*total = 2;
|
||||
else
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
/* These are more costly than a CONST_INT, but we can relax them,
|
||||
so they're less costly than a CONST_DOUBLE. */
|
||||
*total = 6;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
/* We don't optimize CONST_DOUBLEs well nor do we relax them well,
|
||||
so their cost is very high. */
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
/* ??? This probably needs more work. */
|
||||
case MOD:
|
||||
case DIV:
|
||||
case MULT:
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -800,37 +800,6 @@ struct cum_arg {int nbytes; };
|
|||
#define CC_NO_CARRY CC_NO_OVERFLOW
|
||||
#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
/* Zeros are extremely cheap. */ \
|
||||
if (INTVAL (RTX) == 0 && OUTER_CODE == SET) \
|
||||
return 0; \
|
||||
/* If it fits in 8 bits, then it's still relatively cheap. */ \
|
||||
if (INT_8_BITS (INTVAL (RTX))) \
|
||||
return 1; \
|
||||
/* This is the "base" cost, includes constants where either the \
|
||||
upper or lower 16bits are all zeros. */ \
|
||||
if (INT_16_BITS (INTVAL (RTX)) \
|
||||
|| (INTVAL (RTX) & 0xffff) == 0 \
|
||||
|| (INTVAL (RTX) & 0xffff0000) == 0) \
|
||||
return 2; \
|
||||
return 4; \
|
||||
/* These are more costly than a CONST_INT, but we can relax them, \
|
||||
so they're less costly than a CONST_DOUBLE. */ \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 6; \
|
||||
/* We don't optimize CONST_DOUBLEs well nor do we relax them well, \
|
||||
so their cost is very high. */ \
|
||||
case CONST_DOUBLE: \
|
||||
return 8;
|
||||
|
||||
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
|
||||
((CLASS1 == CLASS2 && (CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS)) ? 2 :\
|
||||
((CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS) && \
|
||||
|
@ -845,19 +814,6 @@ struct cum_arg {int nbytes; };
|
|||
|
||||
#define ADDRESS_COST(X) mn10300_address_cost((X), 0)
|
||||
|
||||
/* A crude cut at RTX_COSTS for the MN10300. */
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
#define RTX_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case UMOD: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case DIV: \
|
||||
return 8; \
|
||||
case MULT: \
|
||||
return 8;
|
||||
|
||||
/* Nonzero if access to memory by bytes or half words is no faster
|
||||
than accessing full words. */
|
||||
#define SLOW_BYTE_ACCESS 1
|
||||
|
|
|
@ -72,6 +72,7 @@ const struct attribute_spec ns32k_attribute_table[];
|
|||
static void ns32k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void ns32k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void ns32k_encode_section_info PARAMS ((tree, int));
|
||||
static bool ns32k_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ATTRIBUTE_TABLE
|
||||
|
@ -92,6 +93,9 @@ static void ns32k_encode_section_info PARAMS ((tree, int));
|
|||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO ns32k_encode_section_info
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS ns32k_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Generate the assembly code for function entry. FILE is a stdio
|
||||
|
@ -490,6 +494,38 @@ hard_regno_mode_ok (regno, mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
ns32k_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) <= 7 && INTVAL (x) >= -8)
|
||||
*total = 0;
|
||||
else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000)
|
||||
*total = 1;
|
||||
else
|
||||
*total = 3;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 3;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int register_move_cost (CLASS1, CLASS2)
|
||||
enum reg_class CLASS1;
|
||||
enum reg_class CLASS2;
|
||||
|
|
|
@ -1166,22 +1166,6 @@ __transfer_from_trampoline () \
|
|||
|
||||
#define ADDRESS_COST(RTX) calc_address_cost (RTX)
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (RTX) <= 7 && INTVAL (RTX) >= -8) return 0; \
|
||||
if (INTVAL (RTX) < 0x2000 && INTVAL (RTX) >= -0x2000) \
|
||||
return 1; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 3; \
|
||||
case CONST_DOUBLE: \
|
||||
return 5;
|
||||
|
||||
/* Tell final.c how to eliminate redundant test instructions. */
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ hppa_fpstore_bypass_p (out_insn, in_insn)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
static bool hppa_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
static inline rtx force_mode PARAMS ((enum machine_mode, rtx));
|
||||
static void pa_combine_instructions PARAMS ((rtx));
|
||||
static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
|
||||
|
@ -220,6 +221,9 @@ static size_t n_deferred_plabels = 0;
|
|||
#define TARGET_ASM_DESTRUCTOR pa_asm_out_destructor
|
||||
#endif
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS hppa_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
void
|
||||
|
@ -1315,6 +1319,87 @@ hppa_address_cost (X)
|
|||
return 4;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
hppa_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) == 0)
|
||||
*total = 0;
|
||||
else if (INT_14_BITS (x))
|
||||
*total = 1;
|
||||
else
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case HIGH:
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if ((x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode))
|
||||
&& outer_code != SET)
|
||||
*total = 0;
|
||||
else
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
|
||||
*total = COSTS_N_INSNS (8);
|
||||
else
|
||||
*total = COSTS_N_INSNS (20);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
{
|
||||
*total = COSTS_N_INSNS (14);
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (60);
|
||||
return true;
|
||||
|
||||
case PLUS: /* this includes shNadd insns */
|
||||
case MINUS:
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure mode of ORIG, a REG rtx, is MODE. Returns either ORIG or a
|
||||
new rtx with the correct mode. */
|
||||
static inline rtx
|
||||
|
|
|
@ -1595,28 +1595,6 @@ do { \
|
|||
few bits. */
|
||||
#define SHIFT_COUNT_TRUNCATED 1
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (RTX) == 0) return 0; \
|
||||
if (INT_14_BITS (RTX)) return 1; \
|
||||
case HIGH: \
|
||||
return 2; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 4; \
|
||||
case CONST_DOUBLE: \
|
||||
if ((RTX == CONST0_RTX (DFmode) || RTX == CONST0_RTX (SFmode)) \
|
||||
&& OUTER_CODE != SET) \
|
||||
return 0; \
|
||||
else \
|
||||
return 8;
|
||||
|
||||
#define ADDRESS_COST(RTX) \
|
||||
(GET_CODE (RTX) == REG ? 1 : hppa_address_cost (RTX))
|
||||
|
||||
|
@ -1636,34 +1614,6 @@ do { \
|
|||
: FP_REG_CLASS_P (CLASS2) && ! FP_REG_CLASS_P (CLASS1) ? 16 \
|
||||
: 2)
|
||||
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. The purpose for the cost of MULT is to encourage
|
||||
`synth_mult' to find a synthetic multiply when reasonable. */
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MULT: \
|
||||
if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
|
||||
return COSTS_N_INSNS (3); \
|
||||
return (TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) \
|
||||
? COSTS_N_INSNS (8) : COSTS_N_INSNS (20); \
|
||||
case DIV: \
|
||||
if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
|
||||
return COSTS_N_INSNS (14); \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (60); \
|
||||
case PLUS: /* this includes shNadd insns */ \
|
||||
case MINUS: \
|
||||
if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
|
||||
return COSTS_N_INSNS (3); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (1);
|
||||
|
||||
/* Adjust the cost of branches. */
|
||||
#define BRANCH_COST (pa_cpu == PROCESSOR_8000 ? 2 : 1)
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ static const char *singlemove_string PARAMS ((rtx *));
|
|||
static bool pdp11_assemble_integer PARAMS ((rtx, unsigned int, int));
|
||||
static void pdp11_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static bool pdp11_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_BYTE_OP
|
||||
|
@ -80,6 +81,9 @@ static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
#undef TARGET_ASM_CLOSE_PAREN
|
||||
#define TARGET_ASM_CLOSE_PAREN "]"
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS pdp11_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Nonzero if OP is a valid second operand for an arithmetic insn. */
|
||||
|
@ -1015,6 +1019,116 @@ register_move_cost(c1, c2)
|
|||
return move_costs[(int)c1][(int)c2];
|
||||
}
|
||||
|
||||
static bool
|
||||
pdp11_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
/* Twice as expensive as REG. */
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
/* Twice (or 4 times) as expensive as 16 bit. */
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
/* ??? There is something wrong in MULT because MULT is not
|
||||
as cheap as total = 2 even if we can shift! */
|
||||
/* If optimizing for size make mult etc cheap, but not 1, so when
|
||||
in doubt the faster insn is chosen. */
|
||||
if (optimize_size)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (11);
|
||||
return false;
|
||||
|
||||
case DIV:
|
||||
if (optimize_size)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (25);
|
||||
return false;
|
||||
|
||||
case MOD:
|
||||
if (optimize_size)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (26);
|
||||
return false;
|
||||
|
||||
case ABS:
|
||||
/* Equivalent to length, so same for optimize_size. */
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return false;
|
||||
|
||||
case ZERO_EXTEND:
|
||||
/* Only used for qi->hi. */
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
||||
case SIGN_EXTEND:
|
||||
if (GET_MODE (x) == HImode)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if (GET_MODE (x) == SImode)
|
||||
*total = COSTS_N_INSNS (6);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return false;
|
||||
|
||||
case ASHIFT:
|
||||
case LSHIFTRT:
|
||||
case ASHIFTRT:
|
||||
if (optimize_size)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else if (GET_MODE (x) == QImode)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
*total = COSTS_N_INSNS (8); /* worst case */
|
||||
else
|
||||
*total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
|
||||
}
|
||||
else if (GET_MODE (x) == HImode)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
if (abs (INTVAL (XEXP (x, 1))) == 1)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
|
||||
}
|
||||
else
|
||||
*total = COSTS_N_INSNS (10); /* worst case */
|
||||
}
|
||||
else if (GET_MODE (x) == SImode)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
*total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
|
||||
else /* worst case */
|
||||
*total = COSTS_N_INSNS (18);
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
output_jump(pos, neg, length)
|
||||
const char *pos, *neg;
|
||||
|
|
|
@ -934,28 +934,6 @@ extern int may_call_alloca;
|
|||
but a CALL with constant address is cheap. */
|
||||
/* #define NO_FUNCTION_CSE */
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch.
|
||||
|
||||
-1, 0, 1 are cheaper for add, sub ...
|
||||
*/
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL(RTX) == 0 \
|
||||
|| INTVAL(RTX) == -1 \
|
||||
|| INTVAL(RTX) == 1) \
|
||||
return 0; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
/* twice as expensive as REG */ \
|
||||
return 2; \
|
||||
case CONST_DOUBLE: \
|
||||
/* twice (or 4 times) as expensive as 16 bit */ \
|
||||
return 4;
|
||||
|
||||
/* cost of moving one register class to another */
|
||||
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
|
||||
|
@ -1212,89 +1190,6 @@ JMP FUNCTION 0x0058 0x0000 <- FUNCTION
|
|||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE.
|
||||
|
||||
we don't say how expensive SImode is - pretty expensive!!!
|
||||
|
||||
there is something wrong in MULT because MULT is not
|
||||
as cheap as total = 2 even if we can shift!
|
||||
|
||||
if optimizing for size make mult etc cheap, but not 1, so when
|
||||
in doubt the faster insn is chosen.
|
||||
*/
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MULT: \
|
||||
if (optimize_size) \
|
||||
total = COSTS_N_INSNS(2); \
|
||||
else \
|
||||
total = COSTS_N_INSNS (11); \
|
||||
break; \
|
||||
case DIV: \
|
||||
if (optimize_size) \
|
||||
total = COSTS_N_INSNS(2); \
|
||||
else \
|
||||
total = COSTS_N_INSNS (25); \
|
||||
break; \
|
||||
case MOD: \
|
||||
if (optimize_size) \
|
||||
total = COSTS_N_INSNS(2); \
|
||||
else \
|
||||
total = COSTS_N_INSNS (26); \
|
||||
break; \
|
||||
case ABS: \
|
||||
/* equivalent to length, so same for optimize_size */ \
|
||||
total = COSTS_N_INSNS (3); \
|
||||
break; \
|
||||
case ZERO_EXTEND: \
|
||||
/* only used for: qi->hi */ \
|
||||
total = COSTS_N_INSNS(1); \
|
||||
break; \
|
||||
case SIGN_EXTEND: \
|
||||
if (GET_MODE(X) == HImode) \
|
||||
total = COSTS_N_INSNS(1); \
|
||||
else if (GET_MODE(X) == SImode) \
|
||||
total = COSTS_N_INSNS(6); \
|
||||
else \
|
||||
total = COSTS_N_INSNS(2); \
|
||||
break; \
|
||||
/* case LSHIFT: */ \
|
||||
case ASHIFT: \
|
||||
case LSHIFTRT: \
|
||||
case ASHIFTRT: \
|
||||
if (optimize_size) \
|
||||
total = COSTS_N_INSNS(1); \
|
||||
else if (GET_MODE(X) == QImode) \
|
||||
{ \
|
||||
if (GET_CODE(XEXP (X,1)) != CONST_INT) \
|
||||
total = COSTS_N_INSNS(8); /* worst case */ \
|
||||
else \
|
||||
total = COSTS_N_INSNS(INTVAL(XEXP (X,1))); \
|
||||
} \
|
||||
else if (GET_MODE(X) == HImode) \
|
||||
{ \
|
||||
if (GET_CODE(XEXP (X,1)) == CONST_INT) \
|
||||
{ \
|
||||
if (abs (INTVAL (XEXP (X, 1))) == 1) \
|
||||
total = COSTS_N_INSNS(1); \
|
||||
else \
|
||||
total = COSTS_N_INSNS(2.5 + 0.5 *INTVAL(XEXP(X,1))); \
|
||||
} \
|
||||
else /* worst case */ \
|
||||
total = COSTS_N_INSNS (10); \
|
||||
} \
|
||||
else if (GET_MODE(X) == SImode) \
|
||||
{ \
|
||||
if (GET_CODE(XEXP (X,1)) == CONST_INT) \
|
||||
total = COSTS_N_INSNS(2.5 + 0.5 *INTVAL(XEXP(X,1))); \
|
||||
else /* worst case */ \
|
||||
total = COSTS_N_INSNS(18); \
|
||||
} \
|
||||
break;
|
||||
|
||||
|
||||
/* there is no point in avoiding branches on a pdp,
|
||||
since branches are really cheap - I just want to find out
|
||||
how much difference the BRANCH_COST macro makes in code */
|
||||
|
|
|
@ -59,6 +59,7 @@ static void romp_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
|||
static void romp_select_rtx_section PARAMS ((enum machine_mode, rtx,
|
||||
unsigned HOST_WIDE_INT));
|
||||
static void romp_encode_section_info PARAMS ((tree, int));
|
||||
static bool romp_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_FUNCTION_PROLOGUE
|
||||
|
@ -69,6 +70,8 @@ static void romp_encode_section_info PARAMS ((tree, int));
|
|||
#define TARGET_ASM_SELECT_RTX_SECTION romp_select_rtx_section
|
||||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO romp_encode_section_info
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS romp_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -2099,3 +2102,66 @@ romp_encode_section_info (decl, first)
|
|||
if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
|
||||
SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
romp_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case CONST_INT:
|
||||
if ((outer_code == IOR && exact_log2 (INTVAL (x)) >= 0)
|
||||
|| (outer_code == AND && exact_log2 (~INTVAL (x)) >= 0)
|
||||
|| ((outer_code == PLUS || outer_code == MINUS)
|
||||
&& (unsigned HOST_WIDE_INT) (INTVAL (x) + 15) < 31)
|
||||
|| (outer_code == SET && (unsigned HOST_WIDE_INT) INTVAL (x) < 16))
|
||||
*total = 0;
|
||||
else if ((unsigned HOST_WIDE_INT) (INTVAL (x) + 0x8000) < 0x10000
|
||||
|| (INTVAL (x) & 0xffff0000) == 0)
|
||||
*total = 0;
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
if (current_function_operand (x, Pmode))
|
||||
*total = 0;
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (x == CONST0_RTX (GET_MODE (x)))
|
||||
*total = 2;
|
||||
else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
*total = COSTS_N_INSNS (5)
|
||||
else
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
*total = current_function_operand (x, Pmode) ? 0 : COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (TARGET_IN_LINE_MUL && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT)
|
||||
*total = COSTS_N_INSNS (19);
|
||||
else
|
||||
*total = COSTS_N_INSNS (25);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (45);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1162,50 +1162,6 @@ struct rt_cargs {int gregs, fregs; };
|
|||
|
||||
/* #define SHIFT_COUNT_TRUNCATED */
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX whose
|
||||
rtx-code is CODE, contained within an expression of code OUTER_CODE.
|
||||
The body of this macro is a portion of a switch statement. If the
|
||||
code is computed here, return it with a return statement. Otherwise,
|
||||
break from the switch. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (((OUTER_CODE) == IOR && exact_log2 (INTVAL (RTX)) >= 0) \
|
||||
|| ((OUTER_CODE) == AND && exact_log2 (~INTVAL (RTX)) >= 0) \
|
||||
|| (((OUTER_CODE) == PLUS || (OUTER_CODE) == MINUS) \
|
||||
&& (unsigned int) (INTVAL (RTX) + 15) < 31) \
|
||||
|| ((OUTER_CODE) == SET && (unsigned int) INTVAL (RTX) < 16))\
|
||||
return 0; \
|
||||
return ((unsigned int) (INTVAL(RTX) + 0x8000) < 0x10000 \
|
||||
|| (INTVAL (RTX) & 0xffff0000) == 0) ? 0 : COSTS_N_INSNS (2);\
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
if (current_function_operand (RTX, Pmode)) return 0; \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case CONST_DOUBLE: \
|
||||
if ((RTX) == CONST0_RTX (GET_MODE (RTX))) return 2; \
|
||||
return ((GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT) \
|
||||
? COSTS_N_INSNS (5) : COSTS_N_INSNS (4));
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE.
|
||||
|
||||
References to our own data area are really references to r14, so they
|
||||
are very cheap. Multiples and divides are very expensive. */
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case MEM: \
|
||||
return current_function_operand (X, Pmode) ? 0 : COSTS_N_INSNS (2); \
|
||||
case MULT: \
|
||||
return (TARGET_IN_LINE_MUL && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT)\
|
||||
? COSTS_N_INSNS (19) : COSTS_N_INSNS (25); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (45);
|
||||
|
||||
/* Compute the cost of an address. This is meant to approximate the size
|
||||
and/or execution delay of an insn using that address. If the cost is
|
||||
approximated by the RTL complexity, including CONST_COSTS above, as
|
||||
|
|
|
@ -227,6 +227,7 @@ static unsigned int rs6000_xcoff_section_type_flags PARAMS ((tree, const char *,
|
|||
static void rs6000_xcoff_encode_section_info PARAMS ((tree, int))
|
||||
ATTRIBUTE_UNUSED;
|
||||
static bool rs6000_binds_local_p PARAMS ((tree));
|
||||
static bool rs6000_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
static int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
static int rs6000_adjust_priority PARAMS ((rtx, int));
|
||||
static int rs6000_issue_rate PARAMS ((void));
|
||||
|
@ -404,6 +405,9 @@ static const char alt_reg_names[][8] =
|
|||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS rs6000_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Override command line options. Mostly we process the processor
|
||||
|
@ -13230,6 +13234,210 @@ rs6000_binds_local_p (decl)
|
|||
return default_binds_local_p_1 (decl, flag_pic || rs6000_flag_pic);
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
rs6000_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* On the RS/6000, if it is valid in the insn, it is free.
|
||||
So this always returns 0. */
|
||||
case CONST_INT:
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST_DOUBLE:
|
||||
case HIGH:
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
*total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1))
|
||||
+ 0x8000) >= 0x10000)
|
||||
&& ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
|
||||
? COSTS_N_INSNS (2)
|
||||
: COSTS_N_INSNS (1));
|
||||
return true;
|
||||
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
*total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& (INTVAL (XEXP (x, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0
|
||||
&& ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
|
||||
? COSTS_N_INSNS (2)
|
||||
: COSTS_N_INSNS (1));
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (optimize_size)
|
||||
{
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
switch (rs6000_cpu)
|
||||
{
|
||||
case PROCESSOR_RIOS1:
|
||||
case PROCESSOR_PPC405:
|
||||
*total = (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
? COSTS_N_INSNS (5)
|
||||
: (INTVAL (XEXP (x, 1)) >= -256
|
||||
&& INTVAL (XEXP (x, 1)) <= 255)
|
||||
? COSTS_N_INSNS (3) : COSTS_N_INSNS (4));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_RS64A:
|
||||
*total = (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
? GET_MODE (XEXP (x, 1)) != DImode
|
||||
? COSTS_N_INSNS (20) : COSTS_N_INSNS (34)
|
||||
: (INTVAL (XEXP (x, 1)) >= -256
|
||||
&& INTVAL (XEXP (x, 1)) <= 255)
|
||||
? COSTS_N_INSNS (8) : COSTS_N_INSNS (12));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_RIOS2:
|
||||
case PROCESSOR_MPCCORE:
|
||||
case PROCESSOR_PPC604e:
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC601:
|
||||
*total = COSTS_N_INSNS (5);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC603:
|
||||
case PROCESSOR_PPC7400:
|
||||
case PROCESSOR_PPC750:
|
||||
*total = (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
? COSTS_N_INSNS (5)
|
||||
: (INTVAL (XEXP (x, 1)) >= -256
|
||||
&& INTVAL (XEXP (x, 1)) <= 255)
|
||||
? COSTS_N_INSNS (2) : COSTS_N_INSNS (3));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC7450:
|
||||
*total = (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
? COSTS_N_INSNS (4)
|
||||
: COSTS_N_INSNS (3));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC403:
|
||||
case PROCESSOR_PPC604:
|
||||
case PROCESSOR_PPC8540:
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC620:
|
||||
case PROCESSOR_PPC630:
|
||||
case PROCESSOR_POWER4:
|
||||
*total = (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
? GET_MODE (XEXP (x, 1)) != DImode
|
||||
? COSTS_N_INSNS (5) : COSTS_N_INSNS (7)
|
||||
: (INTVAL (XEXP (x, 1)) >= -256
|
||||
&& INTVAL (XEXP (x, 1)) <= 255)
|
||||
? COSTS_N_INSNS (3) : COSTS_N_INSNS (4));
|
||||
return true;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
|
||||
{
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case UDIV:
|
||||
case UMOD:
|
||||
switch (rs6000_cpu)
|
||||
{
|
||||
case PROCESSOR_RIOS1:
|
||||
*total = COSTS_N_INSNS (19);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_RIOS2:
|
||||
*total = COSTS_N_INSNS (13);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_RS64A:
|
||||
*total = (GET_MODE (XEXP (x, 1)) != DImode
|
||||
? COSTS_N_INSNS (65)
|
||||
: COSTS_N_INSNS (67));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_MPCCORE:
|
||||
*total = COSTS_N_INSNS (6);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC403:
|
||||
*total = COSTS_N_INSNS (33);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC405:
|
||||
*total = COSTS_N_INSNS (35);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC601:
|
||||
*total = COSTS_N_INSNS (36);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC603:
|
||||
*total = COSTS_N_INSNS (37);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC604:
|
||||
case PROCESSOR_PPC604e:
|
||||
*total = COSTS_N_INSNS (20);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC620:
|
||||
case PROCESSOR_PPC630:
|
||||
case PROCESSOR_POWER4:
|
||||
*total = (GET_MODE (XEXP (x, 1)) != DImode
|
||||
? COSTS_N_INSNS (21)
|
||||
: COSTS_N_INSNS (37));
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC750:
|
||||
case PROCESSOR_PPC8540:
|
||||
case PROCESSOR_PPC7400:
|
||||
*total = COSTS_N_INSNS (19);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_PPC7450:
|
||||
*total = COSTS_N_INSNS (23);
|
||||
return true;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
case FFS:
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
/* MEM should be slightly more expensive than (plus (reg) (const)) */
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* A C expression returning the cost of moving data from a register of class
|
||||
CLASS1 to one of CLASS2. */
|
||||
|
||||
|
|
|
@ -2291,139 +2291,6 @@ do { \
|
|||
|
||||
#define SHIFT_COUNT_TRUNCATED (TARGET_POWER ? 1 : 0)
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch.
|
||||
|
||||
On the RS/6000, if it is valid in the insn, it is free. So this
|
||||
always returns 0. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
case CONST_DOUBLE: \
|
||||
case HIGH: \
|
||||
return 0;
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
case PLUS: \
|
||||
return ((GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (X, 1)) \
|
||||
+ 0x8000) >= 0x10000) \
|
||||
&& ((INTVAL (XEXP (X, 1)) & 0xffff) != 0)) \
|
||||
? COSTS_N_INSNS (2) \
|
||||
: COSTS_N_INSNS (1)); \
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
return ((GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& (INTVAL (XEXP (X, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0 \
|
||||
&& ((INTVAL (XEXP (X, 1)) & 0xffff) != 0)) \
|
||||
? COSTS_N_INSNS (2) \
|
||||
: COSTS_N_INSNS (1)); \
|
||||
case MULT: \
|
||||
if (optimize_size) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
switch (rs6000_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_RIOS1: \
|
||||
case PROCESSOR_PPC405: \
|
||||
return (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
? COSTS_N_INSNS (5) \
|
||||
: INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
|
||||
? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
|
||||
case PROCESSOR_RS64A: \
|
||||
return (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
? GET_MODE (XEXP (X, 1)) != DImode \
|
||||
? COSTS_N_INSNS (20) : COSTS_N_INSNS (34) \
|
||||
: INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
|
||||
? COSTS_N_INSNS (8) : COSTS_N_INSNS (12)); \
|
||||
case PROCESSOR_RIOS2: \
|
||||
case PROCESSOR_MPCCORE: \
|
||||
case PROCESSOR_PPC604e: \
|
||||
return COSTS_N_INSNS (2); \
|
||||
case PROCESSOR_PPC601: \
|
||||
return COSTS_N_INSNS (5); \
|
||||
case PROCESSOR_PPC603: \
|
||||
case PROCESSOR_PPC7400: \
|
||||
case PROCESSOR_PPC750: \
|
||||
return (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
? COSTS_N_INSNS (5) \
|
||||
: INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
|
||||
? COSTS_N_INSNS (2) : COSTS_N_INSNS (3)); \
|
||||
case PROCESSOR_PPC7450: \
|
||||
return (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
? COSTS_N_INSNS (4) \
|
||||
: COSTS_N_INSNS (3)); \
|
||||
case PROCESSOR_PPC403: \
|
||||
case PROCESSOR_PPC604: \
|
||||
case PROCESSOR_PPC8540: \
|
||||
return COSTS_N_INSNS (4); \
|
||||
case PROCESSOR_PPC620: \
|
||||
case PROCESSOR_PPC630: \
|
||||
case PROCESSOR_POWER4: \
|
||||
return (GET_CODE (XEXP (X, 1)) != CONST_INT \
|
||||
? GET_MODE (XEXP (X, 1)) != DImode \
|
||||
? COSTS_N_INSNS (5) : COSTS_N_INSNS (7) \
|
||||
: INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
|
||||
? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
|
||||
} \
|
||||
case DIV: \
|
||||
case MOD: \
|
||||
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
/* otherwise fall through to normal divide. */ \
|
||||
case UDIV: \
|
||||
case UMOD: \
|
||||
switch (rs6000_cpu) \
|
||||
{ \
|
||||
case PROCESSOR_RIOS1: \
|
||||
return COSTS_N_INSNS (19); \
|
||||
case PROCESSOR_RIOS2: \
|
||||
return COSTS_N_INSNS (13); \
|
||||
case PROCESSOR_RS64A: \
|
||||
return (GET_MODE (XEXP (X, 1)) != DImode \
|
||||
? COSTS_N_INSNS (65) \
|
||||
: COSTS_N_INSNS (67)); \
|
||||
case PROCESSOR_MPCCORE: \
|
||||
return COSTS_N_INSNS (6); \
|
||||
case PROCESSOR_PPC403: \
|
||||
return COSTS_N_INSNS (33); \
|
||||
case PROCESSOR_PPC405: \
|
||||
return COSTS_N_INSNS (35); \
|
||||
case PROCESSOR_PPC601: \
|
||||
return COSTS_N_INSNS (36); \
|
||||
case PROCESSOR_PPC603: \
|
||||
return COSTS_N_INSNS (37); \
|
||||
case PROCESSOR_PPC604: \
|
||||
case PROCESSOR_PPC604e: \
|
||||
return COSTS_N_INSNS (20); \
|
||||
case PROCESSOR_PPC620: \
|
||||
case PROCESSOR_PPC630: \
|
||||
case PROCESSOR_POWER4: \
|
||||
return (GET_MODE (XEXP (X, 1)) != DImode \
|
||||
? COSTS_N_INSNS (21) \
|
||||
: COSTS_N_INSNS (37)); \
|
||||
case PROCESSOR_PPC750: \
|
||||
case PROCESSOR_PPC8540: \
|
||||
case PROCESSOR_PPC7400: \
|
||||
return COSTS_N_INSNS (19); \
|
||||
case PROCESSOR_PPC7450: \
|
||||
return COSTS_N_INSNS (23); \
|
||||
} \
|
||||
case FFS: \
|
||||
return COSTS_N_INSNS (4); \
|
||||
case MEM: \
|
||||
/* MEM should be slightly more expensive than (plus (reg) (const)) */ \
|
||||
return 5;
|
||||
|
||||
/* Compute the cost of an address. This is meant to approximate the size
|
||||
and/or execution delay of an insn using that address. If the cost is
|
||||
approximated by the RTL complexity, including CONST_COSTS above, as
|
||||
|
|
|
@ -66,6 +66,7 @@ static enum attr_type s390_safe_attr_type PARAMS ((rtx));
|
|||
static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
static int s390_issue_rate PARAMS ((void));
|
||||
static int s390_use_dfa_pipeline_interface PARAMS ((void));
|
||||
static bool s390_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
|
@ -113,6 +114,8 @@ static int s390_use_dfa_pipeline_interface PARAMS ((void));
|
|||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE s390_use_dfa_pipeline_interface
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS s390_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -1192,6 +1195,79 @@ q_constraint (op)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
s390_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST:
|
||||
if (GET_CODE (XEXP (x, 0)) == MINUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
|
||||
*total = 1000;
|
||||
else
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case CONST_INT:
|
||||
/* Force_const_mem does not work out of reload, because the
|
||||
saveable_obstack is set to reload_obstack, which does not
|
||||
live long enough. Because of this we cannot use force_const_mem
|
||||
in addsi3. This leads to problems with gen_add2_insn with a
|
||||
constant greater than a short. Because of that we give an
|
||||
addition of greater constants a cost of 3 (reload1.c 10096). */
|
||||
/* ??? saveable_obstack no longer exists. */
|
||||
if (outer_code == PLUS
|
||||
&& (INTVAL (x) > 32767 || INTVAL (x) < -32768))
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
case CONST_DOUBLE:
|
||||
*total = 0;
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
case PLUS:
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
case MINUS:
|
||||
case NEG:
|
||||
case NOT:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (GET_MODE (XEXP (x, 0)) == DImode)
|
||||
*total = COSTS_N_INSNS (40);
|
||||
else
|
||||
*total = COSTS_N_INSNS (7);
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (33);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the cost of an address rtx ADDR. */
|
||||
|
||||
int
|
||||
|
|
|
@ -812,72 +812,6 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
|
|||
|
||||
/* Relative costs of operations. */
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain `case' labels for
|
||||
expression codes `const_int', `const', `symbol_ref', `label_ref'
|
||||
and `const_double'. Each case must ultimately reach a `return'
|
||||
statement to return the relative cost of the use of that kind of
|
||||
constant value in an expression. The cost may depend on the
|
||||
precise value of the constant, which is available for examination
|
||||
in X, and the rtx code of the expression in which it is contained,
|
||||
found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
/* Force_const_mem does not work out of reload, because the saveable_obstack
|
||||
is set to reload_obstack, which does not live long enough.
|
||||
Because of this we cannot use force_const_mem in addsi3.
|
||||
This leads to problems with gen_add2_insn with a constant greater
|
||||
than a short. Because of that we give an addition of greater
|
||||
constants a cost of 3 (reload1.c 10096). */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST: \
|
||||
if ((GET_CODE (XEXP (RTX, 0)) == MINUS) && \
|
||||
(GET_CODE (XEXP (XEXP (RTX, 0), 1)) != CONST_INT)) \
|
||||
return 1000; \
|
||||
case CONST_INT: \
|
||||
if ((OUTER_CODE == PLUS) && \
|
||||
((INTVAL (RTX) > 32767) || \
|
||||
(INTVAL (RTX) < -32768))) \
|
||||
return COSTS_N_INSNS (3); \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
case CONST_DOUBLE: \
|
||||
return 0; \
|
||||
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
`COSTS_N_INSNS (N)' to specify a cost equal to N fast
|
||||
instructions. OUTER_CODE is the code of the expression in which X
|
||||
is contained. */
|
||||
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
case PLUS: \
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
case MINUS: \
|
||||
case NEG: \
|
||||
case NOT: \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case MULT: \
|
||||
if (GET_MODE (XEXP (X, 0)) == DImode) \
|
||||
return COSTS_N_INSNS (40); \
|
||||
else \
|
||||
return COSTS_N_INSNS (7); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (33);
|
||||
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains
|
||||
ADDRESS. If not defined, the cost is computed from the ADDRESS
|
||||
expression and the `CONST_COSTS' values. */
|
||||
|
|
|
@ -56,10 +56,6 @@ extern int expand_block_move PARAMS ((rtx *));
|
|||
extern int prepare_move_operands PARAMS ((rtx[], enum machine_mode mode));
|
||||
extern void from_compare PARAMS ((rtx *, int));
|
||||
extern int shift_insns_rtx PARAMS ((rtx));
|
||||
extern int shiftcosts PARAMS ((rtx));
|
||||
extern int addsubcosts PARAMS ((rtx));
|
||||
extern int andcosts PARAMS ((rtx));
|
||||
extern int multcosts PARAMS ((rtx));
|
||||
extern void gen_ashift PARAMS ((int, int, rtx));
|
||||
extern void gen_ashift_hi PARAMS ((int, int, rtx));
|
||||
extern void gen_shifty_op PARAMS ((int, rtx *));
|
||||
|
|
|
@ -214,7 +214,11 @@ static void sh_media_init_builtins PARAMS ((void));
|
|||
static rtx sh_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
|
||||
static int flow_dependent_p PARAMS ((rtx, rtx));
|
||||
static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));
|
||||
|
||||
static int shiftcosts PARAMS ((rtx));
|
||||
static int andcosts PARAMS ((rtx));
|
||||
static int addsubcosts PARAMS ((rtx));
|
||||
static int multcosts PARAMS ((rtx));
|
||||
static bool sh_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ATTRIBUTE_TABLE
|
||||
|
@ -266,6 +270,9 @@ static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));
|
|||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL sh_function_ok_for_sibcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS sh_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Print the operand address in x to the stream. */
|
||||
|
@ -1274,7 +1281,7 @@ shift_insns_rtx (insn)
|
|||
|
||||
/* Return the cost of a shift. */
|
||||
|
||||
int
|
||||
static inline int
|
||||
shiftcosts (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -1314,7 +1321,7 @@ shiftcosts (x)
|
|||
|
||||
/* Return the cost of an AND operation. */
|
||||
|
||||
int
|
||||
static inline int
|
||||
andcosts (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -1354,7 +1361,7 @@ andcosts (x)
|
|||
|
||||
/* Return the cost of an addition or a subtraction. */
|
||||
|
||||
int
|
||||
static inline int
|
||||
addsubcosts (x)
|
||||
rtx x;
|
||||
{
|
||||
|
@ -1395,7 +1402,7 @@ addsubcosts (x)
|
|||
}
|
||||
|
||||
/* Return the cost of a multiply. */
|
||||
int
|
||||
static inline int
|
||||
multcosts (x)
|
||||
rtx x ATTRIBUTE_UNUSED;
|
||||
{
|
||||
|
@ -1421,6 +1428,101 @@ multcosts (x)
|
|||
return 20;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
sh_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code, *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (TARGET_SHMEDIA)
|
||||
{
|
||||
if (INTVAL (x) == 0)
|
||||
*total = 0;
|
||||
else if (outer_code == AND && and_operand ((x), DImode))
|
||||
*total = 0;
|
||||
else if ((outer_code == IOR || outer_code == XOR
|
||||
|| outer_code == PLUS)
|
||||
&& CONST_OK_FOR_P (INTVAL (x)))
|
||||
*total = 0;
|
||||
else if (CONST_OK_FOR_J (INTVAL (x)))
|
||||
*total = COSTS_N_INSNS (outer_code != SET);
|
||||
else if (CONST_OK_FOR_J (INTVAL (x) >> 16))
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else if (CONST_OK_FOR_J ((INTVAL (x) >> 16) >> 16))
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
}
|
||||
if (CONST_OK_FOR_I (INTVAL (x)))
|
||||
*total = 0;
|
||||
else if ((outer_code == AND || outer_code == IOR || outer_code == XOR)
|
||||
&& CONST_OK_FOR_L (INTVAL (x)))
|
||||
*total = 1;
|
||||
else
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
if (TARGET_SHMEDIA64)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else if (TARGET_SHMEDIA32)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (TARGET_SHMEDIA)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else
|
||||
*total = 10;
|
||||
return true;
|
||||
|
||||
case PLUS:
|
||||
*total = COSTS_N_INSNS (addsubcosts (x));
|
||||
return true;
|
||||
|
||||
case AND:
|
||||
*total = COSTS_N_INSNS (andcosts (x));
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS (multcosts (x));
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
*total = COSTS_N_INSNS (shiftcosts (x));
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
case MOD:
|
||||
case UMOD:
|
||||
*total = COSTS_N_INSNS (20);
|
||||
return true;
|
||||
|
||||
case FLOAT:
|
||||
case FIX:
|
||||
*total = 100;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Code to expand a shift. */
|
||||
|
||||
void
|
||||
|
|
|
@ -2690,70 +2690,6 @@ while (0)
|
|||
#define Pmode (TARGET_SHMEDIA64 ? DImode : SImode)
|
||||
#define FUNCTION_MODE Pmode
|
||||
|
||||
/* The relative costs of various types of constants. */
|
||||
|
||||
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (TARGET_SHMEDIA) \
|
||||
{ \
|
||||
if (INTVAL (RTX) == 0) \
|
||||
return 0; \
|
||||
if ((OUTER_CODE) == AND && and_operand ((RTX), DImode)) \
|
||||
return 0; \
|
||||
if (((OUTER_CODE) == IOR || (OUTER_CODE) == XOR \
|
||||
|| (OUTER_CODE) == PLUS) \
|
||||
&& CONST_OK_FOR_P (INTVAL (RTX))) \
|
||||
return 0; \
|
||||
if (CONST_OK_FOR_J (INTVAL (RTX))) \
|
||||
return COSTS_N_INSNS ((OUTER_CODE) != SET); \
|
||||
else if (CONST_OK_FOR_J (INTVAL (RTX) >> 16)) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
else if (CONST_OK_FOR_J ((INTVAL (RTX) >> 16) >> 16)) \
|
||||
return COSTS_N_INSNS (3); \
|
||||
else \
|
||||
return COSTS_N_INSNS (4); \
|
||||
} \
|
||||
if (CONST_OK_FOR_I (INTVAL (RTX))) \
|
||||
return 0; \
|
||||
else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
|
||||
&& CONST_OK_FOR_L (INTVAL (RTX))) \
|
||||
return 1; \
|
||||
else \
|
||||
return 8; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
if (TARGET_SHMEDIA64) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
if (TARGET_SHMEDIA32) \
|
||||
return COSTS_N_INSNS (2); \
|
||||
return 5; \
|
||||
case CONST_DOUBLE: \
|
||||
if (TARGET_SHMEDIA) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
else \
|
||||
return 10;
|
||||
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case PLUS: \
|
||||
return COSTS_N_INSNS (addsubcosts (X)); \
|
||||
case AND: \
|
||||
return COSTS_N_INSNS (andcosts (X)); \
|
||||
case MULT: \
|
||||
return COSTS_N_INSNS (multcosts (X)); \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
return COSTS_N_INSNS (shiftcosts (X)); \
|
||||
case DIV: \
|
||||
case UDIV: \
|
||||
case MOD: \
|
||||
case UMOD: \
|
||||
return COSTS_N_INSNS (20); \
|
||||
case FLOAT: \
|
||||
case FIX: \
|
||||
return 100;
|
||||
|
||||
/* The multiply insn on the SH1 and the divide insns on the SH1 and SH2
|
||||
are actually function calls with some special constraints on arguments
|
||||
and register usage.
|
||||
|
|
|
@ -120,7 +120,6 @@ extern char *sparc_v8plus_shift PARAMS ((rtx *, rtx, const char *));
|
|||
extern int sparc_check_64 PARAMS ((rtx, rtx));
|
||||
extern rtx gen_df_reg PARAMS ((rtx, int));
|
||||
extern int sparc_extra_constraint_check PARAMS ((rtx, int, int));
|
||||
extern int sparc_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
#endif /* __SPARC_PROTOS_H__ */
|
||||
|
|
|
@ -181,6 +181,7 @@ static void sparc_encode_section_info PARAMS ((tree, int));
|
|||
static bool sparc_function_ok_for_sibcall PARAMS ((tree, tree));
|
||||
static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree));
|
||||
static bool sparc_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Option handling. */
|
||||
|
||||
|
@ -252,6 +253,9 @@ enum processor_type sparc_cpu;
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS sparc_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Validate and override various options, and do some machine dependent
|
||||
|
@ -8156,10 +8160,10 @@ sparc_extra_constraint_check (op, c, strict)
|
|||
??? scheduler description. Some day, teach genautomata to output
|
||||
??? the latencies and then CSE will just use that. */
|
||||
|
||||
int
|
||||
sparc_rtx_costs (x, code, outer_code)
|
||||
static bool
|
||||
sparc_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
enum rtx_code code, outer_code;
|
||||
int code, outer_code, *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
|
@ -8173,50 +8177,61 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
return COSTS_N_INSNS (4);
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
return COSTS_N_INSNS (3);
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_CYPRESS:
|
||||
return COSTS_N_INSNS (5);
|
||||
*total = COSTS_N_INSNS (5);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
default:
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case SQRT:
|
||||
switch (sparc_cpu)
|
||||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (13);
|
||||
*total = COSTS_N_INSNS (13);
|
||||
else
|
||||
return COSTS_N_INSNS (23);
|
||||
*total = COSTS_N_INSNS (23);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (20);
|
||||
*total = COSTS_N_INSNS (20);
|
||||
else
|
||||
return COSTS_N_INSNS (29);
|
||||
*total = COSTS_N_INSNS (29);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
return COSTS_N_INSNS (12);
|
||||
*total = COSTS_N_INSNS (12);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_CYPRESS:
|
||||
return COSTS_N_INSNS (63);
|
||||
*total = COSTS_N_INSNS (63);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
return COSTS_N_INSNS (17);
|
||||
*total = COSTS_N_INSNS (17);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return COSTS_N_INSNS (30);
|
||||
*total = COSTS_N_INSNS (30);
|
||||
return true;
|
||||
}
|
||||
|
||||
case COMPARE:
|
||||
|
@ -8226,18 +8241,22 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
return COSTS_N_INSNS (3);
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_CYPRESS:
|
||||
return COSTS_N_INSNS (5);
|
||||
*total = COSTS_N_INSNS (5);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
default:
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8245,7 +8264,8 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
??? all UltraSPARC processors because the result
|
||||
??? can be bypassed to a branch in the same group. */
|
||||
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (FLOAT_MODE_P (GET_MODE (x)))
|
||||
|
@ -8254,20 +8274,25 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
return COSTS_N_INSNS (4);
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
return COSTS_N_INSNS (3);
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_CYPRESS:
|
||||
return COSTS_N_INSNS (7);
|
||||
*total = COSTS_N_INSNS (7);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return COSTS_N_INSNS (5);
|
||||
*total = COSTS_N_INSNS (5);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8304,20 +8329,28 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
Since we do not play any such tricks currently the
|
||||
safest thing to do is report the worst case latency. */
|
||||
if (sparc_cpu == PROCESSOR_ULTRASPARC)
|
||||
return (GET_MODE (x) == DImode ?
|
||||
COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
|
||||
{
|
||||
*total = (GET_MODE (x) == DImode
|
||||
? COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Multiply latency on Ultra-III, fortunately, is constant. */
|
||||
if (sparc_cpu == PROCESSOR_ULTRASPARC3)
|
||||
return COSTS_N_INSNS (6);
|
||||
{
|
||||
*total = COSTS_N_INSNS (6);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sparc_cpu == PROCESSOR_HYPERSPARC
|
||||
|| sparc_cpu == PROCESSOR_SPARCLITE86X)
|
||||
return COSTS_N_INSNS (17);
|
||||
{
|
||||
*total = COSTS_N_INSNS (17);
|
||||
return true;
|
||||
}
|
||||
|
||||
return (TARGET_HARD_MUL
|
||||
? COSTS_N_INSNS (5)
|
||||
: COSTS_N_INSNS (25));
|
||||
*total = (TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25));
|
||||
return true;
|
||||
|
||||
case DIV:
|
||||
case UDIV:
|
||||
|
@ -8329,57 +8362,67 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (13);
|
||||
*total = COSTS_N_INSNS (13);
|
||||
else
|
||||
return COSTS_N_INSNS (23);
|
||||
*total = COSTS_N_INSNS (23);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (17);
|
||||
*total = COSTS_N_INSNS (17);
|
||||
else
|
||||
return COSTS_N_INSNS (20);
|
||||
*total = COSTS_N_INSNS (20);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (6);
|
||||
*total = COSTS_N_INSNS (6);
|
||||
else
|
||||
return COSTS_N_INSNS (9);
|
||||
*total = COSTS_N_INSNS (9);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
return COSTS_N_INSNS (8);
|
||||
*total = COSTS_N_INSNS (8);
|
||||
else
|
||||
return COSTS_N_INSNS (12);
|
||||
*total = COSTS_N_INSNS (12);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return COSTS_N_INSNS (7);
|
||||
*total = COSTS_N_INSNS (7);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sparc_cpu == PROCESSOR_ULTRASPARC)
|
||||
return (GET_MODE (x) == DImode ?
|
||||
COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
|
||||
if (sparc_cpu == PROCESSOR_ULTRASPARC3)
|
||||
return (GET_MODE (x) == DImode ?
|
||||
COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
|
||||
return COSTS_N_INSNS (25);
|
||||
*total = (GET_MODE (x) == DImode
|
||||
? COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
|
||||
else if (sparc_cpu == PROCESSOR_ULTRASPARC3)
|
||||
*total = (GET_MODE (x) == DImode
|
||||
? COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
|
||||
else
|
||||
*total = COSTS_N_INSNS (25);
|
||||
return true;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
/* Conditional moves. */
|
||||
switch (sparc_cpu)
|
||||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
if (FLOAT_MODE_P (GET_MODE (x)))
|
||||
return COSTS_N_INSNS (3);
|
||||
*total = COSTS_N_INSNS (3);
|
||||
else
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
|
||||
case MEM:
|
||||
|
@ -8390,9 +8433,10 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
{
|
||||
case PROCESSOR_ULTRASPARC:
|
||||
if (outer_code == ZERO_EXTEND)
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_ULTRASPARC3:
|
||||
if (outer_code == ZERO_EXTEND)
|
||||
|
@ -8400,75 +8444,87 @@ sparc_rtx_costs (x, code, outer_code)
|
|||
if (GET_MODE (x) == QImode
|
||||
|| GET_MODE (x) == HImode
|
||||
|| outer_code == SIGN_EXTEND)
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This handles sign extension (3 cycles)
|
||||
and everything else (2 cycles). */
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
}
|
||||
return true;
|
||||
|
||||
case PROCESSOR_SUPERSPARC:
|
||||
if (FLOAT_MODE_P (GET_MODE (x))
|
||||
|| outer_code == ZERO_EXTEND
|
||||
|| outer_code == SIGN_EXTEND)
|
||||
return COSTS_N_INSNS (0);
|
||||
*total = COSTS_N_INSNS (0);
|
||||
else
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_TSC701:
|
||||
if (outer_code == ZERO_EXTEND
|
||||
|| outer_code == SIGN_EXTEND)
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
return COSTS_N_INSNS (3);
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_CYPRESS:
|
||||
if (outer_code == ZERO_EXTEND
|
||||
|| outer_code == SIGN_EXTEND)
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
return COSTS_N_INSNS (2);
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case PROCESSOR_HYPERSPARC:
|
||||
case PROCESSOR_SPARCLITE86X:
|
||||
default:
|
||||
if (outer_code == ZERO_EXTEND
|
||||
|| outer_code == SIGN_EXTEND)
|
||||
return COSTS_N_INSNS (0);
|
||||
*total = COSTS_N_INSNS (0);
|
||||
else
|
||||
return COSTS_N_INSNS (1);
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
|
||||
return 0;
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
/* fallthru */
|
||||
case HIGH:
|
||||
return 2;
|
||||
*total = 2;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
return 4;
|
||||
*total = 4;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (GET_MODE (x) == DImode)
|
||||
if ((XINT (x, 3) == 0
|
||||
&& (unsigned) XINT (x, 2) < 0x1000)
|
||||
|| (XINT (x, 3) == -1
|
||||
&& XINT (x, 2) < 0
|
||||
&& XINT (x, 2) >= -0x1000))
|
||||
return 0;
|
||||
return 8;
|
||||
if (GET_MODE (x) == DImode
|
||||
&& ((XINT (x, 3) == 0
|
||||
&& (unsigned HOST_WIDE_INT) XINT (x, 2) < 0x1000)
|
||||
|| (XINT (x, 3) == -1
|
||||
&& XINT (x, 2) < 0
|
||||
&& XINT (x, 2) >= -0x1000)))
|
||||
*total = 0;
|
||||
else
|
||||
*total = 8;
|
||||
return true;
|
||||
|
||||
default:
|
||||
abort();
|
||||
};
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are referencing a function make the SYMBOL_REF special. In
|
||||
|
|
|
@ -2608,27 +2608,6 @@ do { \
|
|||
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
|
||||
? 9 : 3))
|
||||
|
||||
/* The cases that RTX_COSTS handles. */
|
||||
|
||||
#define RTX_COSTS_CASES \
|
||||
case PLUS: case MINUS: case ABS: case NEG: \
|
||||
case FLOAT: case UNSIGNED_FLOAT: \
|
||||
case FIX: case UNSIGNED_FIX: \
|
||||
case FLOAT_EXTEND: case FLOAT_TRUNCATE: \
|
||||
case SQRT: \
|
||||
case COMPARE: case IF_THEN_ELSE: \
|
||||
case MEM: \
|
||||
case MULT: case DIV: case UDIV: case MOD: case UMOD: \
|
||||
case CONST_INT: case HIGH: case CONST: \
|
||||
case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE:
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE. */
|
||||
|
||||
#define RTX_COSTS(X,CODE,OUTER_CODE) \
|
||||
RTX_COSTS_CASES \
|
||||
return sparc_rtx_costs(X,CODE,OUTER_CODE);
|
||||
|
||||
#define ADDRESS_COST(RTX) 1
|
||||
|
||||
#define PREFETCH_BLOCK \
|
||||
|
|
|
@ -57,6 +57,7 @@ static void xstormy16_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
|||
|
||||
static void xstormy16_init_builtins PARAMS ((void));
|
||||
static rtx xstormy16_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
|
||||
static bool xstormy16_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Define the information needed to generate branch and scc insns. This is
|
||||
stored from the compare operation. */
|
||||
|
@ -97,6 +98,47 @@ inequality_operator (op, mode)
|
|||
return comparison_operator (op, mode) && ! equality_operator (op, mode);
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
xstormy16_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) < 16 && INTVAL (x) >= 0)
|
||||
*total = COSTS_N_INSNS (1) / 2;
|
||||
else if (INTVAL (x) < 256 && INTVAL (x) >= 0)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2);
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
*total = COSTS_N_INSNS(2);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
*total = COSTS_N_INSNS (35 + 6);
|
||||
return true;
|
||||
case DIV:
|
||||
*total = COSTS_N_INSNS (51 - 6);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Branches are handled as follows:
|
||||
|
||||
1. HImode compare-and-branches. The machine supports these
|
||||
|
@ -2165,4 +2207,7 @@ xstormy16_expand_builtin(exp, target, subtarget, mode, ignore)
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS xstormy16_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
|
|
@ -2197,43 +2197,6 @@ do { \
|
|||
|
||||
/* Describing Relative Costs of Operations */
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs of
|
||||
constant RTL expressions. It must contain `case' labels for expression
|
||||
codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'.
|
||||
Each case must ultimately reach a `return' statement to return the relative
|
||||
cost of the use of that kind of constant value in an expression. The cost
|
||||
may depend on the precise value of the constant, which is available for
|
||||
examination in X, and the rtx code of the expression in which it is
|
||||
contained, found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained with
|
||||
`GET_CODE (X)'. */
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (X) < 16 && INTVAL (X) >= 0) \
|
||||
return COSTS_N_INSNS (1)/2; \
|
||||
if (INTVAL (X) < 256 && INTVAL (X) >= 0) \
|
||||
return COSTS_N_INSNS (1); \
|
||||
case CONST_DOUBLE: \
|
||||
case CONST: \
|
||||
case SYMBOL_REF: \
|
||||
case LABEL_REF: \
|
||||
return COSTS_N_INSNS(2);
|
||||
|
||||
/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be
|
||||
used, for example, to indicate how costly a multiply instruction is. In
|
||||
writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify
|
||||
a cost equal to N fast instructions. OUTER_CODE is the code of the
|
||||
expression in which X is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost assumptions are
|
||||
adequate for the target machine. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MULT: \
|
||||
return COSTS_N_INSNS (35 + 6); \
|
||||
case DIV: \
|
||||
return COSTS_N_INSNS (51 - 6);
|
||||
|
||||
/* An expression giving the cost of an addressing mode that contains ADDRESS.
|
||||
If not defined, the cost is computed from the ADDRESS expression and the
|
||||
`CONST_COSTS' values.
|
||||
|
|
|
@ -46,7 +46,6 @@ extern int v850_output_addr_const_extra PARAMS ((FILE *, rtx));
|
|||
extern rtx v850_return_addr PARAMS ((int));
|
||||
extern void print_operand PARAMS ((FILE *, rtx, int ));
|
||||
extern void print_operand_address PARAMS ((FILE *, rtx));
|
||||
extern int const_costs PARAMS ((rtx, enum rtx_code));
|
||||
extern const char *output_move_double PARAMS ((rtx *));
|
||||
extern const char *output_move_single PARAMS ((rtx *));
|
||||
extern void v850_reorg PARAMS ((rtx));
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
/* Function prototypes for stupid compilers: */
|
||||
static void const_double_split PARAMS ((rtx, HOST_WIDE_INT *, HOST_WIDE_INT *));
|
||||
static int const_costs_int PARAMS ((HOST_WIDE_INT, int));
|
||||
static int const_costs PARAMS ((rtx, enum rtx_code));
|
||||
static bool v850_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
static void substitute_ep_register PARAMS ((rtx, rtx, int, int, rtx *, rtx *));
|
||||
static int ep_memory_offset PARAMS ((enum machine_mode, int));
|
||||
static void v850_set_data_area PARAMS ((tree, v850_data_area));
|
||||
|
@ -105,6 +107,9 @@ static int v850_interrupt_p = FALSE;
|
|||
#undef TARGET_STRIP_NAME_ENCODING
|
||||
#define TARGET_STRIP_NAME_ENCODING v850_strip_name_encoding
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS v850_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Sometimes certain combinations of command options do not make
|
||||
|
@ -322,7 +327,7 @@ const_costs_int (value, zero_cost)
|
|||
return 4;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
const_costs (r, c)
|
||||
rtx r;
|
||||
enum rtx_code c;
|
||||
|
@ -354,6 +359,55 @@ const_costs (r, c)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
v850_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code ATTRIBUTE_UNUSED, *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
case CONST_DOUBLE:
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
*total = COSTS_N_INSNS (const_costs (x, code));
|
||||
return true;
|
||||
|
||||
case MOD:
|
||||
case DIV:
|
||||
case UMOD:
|
||||
case UDIV:
|
||||
if (TARGET_V850E && optimize_size)
|
||||
*total = 6;
|
||||
else
|
||||
*total = 60;
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
if (TARGET_V850E
|
||||
&& ( GET_MODE (x) == SImode
|
||||
|| GET_MODE (x) == HImode
|
||||
|| GET_MODE (x) == QImode))
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == REG)
|
||||
*total = 4;
|
||||
else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
if (CONST_OK_FOR_O (INTVAL (XEXP (x, 1))))
|
||||
*total = 6;
|
||||
else if (CONST_OK_FOR_K (INTVAL (XEXP (x, 1))))
|
||||
*total = 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
*total = 20;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print operand X using operand code CODE to assembly language output file
|
||||
FILE. */
|
||||
|
|
|
@ -1025,64 +1025,6 @@ do { \
|
|||
#define CC_NO_CARRY CC_NO_OVERFLOW
|
||||
#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
|
||||
|
||||
/* A part of a C `switch' statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain `case' labels for
|
||||
expression codes `const_int', `const', `symbol_ref', `label_ref'
|
||||
and `const_double'. Each case must ultimately reach a `return'
|
||||
statement to return the relative cost of the use of that kind of
|
||||
constant value in an expression. The cost may depend on the
|
||||
precise value of the constant, which is available for examination
|
||||
in X, and the rtx code of the expression in which it is contained,
|
||||
found in OUTER_CODE.
|
||||
|
||||
CODE is the expression code--redundant, since it can be obtained
|
||||
with `GET_CODE (X)'. */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
case CONST_DOUBLE: \
|
||||
case CONST: \
|
||||
case SYMBOL_REF: \
|
||||
case LABEL_REF: \
|
||||
{ \
|
||||
int _zxy = const_costs(RTX, CODE); \
|
||||
return (_zxy) ? COSTS_N_INSNS (_zxy) : 0; \
|
||||
}
|
||||
|
||||
/* A crude cut at RTX_COSTS for the V850. */
|
||||
|
||||
/* Provide the costs of a rtl expression. This is in the body of a
|
||||
switch on CODE.
|
||||
|
||||
There aren't DImode MOD, DIV or MULT operations, so call them
|
||||
very expensive. Everything else is pretty much a constant cost. */
|
||||
|
||||
#define RTX_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case MOD: \
|
||||
case DIV: \
|
||||
case UMOD: \
|
||||
case UDIV: \
|
||||
if (TARGET_V850E && optimize_size) \
|
||||
return 6; \
|
||||
return 60; \
|
||||
case MULT: \
|
||||
if (TARGET_V850E \
|
||||
&& ( GET_MODE (RTX) == SImode \
|
||||
|| GET_MODE (RTX) == HImode \
|
||||
|| GET_MODE (RTX) == QImode)) \
|
||||
{ \
|
||||
if (GET_CODE (XEXP (RTX, 1)) == REG) \
|
||||
return 4; \
|
||||
else if (GET_CODE (XEXP (RTX, 1)) == CONST_INT) \
|
||||
{ \
|
||||
if (CONST_OK_FOR_O (INTVAL (XEXP (RTX, 1)))) \
|
||||
return 6; \
|
||||
else if (CONST_OK_FOR_K (INTVAL (XEXP (RTX, 1)))) \
|
||||
return 10; \
|
||||
} \
|
||||
} \
|
||||
return 20;
|
||||
|
||||
/* All addressing modes have the same cost on the V850 series. */
|
||||
#define ADDRESS_COST(ADDR) 1
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ static int follows_p PARAMS ((rtx, rtx));
|
|||
static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, tree));
|
||||
static int vax_rtx_costs_1 PARAMS ((rtx, enum rtx_code, enum rtx_code));
|
||||
static bool vax_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
|
@ -58,6 +60,9 @@ static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
|
|||
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS vax_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Set global variables as needed for the options enabled. */
|
||||
|
@ -482,16 +487,15 @@ vax_address_cost (addr)
|
|||
return reg + indexed + indir + offset + predec;
|
||||
}
|
||||
|
||||
|
||||
/* Cost of an expression on a VAX. This version has costs tuned for the
|
||||
CVAX chip (found in the VAX 3 series) with comments for variations on
|
||||
other models. */
|
||||
|
||||
int
|
||||
vax_rtx_cost (x)
|
||||
static int
|
||||
vax_rtx_costs_1 (x, code, outer_code)
|
||||
register rtx x;
|
||||
enum rtx_code code, outer_code;
|
||||
{
|
||||
register enum rtx_code code = GET_CODE (x);
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
register int c;
|
||||
int i = 0; /* may be modified in switch */
|
||||
|
@ -499,6 +503,40 @@ vax_rtx_cost (x)
|
|||
|
||||
switch (code)
|
||||
{
|
||||
/* On a VAX, constants from 0..63 are cheap because they can use the
|
||||
1 byte literal constant format. compare to -1 should be made cheap
|
||||
so that decrement-and-branch insns can be formed more easily (if
|
||||
the value -1 is copied to a register some decrement-and-branch
|
||||
patterns will not match). */
|
||||
case CONST_INT:
|
||||
if (INTVAL (x) == 0)
|
||||
return 0;
|
||||
if (outer_code == AND)
|
||||
return ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2;
|
||||
if ((unsigned HOST_WIDE_INT) INTVAL (x) <= 077)
|
||||
return 1;
|
||||
if (outer_code == COMPARE && INTVAL (x) == -1)
|
||||
return 1;
|
||||
if (outer_code == PLUS && (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077)
|
||||
return 1;
|
||||
/* FALLTHRU */
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
return 3;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
return vax_float_literal (x) ? 5 : 8;
|
||||
else
|
||||
return (((CONST_DOUBLE_HIGH (x) == 0
|
||||
&& (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x) < 64)
|
||||
|| (outer_code == PLUS
|
||||
&& CONST_DOUBLE_HIGH (x) == -1 \
|
||||
&& (unsigned HOST_WIDE_INT)-CONST_DOUBLE_LOW (x) < 64))
|
||||
? 2 : 5);
|
||||
|
||||
case POST_INC:
|
||||
return 2;
|
||||
case PRE_DEC:
|
||||
|
@ -617,7 +655,6 @@ vax_rtx_cost (x)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Now look inside the expression. Operands which are not registers or
|
||||
short constants add to the cost.
|
||||
|
||||
|
@ -678,6 +715,16 @@ vax_rtx_cost (x)
|
|||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static bool
|
||||
vax_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
*total = vax_rtx_costs_1 (x, code, outer_code);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return 1 if insn A follows B. */
|
||||
|
||||
|
|
|
@ -848,49 +848,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
|
|||
|
||||
#define TARGET_FLOAT_FORMAT VAX_FLOAT_FORMAT
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
return it with a return statement. Otherwise, break from the switch. */
|
||||
|
||||
/* On a VAX, constants from 0..63 are cheap because they can use the
|
||||
1 byte literal constant format. compare to -1 should be made cheap
|
||||
so that decrement-and-branch insns can be formed more easily (if
|
||||
the value -1 is copied to a register some decrement-and-branch patterns
|
||||
will not match). */
|
||||
|
||||
#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
if (INTVAL (RTX) == 0) return 0; \
|
||||
if ((OUTER_CODE) == AND) \
|
||||
return ((unsigned) ~INTVAL (RTX) <= 077) ? 1 : 2; \
|
||||
if ((unsigned) INTVAL (RTX) <= 077) return 1; \
|
||||
if ((OUTER_CODE) == COMPARE && INTVAL (RTX) == -1) \
|
||||
return 1; \
|
||||
if ((OUTER_CODE) == PLUS && (unsigned) -INTVAL (RTX) <= 077)\
|
||||
return 1; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 3; \
|
||||
case CONST_DOUBLE: \
|
||||
if (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT) \
|
||||
return vax_float_literal (RTX) ? 5 : 8; \
|
||||
else \
|
||||
return (((CONST_DOUBLE_HIGH (RTX) == 0 \
|
||||
&& (unsigned) CONST_DOUBLE_LOW (RTX) < 64) \
|
||||
|| ((OUTER_CODE) == PLUS \
|
||||
&& CONST_DOUBLE_HIGH (RTX) == -1 \
|
||||
&& (unsigned)-CONST_DOUBLE_LOW (RTX) < 64)) \
|
||||
? 2 : 5);
|
||||
|
||||
#define RTX_COSTS(RTX,CODE,OUTER_CODE) case FIX: case FLOAT: \
|
||||
case MULT: case DIV: case UDIV: case MOD: case UMOD: \
|
||||
case ASHIFT: case LSHIFTRT: case ASHIFTRT: \
|
||||
case ROTATE: case ROTATERT: case PLUS: case MINUS: case IOR: \
|
||||
case XOR: case AND: case NEG: case NOT: case ZERO_EXTRACT: \
|
||||
case SIGN_EXTRACT: case MEM: return vax_rtx_cost(RTX)
|
||||
|
||||
#define ADDRESS_COST(RTX) (1 + (GET_CODE (RTX) == REG ? 0 : vax_address_cost(RTX)))
|
||||
|
||||
/* Specify the cost of a branch insn; roughly the number of extra insns that
|
||||
|
|
|
@ -204,6 +204,7 @@ static unsigned int xtensa_multibss_section_type_flags
|
|||
static void xtensa_select_rtx_section
|
||||
PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
|
||||
static void xtensa_encode_section_info PARAMS ((tree, int));
|
||||
static bool xtensa_rtx_costs PARAMS ((rtx, int, int, int *));
|
||||
|
||||
static rtx frame_size_const;
|
||||
static int current_function_arg_words;
|
||||
|
@ -240,6 +241,9 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
|
|||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO xtensa_encode_section_info
|
||||
|
||||
#undef TARGET_RTX_COSTS
|
||||
#define TARGET_RTX_COSTS xtensa_rtx_costs
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
||||
|
@ -2838,4 +2842,216 @@ xtensa_encode_section_info (decl, first)
|
|||
SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
|
||||
}
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
|
||||
static bool
|
||||
xtensa_rtx_costs (x, code, outer_code, total)
|
||||
rtx x;
|
||||
int code, outer_code;
|
||||
int *total;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case CONST_INT:
|
||||
switch (outer_code)
|
||||
{
|
||||
case SET:
|
||||
if (xtensa_simm12b (INTVAL (x)))
|
||||
{
|
||||
*total = 4;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case PLUS:
|
||||
if (xtensa_simm8 (INTVAL (x))
|
||||
|| xtensa_simm8x256 (INTVAL (x)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AND:
|
||||
if (xtensa_mask_immediate (INTVAL (x)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case COMPARE:
|
||||
if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
|
||||
{
|
||||
*total = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
case ROTATE:
|
||||
case ROTATERT:
|
||||
/* no way to tell if X is the 2nd operand so be conservative */
|
||||
default: break;
|
||||
}
|
||||
if (xtensa_simm12b (INTVAL (x)))
|
||||
*total = 5;
|
||||
else
|
||||
*total = 6;
|
||||
return true;
|
||||
|
||||
case CONST:
|
||||
case LABEL_REF:
|
||||
case SYMBOL_REF:
|
||||
*total = 5;
|
||||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
*total = 7;
|
||||
return true;
|
||||
|
||||
case MEM:
|
||||
{
|
||||
int num_words =
|
||||
(GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ? 2 : 1;
|
||||
|
||||
if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
|
||||
*total = COSTS_N_INSNS (num_words);
|
||||
else
|
||||
*total = COSTS_N_INSNS (2*num_words);
|
||||
return true;
|
||||
}
|
||||
|
||||
case FFS:
|
||||
*total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
|
||||
return true;
|
||||
|
||||
case NOT:
|
||||
*total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
|
||||
return true;
|
||||
|
||||
case AND:
|
||||
case IOR:
|
||||
case XOR:
|
||||
if (GET_MODE (x) == DImode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
if (GET_MODE (x) == DImode)
|
||||
*total = COSTS_N_INSNS (50);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
case ABS:
|
||||
{
|
||||
enum machine_mode xmode = GET_MODE (x);
|
||||
if (xmode == SFmode)
|
||||
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
|
||||
else if (xmode == DFmode)
|
||||
*total = COSTS_N_INSNS (50);
|
||||
else
|
||||
*total = COSTS_N_INSNS (4);
|
||||
return true;
|
||||
}
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
{
|
||||
enum machine_mode xmode = GET_MODE (x);
|
||||
if (xmode == SFmode)
|
||||
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
|
||||
else if (xmode == DFmode || xmode == DImode)
|
||||
*total = COSTS_N_INSNS (50);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
}
|
||||
|
||||
case NEG:
|
||||
*total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
|
||||
return true;
|
||||
|
||||
case MULT:
|
||||
{
|
||||
enum machine_mode xmode = GET_MODE (x);
|
||||
if (xmode == SFmode)
|
||||
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
|
||||
else if (xmode == DFmode || xmode == DImode)
|
||||
*total = COSTS_N_INSNS (50);
|
||||
else if (TARGET_MUL32)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else if (TARGET_MAC16)
|
||||
*total = COSTS_N_INSNS (16);
|
||||
else if (TARGET_MUL16)
|
||||
*total = COSTS_N_INSNS (12);
|
||||
else
|
||||
*total = COSTS_N_INSNS (50);
|
||||
return true;
|
||||
}
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
{
|
||||
enum machine_mode xmode = GET_MODE (x);
|
||||
if (xmode == SFmode)
|
||||
{
|
||||
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
|
||||
return true;
|
||||
}
|
||||
else if (xmode == DFmode)
|
||||
{
|
||||
*total = COSTS_N_INSNS (50);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case UDIV:
|
||||
case UMOD:
|
||||
{
|
||||
enum machine_mode xmode = GET_MODE (x);
|
||||
if (xmode == DImode)
|
||||
*total = COSTS_N_INSNS (50);
|
||||
else if (TARGET_DIV32)
|
||||
*total = COSTS_N_INSNS (32);
|
||||
else
|
||||
*total = COSTS_N_INSNS (50);
|
||||
return true;
|
||||
}
|
||||
|
||||
case SQRT:
|
||||
if (GET_MODE (x) == SFmode)
|
||||
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
|
||||
else
|
||||
*total = COSTS_N_INSNS (50);
|
||||
return true;
|
||||
|
||||
case SMIN:
|
||||
case UMIN:
|
||||
case SMAX:
|
||||
case UMAX:
|
||||
*total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
|
||||
return true;
|
||||
|
||||
case SIGN_EXTRACT:
|
||||
case SIGN_EXTEND:
|
||||
*total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
|
||||
return true;
|
||||
|
||||
case ZERO_EXTRACT:
|
||||
case ZERO_EXTEND:
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#include "gt-xtensa.h"
|
||||
|
|
|
@ -1281,153 +1281,6 @@ typedef struct xtensa_args {
|
|||
indexing purposes) so give the MEM rtx a words's mode. */
|
||||
#define FUNCTION_MODE SImode
|
||||
|
||||
/* Xtensa constant costs. */
|
||||
#define CONST_COSTS(X, CODE, OUTER_CODE) \
|
||||
case CONST_INT: \
|
||||
switch (OUTER_CODE) \
|
||||
{ \
|
||||
case SET: \
|
||||
if (xtensa_simm12b (INTVAL (X))) return 4; \
|
||||
break; \
|
||||
case PLUS: \
|
||||
if (xtensa_simm8 (INTVAL (X))) return 0; \
|
||||
if (xtensa_simm8x256 (INTVAL (X))) return 0; \
|
||||
break; \
|
||||
case AND: \
|
||||
if (xtensa_mask_immediate (INTVAL (X))) return 0; \
|
||||
break; \
|
||||
case COMPARE: \
|
||||
if ((INTVAL (X) == 0) || xtensa_b4const (INTVAL (X))) return 0; \
|
||||
break; \
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
case ROTATE: \
|
||||
case ROTATERT: \
|
||||
/* no way to tell if X is the 2nd operand so be conservative */ \
|
||||
default: break; \
|
||||
} \
|
||||
if (xtensa_simm12b (INTVAL (X))) return 5; \
|
||||
return 6; \
|
||||
case CONST: \
|
||||
case LABEL_REF: \
|
||||
case SYMBOL_REF: \
|
||||
return 5; \
|
||||
case CONST_DOUBLE: \
|
||||
return 7;
|
||||
|
||||
/* Costs of various Xtensa operations. */
|
||||
#define RTX_COSTS(X, CODE, OUTER_CODE) \
|
||||
case MEM: \
|
||||
{ \
|
||||
int num_words = \
|
||||
(GET_MODE_SIZE (GET_MODE (X)) > UNITS_PER_WORD) ? 2 : 1; \
|
||||
if (memory_address_p (GET_MODE (X), XEXP ((X), 0))) \
|
||||
return COSTS_N_INSNS (num_words); \
|
||||
\
|
||||
return COSTS_N_INSNS (2*num_words); \
|
||||
} \
|
||||
\
|
||||
case FFS: \
|
||||
return COSTS_N_INSNS (TARGET_NSA ? 5 : 50); \
|
||||
\
|
||||
case NOT: \
|
||||
return COSTS_N_INSNS ((GET_MODE (X) == DImode) ? 3 : 2); \
|
||||
\
|
||||
case AND: \
|
||||
case IOR: \
|
||||
case XOR: \
|
||||
if (GET_MODE (X) == DImode) return COSTS_N_INSNS (2); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
\
|
||||
case ASHIFT: \
|
||||
case ASHIFTRT: \
|
||||
case LSHIFTRT: \
|
||||
if (GET_MODE (X) == DImode) return COSTS_N_INSNS (50); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
\
|
||||
case ABS: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
return COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50); \
|
||||
if (xmode == DFmode) \
|
||||
return COSTS_N_INSNS (50); \
|
||||
return COSTS_N_INSNS (4); \
|
||||
} \
|
||||
\
|
||||
case PLUS: \
|
||||
case MINUS: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
return COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50); \
|
||||
if (xmode == DFmode || xmode == DImode) \
|
||||
return COSTS_N_INSNS (50); \
|
||||
return COSTS_N_INSNS (1); \
|
||||
} \
|
||||
\
|
||||
case NEG: \
|
||||
return COSTS_N_INSNS ((GET_MODE (X) == DImode) ? 4 : 2); \
|
||||
\
|
||||
case MULT: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
return COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50); \
|
||||
if (xmode == DFmode || xmode == DImode) \
|
||||
return COSTS_N_INSNS (50); \
|
||||
if (TARGET_MUL32) \
|
||||
return COSTS_N_INSNS (4); \
|
||||
if (TARGET_MAC16) \
|
||||
return COSTS_N_INSNS (16); \
|
||||
if (TARGET_MUL16) \
|
||||
return COSTS_N_INSNS (12); \
|
||||
return COSTS_N_INSNS (50); \
|
||||
} \
|
||||
\
|
||||
case DIV: \
|
||||
case MOD: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == SFmode) \
|
||||
return COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50); \
|
||||
if (xmode == DFmode) \
|
||||
return COSTS_N_INSNS (50); \
|
||||
} \
|
||||
/* fall through */ \
|
||||
\
|
||||
case UDIV: \
|
||||
case UMOD: \
|
||||
{ \
|
||||
enum machine_mode xmode = GET_MODE (X); \
|
||||
if (xmode == DImode) \
|
||||
return COSTS_N_INSNS (50); \
|
||||
if (TARGET_DIV32) \
|
||||
return COSTS_N_INSNS (32); \
|
||||
return COSTS_N_INSNS (50); \
|
||||
} \
|
||||
\
|
||||
case SQRT: \
|
||||
if (GET_MODE (X) == SFmode) \
|
||||
return COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50); \
|
||||
return COSTS_N_INSNS (50); \
|
||||
\
|
||||
case SMIN: \
|
||||
case UMIN: \
|
||||
case SMAX: \
|
||||
case UMAX: \
|
||||
return COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50); \
|
||||
\
|
||||
case SIGN_EXTRACT: \
|
||||
case SIGN_EXTEND: \
|
||||
return COSTS_N_INSNS (TARGET_SEXT ? 1 : 2); \
|
||||
\
|
||||
case ZERO_EXTRACT: \
|
||||
case ZERO_EXTEND: \
|
||||
return COSTS_N_INSNS (1);
|
||||
|
||||
|
||||
/* An expression giving the cost of an addressing mode that
|
||||
contains ADDRESS. */
|
||||
#define ADDRESS_COST(ADDR) 1
|
||||
|
|
15
gcc/cse.c
15
gcc/cse.c
|
@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
#include "ggc.h"
|
||||
#include "timevar.h"
|
||||
#include "except.h"
|
||||
#include "target.h"
|
||||
|
||||
/* The basic idea of common subexpression elimination is to go
|
||||
through the code, keeping a record of expressions that would
|
||||
|
@ -832,7 +833,7 @@ rtx_cost (x, outer_code)
|
|||
return 0;
|
||||
|
||||
/* Compute the default costs of certain things.
|
||||
Note that RTX_COSTS can override the defaults. */
|
||||
Note that targetm.rtx_costs can override the defaults. */
|
||||
|
||||
code = GET_CODE (x);
|
||||
switch (code)
|
||||
|
@ -867,17 +868,9 @@ rtx_cost (x, outer_code)
|
|||
+ GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
|
||||
break;
|
||||
|
||||
#ifdef RTX_COSTS
|
||||
RTX_COSTS (x, code, outer_code);
|
||||
#endif
|
||||
#ifdef CONST_COSTS
|
||||
CONST_COSTS (x, code, outer_code);
|
||||
#endif
|
||||
|
||||
default:
|
||||
#ifdef DEFAULT_RTX_COSTS
|
||||
DEFAULT_RTX_COSTS (x, code, outer_code);
|
||||
#endif
|
||||
if ((*targetm.rtx_costs) (x, code, outer_code, &total))
|
||||
return total;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -5264,49 +5264,6 @@ These macros let you describe the relative speed of various operations
|
|||
on the target machine.
|
||||
|
||||
@table @code
|
||||
@findex CONST_COSTS
|
||||
@item CONST_COSTS (@var{x}, @var{code}, @var{outer_code})
|
||||
A part of a C @code{switch} statement that describes the relative costs
|
||||
of constant RTL expressions. It must contain @code{case} labels for
|
||||
expression codes @code{const_int}, @code{const}, @code{symbol_ref},
|
||||
@code{label_ref} and @code{const_double}. Each case must ultimately
|
||||
reach a @code{return} statement to return the relative cost of the use
|
||||
of that kind of constant value in an expression. The cost may depend on
|
||||
the precise value of the constant, which is available for examination in
|
||||
@var{x}, and the rtx code of the expression in which it is contained,
|
||||
found in @var{outer_code}.
|
||||
|
||||
@var{code} is the expression code---redundant, since it can be
|
||||
obtained with @code{GET_CODE (@var{x})}.
|
||||
|
||||
@findex RTX_COSTS
|
||||
@findex COSTS_N_INSNS
|
||||
@item RTX_COSTS (@var{x}, @var{code}, @var{outer_code})
|
||||
Like @code{CONST_COSTS} but applies to nonconstant RTL expressions.
|
||||
This can be used, for example, to indicate how costly a multiply
|
||||
instruction is. In writing this macro, you can use the construct
|
||||
@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast
|
||||
instructions. @var{outer_code} is the code of the expression in which
|
||||
@var{x} is contained.
|
||||
|
||||
This macro is optional; do not define it if the default cost assumptions
|
||||
are adequate for the target machine.
|
||||
|
||||
@findex DEFAULT_RTX_COSTS
|
||||
@item DEFAULT_RTX_COSTS (@var{x}, @var{code}, @var{outer_code})
|
||||
This macro, if defined, is called for any case not handled by the
|
||||
@code{RTX_COSTS} or @code{CONST_COSTS} macros. This eliminates the need
|
||||
to put case labels into the macro, but the code, or any functions it
|
||||
calls, must assume that the RTL in @var{x} could be of any type that has
|
||||
not already been handled. The arguments are the same as for
|
||||
@code{RTX_COSTS}, and the macro should execute a return statement giving
|
||||
the cost of any RTL expressions that it can handle. The default cost
|
||||
calculation is used for any RTL for which this macro does not return a
|
||||
value.
|
||||
|
||||
This macro is optional; do not define it if the default cost assumptions
|
||||
are adequate for the target machine.
|
||||
|
||||
@findex ADDRESS_COST
|
||||
@item ADDRESS_COST (@var{address})
|
||||
An expression giving the cost of an addressing mode that contains
|
||||
|
@ -5551,6 +5508,27 @@ itself with an explicit address than to call an address kept in a
|
|||
register.
|
||||
@end table
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_RTX_COSTS (rtx @var{x}, int @var{code}, int @var{outer_code}, int *@var{total})
|
||||
This target hook describes the relative costs of RTL expressions.
|
||||
|
||||
The cost may depend on the precise form of the expression, which is
|
||||
available for examination in @var{x}, and the rtx code of the expression
|
||||
in which it is contained, found in @var{outer_code}. @var{code} is the
|
||||
expression code---redundant, since it can be obtained with
|
||||
@code{GET_CODE (@var{x})}.
|
||||
|
||||
In implementing this hook, you can use the construct
|
||||
@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast
|
||||
instructions.
|
||||
|
||||
On entry to the hook, @code{*@var{total}} contains a default estimate
|
||||
for the cost of the expression. The hook should modify this value as
|
||||
necessary.
|
||||
|
||||
The hook returns true when all subexpressions of @var{x} have been
|
||||
processed, and false when @code{rtx_cost} should recurse.
|
||||
@end deftypefn
|
||||
|
||||
@node Scheduling
|
||||
@section Adjusting the Instruction Scheduler
|
||||
|
||||
|
|
11
gcc/hooks.c
11
gcc/hooks.c
|
@ -131,3 +131,14 @@ hook_bool_rtx_false (a)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
hook_bool_rtx_int_int_intp_false (a, b, c, d)
|
||||
rtx a ATTRIBUTE_UNUSED;
|
||||
int b ATTRIBUTE_UNUSED;
|
||||
int c ATTRIBUTE_UNUSED;
|
||||
int *d ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ bool hook_bool_tree_hwi_hwi_tree_false
|
|||
bool hook_bool_tree_hwi_hwi_tree_true
|
||||
PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
|
||||
bool hook_bool_rtx_false PARAMS ((rtx));
|
||||
bool hook_bool_rtx_int_int_intp_false PARAMS ((rtx, int, int, int *));
|
||||
|
||||
void hook_void_tree_int PARAMS ((tree, int));
|
||||
void hook_void_void PARAMS ((void));
|
||||
|
|
|
@ -613,7 +613,7 @@ typedef char _Bool;
|
|||
ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC MAX_CHAR_TYPE_SIZE \
|
||||
WCHAR_UNSIGNED UNIQUE_SECTION SELECT_SECTION SELECT_RTX_SECTION \
|
||||
ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL \
|
||||
ASM_OUTPUT_MI_THUNK
|
||||
ASM_OUTPUT_MI_THUNK CONST_COSTS RTX_COSTS DEFAULT_RTX_COSTS
|
||||
|
||||
/* Other obsolete target macros, or macros that used to be in target
|
||||
headers and were not used, and may be obsolete or may never have
|
||||
|
|
|
@ -262,6 +262,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
|
||||
#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
|
||||
#define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
|
||||
/* #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false */
|
||||
|
||||
#ifndef TARGET_IN_SMALL_DATA_P
|
||||
#define TARGET_IN_SMALL_DATA_P hook_bool_tree_false
|
||||
|
@ -295,6 +296,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
TARGET_ENCODE_SECTION_INFO, \
|
||||
TARGET_STRIP_NAME_ENCODING, \
|
||||
TARGET_VALID_POINTER_MODE, \
|
||||
TARGET_RTX_COSTS, \
|
||||
TARGET_HAVE_NAMED_SECTIONS, \
|
||||
TARGET_HAVE_CTORS_DTORS, \
|
||||
TARGET_HAVE_TLS, \
|
||||
|
|
|
@ -311,7 +311,16 @@ struct gcc_target
|
|||
/* Undo the effects of encode_section_info on the symbol string. */
|
||||
const char * (* strip_name_encoding) PARAMS ((const char *));
|
||||
|
||||
/* True if MODE is valid for a pointer in __attribute__((mode("MODE"))). */
|
||||
bool (* valid_pointer_mode) PARAMS ((enum machine_mode mode));
|
||||
|
||||
/* Compute a (partial) cost for rtx X. Return true if the complete
|
||||
cost has been computed, and false if subexpressions should be
|
||||
scanned. In either case, *TOTAL contains the cost result. */
|
||||
/* Note that CODE and OUTER_CODE ought to be RTX_CODE, but that's
|
||||
not necessarily defined at this point. */
|
||||
bool (* rtx_costs) PARAMS ((rtx x, int code, int outer_code, int *total));
|
||||
|
||||
/* Leave the boolean fields at the end. */
|
||||
|
||||
/* True if arbitrary sections are supported. */
|
||||
|
|
Loading…
Reference in New Issue