target.def (preferred_reload_class): New hook.

* 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.

From-SVN: r165321
This commit is contained in:
Anatoly Sokolov 2010-10-11 21:41:24 +04:00 committed by Anatoly Sokolov
parent 43c3628797
commit fba42e243e
12 changed files with 152 additions and 45 deletions

View File

@ -1,3 +1,29 @@
2010-10-11 Anatoly Sokolov <aesok@post.ru>
* 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 <ebotcazou@adacore.com>
* simplify-rtx.c (simplify_unary_operation_1): Use unsigned arithmetics

View File

@ -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);

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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,
"",

View File

@ -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

View File

@ -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);