Commit 7ac28727 by Andreas Krebbel Committed by Andreas Krebbel

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
parent a4edaf83
2008-05-27 Andreas Krebbel <krebbel1@de.ibm.com> 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. * defaults.h (TARGET_MEM_CONSTRAINT): New target macro added.
* postreload.c (reload_cse_simplify_operands): Replace 'm' * postreload.c (reload_cse_simplify_operands): Replace 'm'
constraint with TARGET_MEM_CONSTRAINT. constraint with TARGET_MEM_CONSTRAINT.
......
...@@ -1050,6 +1050,7 @@ have. Constraints can also require two operands to match. ...@@ -1050,6 +1050,7 @@ have. Constraints can also require two operands to match.
* Multi-Alternative:: When an insn has two alternative constraint-patterns. * Multi-Alternative:: When an insn has two alternative constraint-patterns.
* Class Preferences:: Constraints guide which hard register to put things in. * Class Preferences:: Constraints guide which hard register to put things in.
* Modifiers:: More precise control over effects of constraints. * 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. * Machine Constraints:: Existing constraints for some particular machines.
* Define Constraints:: How to define machine-specific constraints. * Define Constraints:: How to define machine-specific constraints.
* C Constraint Interface:: How to test constraints from C code. * C Constraint Interface:: How to test constraints from C code.
...@@ -3089,6 +3090,99 @@ Unsigned constant valid for BccUI instructions ...@@ -3089,6 +3090,99 @@ Unsigned constant valid for BccUI instructions
@end table @end table
@ifset INTERNALS @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 @node Define Constraints
@subsection Defining Machine-Specific Constraints @subsection Defining Machine-Specific Constraints
@cindex defining constraints @cindex defining constraints
...@@ -6521,6 +6615,22 @@ If the attribute takes numeric values, no @code{enum} type will be ...@@ -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 defined and the function to obtain the attribute's value will return
@code{int}. @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 @end ifset
@ifset INTERNALS @ifset INTERNALS
@node Expressions @node Expressions
......
...@@ -60,6 +60,14 @@ along with GCC; see the file COPYING3. If not see ...@@ -60,6 +60,14 @@ along with GCC; see the file COPYING3. If not see
#endif #endif
#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_rtx_1 (rtx *, rtx, rtx, rtx);
static void validate_replace_src_1 (rtx *, void *); static void validate_replace_src_1 (rtx *, void *);
static rtx split_insn (rtx); static rtx split_insn (rtx);
...@@ -1920,11 +1928,9 @@ extract_insn (rtx insn) ...@@ -1920,11 +1928,9 @@ extract_insn (rtx insn)
int noperands; int noperands;
rtx body = PATTERN (insn); rtx body = PATTERN (insn);
recog_data.insn = NULL;
recog_data.n_operands = 0; recog_data.n_operands = 0;
recog_data.n_alternatives = 0; recog_data.n_alternatives = 0;
recog_data.n_dups = 0; recog_data.n_dups = 0;
which_alternative = -1;
switch (GET_CODE (body)) switch (GET_CODE (body))
{ {
...@@ -2004,6 +2010,22 @@ extract_insn (rtx insn) ...@@ -2004,6 +2010,22 @@ extract_insn (rtx insn)
: OP_IN); : OP_IN);
gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES); 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 /* After calling extract_insn, you can use this function to extract some
...@@ -2033,6 +2055,12 @@ preprocess_constraints (void) ...@@ -2033,6 +2055,12 @@ preprocess_constraints (void)
op_alt[j].matches = -1; op_alt[j].matches = -1;
op_alt[j].matched = -1; op_alt[j].matched = -1;
if (!recog_data.alternative_enabled_p[j])
{
p = skip_alternative (p);
continue;
}
if (*p == '\0' || *p == ',') if (*p == '\0' || *p == ',')
{ {
op_alt[j].anything_ok = 1; op_alt[j].anything_ok = 1;
...@@ -2202,6 +2230,17 @@ constrain_operands (int strict) ...@@ -2202,6 +2230,17 @@ constrain_operands (int strict)
int lose = 0; int lose = 0;
funny_match_index = 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++) for (opno = 0; opno < recog_data.n_operands; opno++)
{ {
rtx op = recog_data.operand[opno]; rtx op = recog_data.operand[opno];
......
...@@ -143,6 +143,19 @@ recog_memoized (rtx insn) ...@@ -143,6 +143,19 @@ recog_memoized (rtx insn)
} }
#endif #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. */ /* Nonzero means volatile operands are recognized. */
extern int volatile_ok; extern int volatile_ok;
...@@ -202,6 +215,12 @@ struct recog_data ...@@ -202,6 +215,12 @@ struct recog_data
/* The number of alternatives in the constraints for the insn. */ /* The number of alternatives in the constraints for the insn. */
char n_alternatives; 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. */ /* In case we are caching, hold insn data was generated for. */
rtx insn; rtx insn;
}; };
......
...@@ -1143,8 +1143,9 @@ record_operand_costs (rtx insn, struct costs *op_costs, ...@@ -1143,8 +1143,9 @@ record_operand_costs (rtx insn, struct costs *op_costs,
record_address_regs (GET_MODE (recog_data.operand[i]), record_address_regs (GET_MODE (recog_data.operand[i]),
XEXP (recog_data.operand[i], 0), XEXP (recog_data.operand[i], 0),
0, MEM, SCRATCH, frequency * 2); 0, MEM, SCRATCH, frequency * 2);
else if (constraints[i][0] == 'p' else if (recog_data.alternative_enabled_p[0]
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])) && (constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])))
record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS, record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
SCRATCH, frequency * 2); SCRATCH, frequency * 2);
} }
...@@ -1932,6 +1933,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, ...@@ -1932,6 +1933,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
if (alt_fail) if (alt_fail)
continue; continue;
if (!recog_data.alternative_enabled_p[alt])
continue;
/* Finally, update the costs with the information we've calculated /* Finally, update the costs with the information we've calculated
about this alternative. */ about this alternative. */
......
...@@ -2523,7 +2523,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -2523,7 +2523,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
int noperands; int noperands;
/* These start out as the constraints for the insn /* These start out as the constraints for the insn
and they are chewed up as we consider alternatives. */ 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 /* These are the preferred classes for an operand, or NO_REGS if it isn't
a register. */ a register. */
enum reg_class preferred_class[MAX_RECOG_OPERANDS]; enum reg_class preferred_class[MAX_RECOG_OPERANDS];
...@@ -2630,7 +2630,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -2630,7 +2630,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
memcpy (operand_mode, recog_data.operand_mode, memcpy (operand_mode, recog_data.operand_mode,
noperands * sizeof (enum machine_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; commutative = -1;
...@@ -2641,8 +2642,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -2641,8 +2642,9 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
for (i = 0; i < noperands; i++) for (i = 0; i < noperands; i++)
{ {
char *p; const char *p;
int c; int c;
char *end;
substed_operand[i] = recog_data.operand[i]; substed_operand[i] = recog_data.operand[i];
p = constraints[i]; p = constraints[i];
...@@ -2686,7 +2688,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -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 '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': 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[c][i]
= operands_match_p (recog_data.operand[c], = operands_match_p (recog_data.operand[c],
...@@ -2914,11 +2917,21 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -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. */ a bad register class to only count 1/3 as much. */
int reject = 0; 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; this_earlyclobber = 0;
for (i = 0; i < noperands; i++) for (i = 0; i < noperands; i++)
{ {
char *p = constraints[i]; const char *p = constraints[i];
char *end; char *end;
int len; int len;
int win = 0; int win = 0;
...@@ -3717,7 +3730,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -3717,7 +3730,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
address_reloaded[commutative + 1] = t; address_reloaded[commutative + 1] = t;
memcpy (constraints, recog_data.constraints, memcpy (constraints, recog_data.constraints,
noperands * sizeof (char *)); noperands * sizeof (const char *));
goto try_swapped; goto try_swapped;
} }
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment