From 09a175857d1d874775dcd00100214ece4945d9bb Mon Sep 17 00:00:00 2001 From: aesok Date: Mon, 11 Oct 2010 17:41:24 +0000 Subject: [PATCH] * target.def (preferred_reload_class): New hook. * doc/tm.texi.in (TARGET_PREFERRED_RELOAD_CLASS): Document. * doc/tm.texi: Regenerate. * targhooks.c (default_preferred_reload_class): New function. * targhooks.h (default_preferred_reload_class): Declare. * reload.c (find_dummy_reload): Change preferred_class variable type from enum reg_class to reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS target hook. (find_reloads): Change goal_alternative array type from int to reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS target hook. (push_reload, find_reloads_address_part): Use TARGET_PREFERRED_RELOAD_CLASS target hook. * reload1.c (emit_input_reload_insns): Ditto. * ira-costs.c (copy_cost): Use TARGET_PREFERRED_RELOAD_CLASS target hook. Change rclass argument and secondary_class variable types from 'enum reg_class' to reg_class_t. * config/i386/i386.h (PREFERRED_RELOAD_CLASS): Remove. * config/i386/i386-protos (ix86_preferred_reload_class): Remove. * config/i386/i386.c (ix86_preferred_reload_class): Make static. Change regclass argument and result types from enum reg_class to reg_class_t. (TARGET_PREFERRED_RELOAD_CLASS): Define. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165321 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 26 ++++++++++++++++++++++++++ gcc/config/i386/i386-protos.h | 1 - gcc/config/i386/i386.c | 11 ++++++++--- gcc/config/i386/i386.h | 16 ---------------- gcc/doc/tm.texi | 34 ++++++++++++++++++++++++++++++++++ gcc/doc/tm.texi.in | 34 ++++++++++++++++++++++++++++++++++ gcc/ira-costs.c | 18 ++++++++++-------- gcc/reload.c | 30 +++++++++++++++--------------- gcc/reload1.c | 4 ++-- gcc/target.def | 9 +++++++++ gcc/targhooks.c | 13 +++++++++++++ gcc/targhooks.h | 1 + 12 files changed, 152 insertions(+), 45 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index abd433b..c9501f4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2010-10-11 Anatoly Sokolov + + * target.def (preferred_reload_class): New hook. + * doc/tm.texi.in (TARGET_PREFERRED_RELOAD_CLASS): Document. + * doc/tm.texi: Regenerate. + * targhooks.c (default_preferred_reload_class): New function. + * targhooks.h (default_preferred_reload_class): Declare. + * reload.c (find_dummy_reload): Change preferred_class variable type + from enum reg_class to reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS + target hook. + (find_reloads): Change goal_alternative array type from int to + reg_class_t. Use TARGET_PREFERRED_RELOAD_CLASS target hook. + (push_reload, find_reloads_address_part): Use + TARGET_PREFERRED_RELOAD_CLASS target hook. + * reload1.c (emit_input_reload_insns): Ditto. + * ira-costs.c (copy_cost): Use TARGET_PREFERRED_RELOAD_CLASS target + hook. Change rclass argument and secondary_class variable types from + 'enum reg_class' to reg_class_t. + + * config/i386/i386.h (PREFERRED_RELOAD_CLASS): Remove. + * config/i386/i386-protos (ix86_preferred_reload_class): Remove. + * config/i386/i386.c (ix86_preferred_reload_class): Make static. + Change regclass argument and result types from enum reg_class to + reg_class_t. + (TARGET_PREFERRED_RELOAD_CLASS): Define. + 2010-10-11 Eric Botcazou * simplify-rtx.c (simplify_unary_operation_1): Use unsigned arithmetics diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 75562e8..f23ea93 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -153,7 +153,6 @@ extern bool ix86_secondary_memory_needed (enum reg_class, enum reg_class, enum machine_mode, int); extern bool ix86_cannot_change_mode_class (enum machine_mode, enum machine_mode, enum reg_class); -extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class); extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class); extern int ix86_mode_needed (int, rtx); extern void emit_i387_cw_initialization (int); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4db819e..ff2be62 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -26650,12 +26650,15 @@ i386_ira_cover_classes (void) return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes; } -/* Put float CONST_DOUBLE in the constant pool instead of fp regs. +/* Implement TARGET_PREFERRED_RELOAD_CLASS. + + Put float CONST_DOUBLE in the constant pool instead of fp regs. QImode must go into class Q_REGS. Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and movdf to do mem-to-mem moves through integer regs. */ -enum reg_class -ix86_preferred_reload_class (rtx x, enum reg_class regclass) + +static reg_class_t +ix86_preferred_reload_class (rtx x, reg_class_t regclass) { enum machine_mode mode = GET_MODE (x); @@ -33295,6 +33298,8 @@ ix86_autovectorize_vector_sizes (void) #undef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD ix86_secondary_reload +#undef TARGET_PREFERRED_RELOAD_CLASS +#define TARGET_PREFERRED_RELOAD_CLASS ix86_preferred_reload_class #undef TARGET_CLASS_LIKELY_SPILLED_P #define TARGET_CLASS_LIKELY_SPILLED_P ix86_class_likely_spilled_p diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 62f35ca..719761d 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1373,22 +1373,6 @@ enum reg_class || (CLASS) == LEGACY_REGS || (CLASS) == INDEX_REGS) \ ? Q_REGS : (CLASS)) -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - On the 80386 series, we prevent floating constants from being - reloaded into floating registers (since no move-insn can do that) - and we ensure that QImodes aren't reloaded into the esi or edi reg. */ - -/* Put float CONST_DOUBLE in the constant pool instead of fp regs. - QImode must go into class Q_REGS. - Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and - movdf to do mem-to-mem moves through integer regs. */ - -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - ix86_preferred_reload_class ((X), (CLASS)) - /* Discourage putting floating-point values in SSE registers unless SSE math is being used, and likewise for the 387 registers. */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 298b3b9..55a9897 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2585,6 +2585,40 @@ only if neither labeling works. This macro also has strict and non-strict variants. @end defmac +@deftypefn {Target Hook} reg_class_t TARGET_PREFERRED_RELOAD_CLASS (rtx @var{x}, reg_class_t @var{rclass}) +A target hook that places additional restrictions on the register class +to use when it is necessary to copy value @var{x} into a register in class +@var{rclass}. The value is a register class; perhaps @var{rclass}, or perhaps +another, smaller class. + +The default version of this hook always returns value of @code{rclass} argument. + +Sometimes returning a more restrictive class makes better code. For +example, on the 68000, when @var{x} is an integer constant that is in range +for a @samp{moveq} instruction, the value of this macro is always +@code{DATA_REGS} as long as @var{rclass} includes the data registers. +Requiring a data register guarantees that a @samp{moveq} will be used. + +One case where @code{TARGET_PREFERRED_RELOAD_CLASS} must not return +@var{rclass} is if @var{x} is a legitimate constant which cannot be +loaded into some register class. By returning @code{NO_REGS} you can +force @var{x} into a memory location. For example, rs6000 can load +immediate values into general-purpose registers, but does not have an +instruction for loading an immediate value into a floating-point +register, so @code{TARGET_PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when +@var{x} is a floating-point constant. If the constant can't be loaded +into any kind of register, code generation will be better if +@code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead +of using @code{TARGET_PREFERRED_RELOAD_CLASS}. + +If an insn has pseudos in it after register allocation, reload will go +through the alternatives and call repeatedly @code{TARGET_PREFERRED_RELOAD_CLASS} +to find the best one. Returning @code{NO_REGS}, in this case, makes +reload add a @code{!} in front of the constraint: the x86 back-end uses +this feature to discourage usage of 387 registers when math is done in +the SSE registers (and vice versa). +@end deftypefn + @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class}) A C expression that places additional restrictions on the register class to use when it is necessary to copy value @var{x} into a register in class diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index c97b514..84a071b 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -2583,6 +2583,40 @@ only if neither labeling works. This macro also has strict and non-strict variants. @end defmac +@hook TARGET_PREFERRED_RELOAD_CLASS +A target hook that places additional restrictions on the register class +to use when it is necessary to copy value @var{x} into a register in class +@var{rclass}. The value is a register class; perhaps @var{rclass}, or perhaps +another, smaller class. + +The default version of this hook always returns value of @code{rclass} argument. + +Sometimes returning a more restrictive class makes better code. For +example, on the 68000, when @var{x} is an integer constant that is in range +for a @samp{moveq} instruction, the value of this macro is always +@code{DATA_REGS} as long as @var{rclass} includes the data registers. +Requiring a data register guarantees that a @samp{moveq} will be used. + +One case where @code{TARGET_PREFERRED_RELOAD_CLASS} must not return +@var{rclass} is if @var{x} is a legitimate constant which cannot be +loaded into some register class. By returning @code{NO_REGS} you can +force @var{x} into a memory location. For example, rs6000 can load +immediate values into general-purpose registers, but does not have an +instruction for loading an immediate value into a floating-point +register, so @code{TARGET_PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when +@var{x} is a floating-point constant. If the constant can't be loaded +into any kind of register, code generation will be better if +@code{LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead +of using @code{TARGET_PREFERRED_RELOAD_CLASS}. + +If an insn has pseudos in it after register allocation, reload will go +through the alternatives and call repeatedly @code{TARGET_PREFERRED_RELOAD_CLASS} +to find the best one. Returning @code{NO_REGS}, in this case, makes +reload add a @code{!} in front of the constraint: the x86 back-end uses +this feature to discourage usage of 387 registers when math is done in +the SSE registers (and vice versa). +@end deftypefn + @defmac PREFERRED_RELOAD_CLASS (@var{x}, @var{class}) A C expression that places additional restrictions on the register class to use when it is necessary to copy value @var{x} into a register in class diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 24e8393..3d8298d 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -131,11 +131,11 @@ static int frequency; TO_P is FALSE) a register of class RCLASS in mode MODE. X must not be a pseudo register. */ static int -copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p, +copy_cost (rtx x, enum machine_mode mode, reg_class_t rclass, bool to_p, secondary_reload_info *prev_sri) { secondary_reload_info sri; - enum reg_class secondary_class = NO_REGS; + reg_class_t secondary_class = NO_REGS; /* If X is a SCRATCH, there is actually nothing to move since we are assuming optimal allocation. */ @@ -143,21 +143,21 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p, return 0; /* Get the class we will actually use for a reload. */ - rclass = PREFERRED_RELOAD_CLASS (x, rclass); + rclass = targetm.preferred_reload_class (x, rclass); /* If we need a secondary reload for an intermediate, the cost is that to load the input into the intermediate register, then to copy it. */ sri.prev_sri = prev_sri; sri.extra_cost = 0; - secondary_class - = (enum reg_class) targetm.secondary_reload (to_p, x, rclass, mode, &sri); + secondary_class = targetm.secondary_reload (to_p, x, rclass, mode, &sri); if (secondary_class != NO_REGS) { if (!move_cost[mode]) init_move_cost (mode); - return (move_cost[mode][secondary_class][rclass] + sri.extra_cost + return (move_cost[mode][(int) secondary_class][(int) rclass] + + sri.extra_cost + copy_cost (x, mode, secondary_class, to_p, &sri)); } @@ -165,12 +165,14 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p, the cost to move between the register classes, and use 2 for everything else (constants). */ if (MEM_P (x) || rclass == NO_REGS) - return sri.extra_cost + ira_memory_move_cost[mode][rclass][to_p != 0]; + return sri.extra_cost + + ira_memory_move_cost[mode][(int) rclass][to_p != 0]; else if (REG_P (x)) { if (!move_cost[mode]) init_move_cost (mode); - return (sri.extra_cost + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]); + return (sri.extra_cost + + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][(int) rclass]); } else /* If this is a constant, we may eventually want to call rtx_cost diff --git a/gcc/reload.c b/gcc/reload.c index e396e25..17d4f28 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -1227,7 +1227,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, enum reg_class preferred_class = rclass; if (in != 0) - preferred_class = PREFERRED_RELOAD_CLASS (in, rclass); + preferred_class = (enum reg_class) targetm.preferred_reload_class (in, rclass); /* Output reloads may need analogous treatment, different in detail. */ #ifdef PREFERRED_OUTPUT_RELOAD_CLASS @@ -1963,9 +1963,9 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc, /* Narrow down the reg class, the same way push_reload will; otherwise we might find a dummy now, but push_reload won't. */ { - enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, rclass); + reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass); if (preferred_class != NO_REGS) - rclass = preferred_class; + rclass = (enum reg_class) preferred_class; } /* See if OUT will do. */ @@ -2595,7 +2595,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, char this_alternative_earlyclobber[MAX_RECOG_OPERANDS]; int this_alternative_matches[MAX_RECOG_OPERANDS]; int swapped; - int goal_alternative[MAX_RECOG_OPERANDS]; + reg_class_t goal_alternative[MAX_RECOG_OPERANDS]; int this_alternative_number; int goal_alternative_number = 0; int operand_reloadnum[MAX_RECOG_OPERANDS]; @@ -3506,7 +3506,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, precisely the same as in the code below that calls force_const_mem. */ if (CONST_POOL_OK_P (operand) - && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) + && ((targetm.preferred_reload_class (operand, + this_alternative[i]) == NO_REGS) || no_input_reloads) && operand_mode[i] != VOIDmode) @@ -3534,7 +3535,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS) { - if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i]) + if (targetm.preferred_reload_class (operand, this_alternative[i]) == NO_REGS) reject = 600; @@ -3695,7 +3696,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, { goal_alternative_win[i] = this_alternative_win[i]; goal_alternative_match_win[i] = this_alternative_match_win[i]; - goal_alternative[i] = this_alternative[i]; + goal_alternative[i] = (reg_class_t) this_alternative[i]; goal_alternative_offmemok[i] = this_alternative_offmemok[i]; goal_alternative_matches[i] = this_alternative_matches[i]; goal_alternative_earlyclobber[i] @@ -3722,7 +3723,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, { for (i = 0; i < noperands; i++) { - goal_alternative[i] = this_alternative[i]; + goal_alternative[i] = (reg_class_t) this_alternative[i]; goal_alternative_win[i] = this_alternative_win[i]; goal_alternative_match_win[i] = this_alternative_match_win[i]; @@ -3915,8 +3916,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, } if (CONST_POOL_OK_P (op) - && ((PREFERRED_RELOAD_CLASS (op, - (enum reg_class) goal_alternative[i]) + && ((targetm.preferred_reload_class (op, goal_alternative[i]) == NO_REGS) || no_input_reloads) && mode != VOIDmode) @@ -4094,7 +4094,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, /* If this is only for an output, the optional reload would not actually cause us to use a register now, just note that something is stored here. */ - && ((enum reg_class) goal_alternative[i] != NO_REGS + && (goal_alternative[i] != NO_REGS || modified[i] == RELOAD_WRITE) && ! no_input_reloads /* An optional output reload might allow to delete INSN later. @@ -4168,8 +4168,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, if ((MEM_P (operand) || (REG_P (operand) && REGNO (operand) >= FIRST_PSEUDO_REGISTER)) - && ((enum reg_class) goal_alternative[goal_alternative_matches[i]] - != NO_REGS)) + && (goal_alternative[goal_alternative_matches[i]] != NO_REGS)) operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]] = push_reload (recog_data.operand[goal_alternative_matches[i]], recog_data.operand[i], @@ -6048,7 +6047,7 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, { if (CONSTANT_P (x) && (! LEGITIMATE_CONSTANT_P (x) - || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS)) + || targetm.preferred_reload_class (x, rclass) == NO_REGS)) { x = force_const_mem (mode, x); find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0), @@ -6058,7 +6057,8 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, else if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)) && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1)) - || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS)) + || targetm.preferred_reload_class (XEXP (x, 1), rclass) + == NO_REGS)) { rtx tem; diff --git a/gcc/reload1.c b/gcc/reload1.c index 40098b3..00c1671 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -7500,8 +7500,8 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl, || (reg_equiv_constant [REGNO (SUBREG_REG (oldequiv))] != 0))) || (CONSTANT_P (oldequiv) - && (PREFERRED_RELOAD_CLASS (oldequiv, - REGNO_REG_CLASS (REGNO (reloadreg))) + && (targetm.preferred_reload_class (oldequiv, + REGNO_REG_CLASS (REGNO (reloadreg))) == NO_REGS))) real_oldequiv = rl->in; gen_reload (reloadreg, real_oldequiv, rl->opnum, diff --git a/gcc/target.def b/gcc/target.def index 9d5fe32..f7ad80b 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2033,6 +2033,15 @@ DEFHOOK secondary_reload_info *sri), default_secondary_reload) +/* Given an rtx X being reloaded into a reg required to be in class CLASS, + return the class of reg to actually use. */ +DEFHOOK +(preferred_reload_class, + "", + reg_class_t, + (rtx x, reg_class_t rclass), + default_preferred_reload_class) + DEFHOOK (class_likely_spilled_p, "", diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 9d7ebc0..7a3dda3 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1230,6 +1230,19 @@ default_profile_before_prologue (void) #endif } +/* The default implementation of TARGET_PREFERRED_RELOAD_CLASS. */ + +reg_class_t +default_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, + reg_class_t rclass) +{ +#ifdef PREFERRED_RELOAD_CLASS + return (reg_class_t) PREFERRED_RELOAD_CLASS (x, (enum reg_class) rclass); +#else + return rclass; +#endif +} + /* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P. */ bool diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 920c9183..925e1f5 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -154,6 +154,7 @@ extern int default_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); extern bool default_profile_before_prologue (void); +extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern bool default_class_likely_spilled_p (reg_class_t); extern enum unwind_info_type default_debug_unwind_info (void); -- 2.7.4