mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 22:41:28 +08:00
reload.c: (find_reloads): Skip alternatives according to the "enabled" attribute.
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com> * reload.c: (find_reloads): Skip alternatives according to the "enabled" attribute. Constify the constraint variable. * recog.c (get_attr_enabled): Add default implementation. (extract_insn): Set the alternative_enabled_p array in the recog_data struct. (preprocess_constraints, constrain_operands): Skip alternatives according to the "enabled" attribute * recog.h (struct recog_data): New field alternative_enabled_p. (skip_alternative): New inline function. * regclass.c: (record_operand_costs): Check the "enabled" attribute. (record_reg_classes): Skip alternative according to the "enabled" attribute. * doc/md.texi: Add documention for the "enabled" attribute. From-SVN: r136012
This commit is contained in:
parent
a4edaf8359
commit
7ac28727fb
@ -1,3 +1,21 @@
|
||||
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* reload.c: (find_reloads): Skip alternatives according to the
|
||||
"enabled" attribute. Constify the constraint variable.
|
||||
* recog.c (get_attr_enabled): Add default implementation.
|
||||
(extract_insn): Set the alternative_enabled_p array
|
||||
in the recog_data struct.
|
||||
(preprocess_constraints, constrain_operands): Skip
|
||||
alternatives according to the "enabled" attribute
|
||||
* recog.h (struct recog_data): New field alternative_enabled_p.
|
||||
(skip_alternative): New inline function.
|
||||
* regclass.c: (record_operand_costs): Check the "enabled"
|
||||
attribute.
|
||||
(record_reg_classes): Skip alternative according to the
|
||||
"enabled" attribute.
|
||||
|
||||
* doc/md.texi: Add documention for the "enabled" attribute.
|
||||
|
||||
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* defaults.h (TARGET_MEM_CONSTRAINT): New target macro added.
|
||||
|
110
gcc/doc/md.texi
110
gcc/doc/md.texi
@ -1050,6 +1050,7 @@ have. Constraints can also require two operands to match.
|
||||
* Multi-Alternative:: When an insn has two alternative constraint-patterns.
|
||||
* Class Preferences:: Constraints guide which hard register to put things in.
|
||||
* Modifiers:: More precise control over effects of constraints.
|
||||
* Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute.
|
||||
* Machine Constraints:: Existing constraints for some particular machines.
|
||||
* Define Constraints:: How to define machine-specific constraints.
|
||||
* C Constraint Interface:: How to test constraints from C code.
|
||||
@ -3088,6 +3089,99 @@ Unsigned constant valid for BccUI instructions
|
||||
|
||||
@end table
|
||||
|
||||
@ifset INTERNALS
|
||||
@node Disable Insn Alternatives
|
||||
@subsection Disable insn alternatives using the @code{enabled} attribute
|
||||
@cindex enabled
|
||||
|
||||
The @code{enabled} insn attribute may be used to disable certain insn
|
||||
alternatives for machine-specific reasons. This is useful when adding
|
||||
new instructions to an existing pattern which are only available for
|
||||
certain cpu architecture levels as specified with the @code{-march=}
|
||||
option.
|
||||
|
||||
If an insn alternative is disabled, then it will never be used. The
|
||||
compiler treats the constraints for the disabled alternative as
|
||||
unsatisfiable.
|
||||
|
||||
In order to make use of the @code{enabled} attribute a back end has to add
|
||||
in the machine description files:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
A definition of the @code{enabled} insn attribute. The attribute is
|
||||
defined as usual using the @code{define_attr} command. This
|
||||
definition should be based on other insn attributes and/or target flags.
|
||||
The @code{enabled} attribute is a numeric attribute and should evaluate to
|
||||
@code{(const_int 1)} for an enabled alternative and to
|
||||
@code{(const_int 0)} otherwise.
|
||||
@item
|
||||
A definition of another insn attribute used to describe for what
|
||||
reason an insn alternative might be available or
|
||||
not. E.g. @code{cpu_facility} as in the example below.
|
||||
@item
|
||||
An assignement for the second attribute to each insn definition
|
||||
combining instructions which are not all available under the same
|
||||
circumstances. (Note: It obviously only makes sense for definitions
|
||||
with more than one alternative. Otherwise the insn pattern should be
|
||||
disabled or enabled using the insn condition.)
|
||||
@end enumerate
|
||||
|
||||
E.g. the following two patterns could easily be merged using the @code{enabled}
|
||||
attribute:
|
||||
|
||||
@smallexample
|
||||
|
||||
(define_insn "*movdi_old"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(match_operand:DI 1 "register_operand" " d"))]
|
||||
"!TARGET_NEW"
|
||||
"lgr %0,%1")
|
||||
|
||||
(define_insn "*movdi_new"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d,f,d")
|
||||
(match_operand:DI 1 "register_operand" " d,d,f"))]
|
||||
"TARGET_NEW"
|
||||
"@@
|
||||
lgr %0,%1
|
||||
ldgr %0,%1
|
||||
lgdr %0,%1")
|
||||
|
||||
@end smallexample
|
||||
|
||||
to:
|
||||
|
||||
@smallexample
|
||||
|
||||
(define_insn "*movdi_combined"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d,f,d")
|
||||
(match_operand:DI 1 "register_operand" " d,d,f"))]
|
||||
""
|
||||
"@@
|
||||
lgr %0,%1
|
||||
ldgr %0,%1
|
||||
lgdr %0,%1"
|
||||
[(set_attr "cpu_facility" "*,new,new")])
|
||||
|
||||
@end smallexample
|
||||
|
||||
with the @code{enabled} attribute defined like this:
|
||||
|
||||
@smallexample
|
||||
|
||||
(define_attr "cpu_facility" "standard,new" (const_string "standard"))
|
||||
|
||||
(define_attr "enabled" ""
|
||||
(cond [(eq_attr "cpu_facility" "standard") (const_int 1)
|
||||
(and (eq_attr "cpu_facility" "new")
|
||||
(ne (symbol_ref "TARGET_NEW") (const_int 0)))
|
||||
(const_int 1)]
|
||||
(const_int 0)))
|
||||
|
||||
@end smallexample
|
||||
|
||||
@end ifset
|
||||
|
||||
@ifset INTERNALS
|
||||
@node Define Constraints
|
||||
@subsection Defining Machine-Specific Constraints
|
||||
@ -6521,6 +6615,22 @@ If the attribute takes numeric values, no @code{enum} type will be
|
||||
defined and the function to obtain the attribute's value will return
|
||||
@code{int}.
|
||||
|
||||
There are attributes which are tied to a specific meaning. These
|
||||
attributes are not free to use for other purposes:
|
||||
|
||||
@table @code
|
||||
@item length
|
||||
The @code{length} attribute is used to calculate the length of emitted
|
||||
code chunks. This is especially important when verifying branch
|
||||
distances. @xref{Insn Lengths}.
|
||||
|
||||
@item enabled
|
||||
The @code{enabled} attribute can be defined to prevent certain
|
||||
alternatives of an insn definition from being used during code
|
||||
generation. @xref{Disable Insn Alternatives}.
|
||||
|
||||
@end table
|
||||
|
||||
@end ifset
|
||||
@ifset INTERNALS
|
||||
@node Expressions
|
||||
|
43
gcc/recog.c
43
gcc/recog.c
@ -60,6 +60,14 @@ along with GCC; see the file COPYING3. If not see
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ATTR_enabled
|
||||
static inline bool
|
||||
get_attr_enabled (rtx insn ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
|
||||
static void validate_replace_src_1 (rtx *, void *);
|
||||
static rtx split_insn (rtx);
|
||||
@ -1920,11 +1928,9 @@ extract_insn (rtx insn)
|
||||
int noperands;
|
||||
rtx body = PATTERN (insn);
|
||||
|
||||
recog_data.insn = NULL;
|
||||
recog_data.n_operands = 0;
|
||||
recog_data.n_alternatives = 0;
|
||||
recog_data.n_dups = 0;
|
||||
which_alternative = -1;
|
||||
|
||||
switch (GET_CODE (body))
|
||||
{
|
||||
@ -2004,6 +2010,22 @@ extract_insn (rtx insn)
|
||||
: OP_IN);
|
||||
|
||||
gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
|
||||
|
||||
if (INSN_CODE (insn) < 0)
|
||||
for (i = 0; i < recog_data.n_alternatives; i++)
|
||||
recog_data.alternative_enabled_p[i] = true;
|
||||
else
|
||||
{
|
||||
recog_data.insn = insn;
|
||||
for (i = 0; i < recog_data.n_alternatives; i++)
|
||||
{
|
||||
which_alternative = i;
|
||||
recog_data.alternative_enabled_p[i] = get_attr_enabled (insn);
|
||||
}
|
||||
}
|
||||
|
||||
recog_data.insn = NULL;
|
||||
which_alternative = -1;
|
||||
}
|
||||
|
||||
/* After calling extract_insn, you can use this function to extract some
|
||||
@ -2033,6 +2055,12 @@ preprocess_constraints (void)
|
||||
op_alt[j].matches = -1;
|
||||
op_alt[j].matched = -1;
|
||||
|
||||
if (!recog_data.alternative_enabled_p[j])
|
||||
{
|
||||
p = skip_alternative (p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p == '\0' || *p == ',')
|
||||
{
|
||||
op_alt[j].anything_ok = 1;
|
||||
@ -2202,6 +2230,17 @@ constrain_operands (int strict)
|
||||
int lose = 0;
|
||||
funny_match_index = 0;
|
||||
|
||||
if (!recog_data.alternative_enabled_p[which_alternative])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
constraints[i] = skip_alternative (constraints[i]);
|
||||
|
||||
which_alternative++;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (opno = 0; opno < recog_data.n_operands; opno++)
|
||||
{
|
||||
rtx op = recog_data.operand[opno];
|
||||
|
19
gcc/recog.h
19
gcc/recog.h
@ -143,6 +143,19 @@ recog_memoized (rtx insn)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Skip chars until the next ',' or the end of the string. This is
|
||||
useful to skip alternatives in a constraint string. */
|
||||
static inline const char *
|
||||
skip_alternative (const char *p)
|
||||
{
|
||||
const char *r = p;
|
||||
while (*r != '\0' && *r != ',')
|
||||
r++;
|
||||
if (*r == ',')
|
||||
r++;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Nonzero means volatile operands are recognized. */
|
||||
extern int volatile_ok;
|
||||
|
||||
@ -202,6 +215,12 @@ struct recog_data
|
||||
/* The number of alternatives in the constraints for the insn. */
|
||||
char n_alternatives;
|
||||
|
||||
/* Specifies whether an insn alternative is enabled using the
|
||||
`enabled' attribute in the insn pattern definition. For back
|
||||
ends not using the `enabled' attribute the array fields are
|
||||
always set to `true' in expand_insn. */
|
||||
bool alternative_enabled_p [MAX_RECOG_ALTERNATIVES];
|
||||
|
||||
/* In case we are caching, hold insn data was generated for. */
|
||||
rtx insn;
|
||||
};
|
||||
|
@ -1143,8 +1143,9 @@ record_operand_costs (rtx insn, struct costs *op_costs,
|
||||
record_address_regs (GET_MODE (recog_data.operand[i]),
|
||||
XEXP (recog_data.operand[i], 0),
|
||||
0, MEM, SCRATCH, frequency * 2);
|
||||
else if (constraints[i][0] == 'p'
|
||||
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
|
||||
else if (recog_data.alternative_enabled_p[0]
|
||||
&& (constraints[i][0] == 'p'
|
||||
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])))
|
||||
record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
|
||||
SCRATCH, frequency * 2);
|
||||
}
|
||||
@ -1932,6 +1933,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||
if (alt_fail)
|
||||
continue;
|
||||
|
||||
if (!recog_data.alternative_enabled_p[alt])
|
||||
continue;
|
||||
|
||||
/* Finally, update the costs with the information we've calculated
|
||||
about this alternative. */
|
||||
|
||||
|
25
gcc/reload.c
25
gcc/reload.c
@ -2523,7 +2523,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
int noperands;
|
||||
/* These start out as the constraints for the insn
|
||||
and they are chewed up as we consider alternatives. */
|
||||
char *constraints[MAX_RECOG_OPERANDS];
|
||||
const char *constraints[MAX_RECOG_OPERANDS];
|
||||
/* These are the preferred classes for an operand, or NO_REGS if it isn't
|
||||
a register. */
|
||||
enum reg_class preferred_class[MAX_RECOG_OPERANDS];
|
||||
@ -2630,7 +2630,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
|
||||
memcpy (operand_mode, recog_data.operand_mode,
|
||||
noperands * sizeof (enum machine_mode));
|
||||
memcpy (constraints, recog_data.constraints, noperands * sizeof (char *));
|
||||
memcpy (constraints, recog_data.constraints,
|
||||
noperands * sizeof (const char *));
|
||||
|
||||
commutative = -1;
|
||||
|
||||
@ -2641,8 +2642,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
|
||||
for (i = 0; i < noperands; i++)
|
||||
{
|
||||
char *p;
|
||||
const char *p;
|
||||
int c;
|
||||
char *end;
|
||||
|
||||
substed_operand[i] = recog_data.operand[i];
|
||||
p = constraints[i];
|
||||
@ -2686,7 +2688,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
c = strtoul (p - 1, &p, 10);
|
||||
c = strtoul (p - 1, &end, 10);
|
||||
p = end;
|
||||
|
||||
operands_match[c][i]
|
||||
= operands_match_p (recog_data.operand[c],
|
||||
@ -2914,11 +2917,21 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
a bad register class to only count 1/3 as much. */
|
||||
int reject = 0;
|
||||
|
||||
if (!recog_data.alternative_enabled_p[this_alternative_number])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
constraints[i] = skip_alternative (constraints[i]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
this_earlyclobber = 0;
|
||||
|
||||
for (i = 0; i < noperands; i++)
|
||||
{
|
||||
char *p = constraints[i];
|
||||
const char *p = constraints[i];
|
||||
char *end;
|
||||
int len;
|
||||
int win = 0;
|
||||
@ -3717,7 +3730,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
|
||||
address_reloaded[commutative + 1] = t;
|
||||
|
||||
memcpy (constraints, recog_data.constraints,
|
||||
noperands * sizeof (char *));
|
||||
noperands * sizeof (const char *));
|
||||
goto try_swapped;
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user