summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-11 17:41:24 +0000
committeraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-11 17:41:24 +0000
commit09a175857d1d874775dcd00100214ece4945d9bb (patch)
tree4b63d698c47af01f476f8ddd1376746e9309a913
parent23423d0e7757b04c88648fa3fd964ce8f61477e1 (diff)
downloadgcc-09a175857d1d874775dcd00100214ece4945d9bb.tar.gz
* 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
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c11
-rw-r--r--gcc/config/i386/i386.h16
-rw-r--r--gcc/doc/tm.texi34
-rw-r--r--gcc/doc/tm.texi.in34
-rw-r--r--gcc/ira-costs.c18
-rw-r--r--gcc/reload.c30
-rw-r--r--gcc/reload1.c4
-rw-r--r--gcc/target.def9
-rw-r--r--gcc/targhooks.c13
-rw-r--r--gcc/targhooks.h1
12 files changed, 152 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index abd433b0db4..c9501f4a14e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 75562e8be90..f23ea933ec0 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 4db819e0691..ff2be626ef0 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 62f35cae2ec..719761d2438 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 298b3b9862a..55a98972bc8 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 c97b514ee46..84a071b6242 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 24e8393dd0b..3d8298d94a0 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 e396e2537af..17d4f2838b0 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 40098b3f7e2..00c16719e13 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 9d5fe321223..f7ad80b7b8a 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 9d7ebc0a474..7a3dda3241b 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 920c91830d1..925e1f51aef 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);