md.texi: Document "preferred_for_size" and "preferred_for_speed" attributes.
gcc/ * doc/md.texi: Document "preferred_for_size" and "preferred_for_speed" attributes. * genattr.c (main): Handle "preferred_for_size" and "preferred_for_speed" in the same way as "enabled". * recog.h (bool_attr): New enum. (target_recog): Replace x_enabled_alternatives with x_bool_attr_masks. (get_preferred_alternatives, check_bool_attrs): Declare. * recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached) (get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs): New functions. (get_enabled_alternatives): Use get_bool_attr_mask. * ira-costs.c (record_reg_classes): Use get_preferred_alternatives instead of recog_data.enabled_alternatives. * ira.c (ira_setup_alts): Likewise. * postreload.c (reload_cse_simplify_operands): Likewise. * config/i386/i386.c (ix86_legitimate_combined_insn): Likewise. * ira-lives.c (preferred_alternatives): New variable. (process_bb_node_lives): Set it. (check_and_make_def_conflict, make_early_clobber_and_input_conflicts) (single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead of recog_data.enabled_alternatives. * lra-int.h (lra_insn_recog_data): Replace enabled_alternatives to preferred_alternatives. * lra-constraints.c (process_alt_operands): Update accordingly. * lra.c (lra_set_insn_recog_data): Likewise. (lra_update_insn_recog_data): Assert check_bool_attrs. From-SVN: r216554
This commit is contained in:
parent
75d25a02fc
commit
9840b2fa87
|
@ -1,3 +1,32 @@
|
|||
2014-10-22 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
|
||||
attributes.
|
||||
* genattr.c (main): Handle "preferred_for_size" and
|
||||
"preferred_for_speed" in the same way as "enabled".
|
||||
* recog.h (bool_attr): New enum.
|
||||
(target_recog): Replace x_enabled_alternatives with x_bool_attr_masks.
|
||||
(get_preferred_alternatives, check_bool_attrs): Declare.
|
||||
* recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached)
|
||||
(get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs):
|
||||
New functions.
|
||||
(get_enabled_alternatives): Use get_bool_attr_mask.
|
||||
* ira-costs.c (record_reg_classes): Use get_preferred_alternatives
|
||||
instead of recog_data.enabled_alternatives.
|
||||
* ira.c (ira_setup_alts): Likewise.
|
||||
* postreload.c (reload_cse_simplify_operands): Likewise.
|
||||
* config/i386/i386.c (ix86_legitimate_combined_insn): Likewise.
|
||||
* ira-lives.c (preferred_alternatives): New variable.
|
||||
(process_bb_node_lives): Set it.
|
||||
(check_and_make_def_conflict, make_early_clobber_and_input_conflicts)
|
||||
(single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead
|
||||
of recog_data.enabled_alternatives.
|
||||
* lra-int.h (lra_insn_recog_data): Replace enabled_alternatives
|
||||
to preferred_alternatives.
|
||||
* lra-constraints.c (process_alt_operands): Update accordingly.
|
||||
* lra.c (lra_set_insn_recog_data): Likewise.
|
||||
(lra_update_insn_recog_data): Assert check_bool_attrs.
|
||||
|
||||
2014-10-22 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* recog.h (extract_constrain_insn): Declare.
|
||||
|
|
|
@ -5905,10 +5905,10 @@ ix86_legitimate_combined_insn (rtx_insn *insn)
|
|||
/* Operand has no constraints, anything is OK. */
|
||||
win = !n_alternatives;
|
||||
|
||||
alternative_mask enabled = recog_data.enabled_alternatives;
|
||||
alternative_mask preferred = get_preferred_alternatives (insn);
|
||||
for (j = 0; j < n_alternatives; j++, op_alt += n_operands)
|
||||
{
|
||||
if (!TEST_BIT (enabled, j))
|
||||
if (!TEST_BIT (preferred, j))
|
||||
continue;
|
||||
if (op_alt[i].anything_ok
|
||||
|| (op_alt[i].matches != -1
|
||||
|
|
|
@ -1080,7 +1080,7 @@ the addressing register.
|
|||
* Class Preferences:: Constraints guide which hard register to put things in.
|
||||
* Modifiers:: More precise control over effects of constraints.
|
||||
* Machine Constraints:: Existing constraints for some particular machines.
|
||||
* Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute.
|
||||
* Disable Insn Alternatives:: Disable insn alternatives using attributes.
|
||||
* Define Constraints:: How to define machine-specific constraints.
|
||||
* C Constraint Interface:: How to test constraints from C code.
|
||||
@end menu
|
||||
|
@ -4006,42 +4006,49 @@ Unsigned constant valid for BccUI instructions
|
|||
@subsection Disable insn alternatives using the @code{enabled} attribute
|
||||
@cindex enabled
|
||||
|
||||
The @code{enabled} insn attribute may be used to disable insn
|
||||
alternatives that are not available for the current subtarget.
|
||||
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.
|
||||
There are three insn attributes that may be used to selectively disable
|
||||
instruction alternatives:
|
||||
|
||||
If an insn alternative is disabled, then it will never be used. The
|
||||
compiler treats the constraints for the disabled alternative as
|
||||
unsatisfiable.
|
||||
@table @code
|
||||
@item enabled
|
||||
Says whether an alternative is available on the current subtarget.
|
||||
|
||||
In order to make use of the @code{enabled} attribute a back end has to add
|
||||
in the machine description files:
|
||||
@item preferred_for_size
|
||||
Says whether an enabled alternative should be used in code that is
|
||||
optimized for size.
|
||||
|
||||
@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 attribute must be a static property of the subtarget; that is, it
|
||||
must not depend on the current operands or any other dynamic context
|
||||
(for example, the location of the insn within the body of a loop).
|
||||
@item preferred_for_speed
|
||||
Says whether an enabled alternative should be used in code that is
|
||||
optimized for speed.
|
||||
@end table
|
||||
|
||||
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 assignment 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
|
||||
All these attributes should use @code{(const_int 1)} to allow an alternative
|
||||
or @code{(const_int 0)} to disallow it. The attributes must be a static
|
||||
property of the subtarget; they cannot for example depend on the
|
||||
current operands, on the current optimization level, on the location
|
||||
of the insn within the body of a loop, on whether register allocation
|
||||
has finished, or on the current compiler pass.
|
||||
|
||||
The @code{enabled} attribute is a correctness property. It tells GCC to act
|
||||
as though the disabled alternatives were never defined in the first place.
|
||||
This is useful when adding new instructions to an existing pattern in
|
||||
cases where the new instructions are only available for certain cpu
|
||||
architecture levels (typically mapped to the @code{-march=} command-line
|
||||
option).
|
||||
|
||||
In contrast, the @code{preferred_for_size} and @code{preferred_for_speed}
|
||||
attributes are strong optimization hints rather than correctness properties.
|
||||
@code{preferred_for_size} tells GCC which alternatives to consider when
|
||||
adding or modifying an instruction that GCC wants to optimize for size.
|
||||
@code{preferred_for_speed} does the same thing for speed. Note that things
|
||||
like code motion can lead to cases where code optimized for size uses
|
||||
alternatives that are not preferred for size, and similarly for speed.
|
||||
|
||||
Although @code{define_insn}s can in principle specify the @code{enabled}
|
||||
attribute directly, it is often clearer to have subsiduary attributes
|
||||
for each architectural feature of interest. The @code{define_insn}s
|
||||
can then use these subsiduary attributes to say which alternatives
|
||||
require which features. The example below does this for @code{cpu_facility}.
|
||||
|
||||
E.g. the following two patterns could easily be merged using the @code{enabled}
|
||||
attribute:
|
||||
|
|
|
@ -338,7 +338,9 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
/* Special-purpose attributes should be tested with if, not #ifdef. */
|
||||
const char * const special_attrs[] = { "length", "enabled", 0 };
|
||||
const char * const special_attrs[] = { "length", "enabled",
|
||||
"preferred_for_size",
|
||||
"preferred_for_speed", 0 };
|
||||
for (const char * const *p = special_attrs; *p; p++)
|
||||
{
|
||||
printf ("#ifndef HAVE_ATTR_%s\n"
|
||||
|
@ -355,9 +357,15 @@ main (int argc, char **argv)
|
|||
"#define insn_current_length hook_int_rtx_insn_unreachable\n"
|
||||
"#include \"insn-addr.h\"\n"
|
||||
"#endif\n"
|
||||
"#if !HAVE_ATTR_enabled\n"
|
||||
"extern int hook_int_rtx_1 (rtx);\n"
|
||||
"#if !HAVE_ATTR_enabled\n"
|
||||
"#define get_attr_enabled hook_int_rtx_1\n"
|
||||
"#endif\n"
|
||||
"#if !HAVE_ATTR_preferred_for_size\n"
|
||||
"#define get_attr_preferred_for_size hook_int_rtx_1\n"
|
||||
"#endif\n"
|
||||
"#if !HAVE_ATTR_preferred_for_speed\n"
|
||||
"#define get_attr_preferred_for_speed hook_int_rtx_1\n"
|
||||
"#endif\n");
|
||||
|
||||
/* Output flag masks for use by reorg.
|
||||
|
|
|
@ -416,6 +416,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
|||
|
||||
/* Process each alternative, each time minimizing an operand's cost
|
||||
with the cost for each operand in that alternative. */
|
||||
alternative_mask preferred = get_preferred_alternatives (insn);
|
||||
for (alt = 0; alt < n_alts; alt++)
|
||||
{
|
||||
enum reg_class classes[MAX_RECOG_OPERANDS];
|
||||
|
@ -424,7 +425,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
|||
int alt_fail = 0;
|
||||
int alt_cost = 0, op_cost_add;
|
||||
|
||||
if (!TEST_BIT (recog_data.enabled_alternatives, alt))
|
||||
if (!TEST_BIT (preferred, alt))
|
||||
{
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
constraints[i] = skip_alternative (constraints[i]);
|
||||
|
|
|
@ -85,6 +85,10 @@ static int last_call_num;
|
|||
/* The number of last call at which given allocno was saved. */
|
||||
static int *allocno_saved_at_call;
|
||||
|
||||
/* The value of get_preferred_alternatives for the current instruction,
|
||||
supplemental to recog_data. */
|
||||
static alternative_mask preferred_alternatives;
|
||||
|
||||
/* Record the birth of hard register REGNO, updating hard_regs_live and
|
||||
hard reg conflict information for living allocnos. */
|
||||
static void
|
||||
|
@ -641,10 +645,9 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
|
|||
/* If there's any alternative that allows USE to match DEF, do not
|
||||
record a conflict. If that causes us to create an invalid
|
||||
instruction due to the earlyclobber, reload must fix it up. */
|
||||
alternative_mask enabled = recog_data.enabled_alternatives;
|
||||
for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++)
|
||||
{
|
||||
if (!TEST_BIT (enabled, alt1))
|
||||
if (!TEST_BIT (preferred_alternatives, alt1))
|
||||
continue;
|
||||
const operand_alternative *op_alt1
|
||||
= &recog_op_alt[alt1 * n_operands];
|
||||
|
@ -692,10 +695,9 @@ make_early_clobber_and_input_conflicts (void)
|
|||
|
||||
int n_alternatives = recog_data.n_alternatives;
|
||||
int n_operands = recog_data.n_operands;
|
||||
alternative_mask enabled = recog_data.enabled_alternatives;
|
||||
const operand_alternative *op_alt = recog_op_alt;
|
||||
for (alt = 0; alt < n_alternatives; alt++, op_alt += n_operands)
|
||||
if (TEST_BIT (enabled, alt))
|
||||
if (TEST_BIT (preferred_alternatives, alt))
|
||||
for (def = 0; def < n_operands; def++)
|
||||
{
|
||||
def_cl = NO_REGS;
|
||||
|
@ -762,13 +764,13 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
|
|||
enum constraint_num cn;
|
||||
|
||||
cl = NO_REGS;
|
||||
alternative_mask enabled = recog_data.enabled_alternatives;
|
||||
alternative_mask preferred = preferred_alternatives;
|
||||
for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
|
||||
if (c == '#')
|
||||
enabled &= ~ALTERNATIVE_BIT (0);
|
||||
preferred &= ~ALTERNATIVE_BIT (0);
|
||||
else if (c == ',')
|
||||
enabled >>= 1;
|
||||
else if (enabled & 1)
|
||||
preferred >>= 1;
|
||||
else if (preferred & 1)
|
||||
switch (c)
|
||||
{
|
||||
case 'g':
|
||||
|
@ -851,13 +853,13 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
|
|||
mode = (GET_CODE (op) == SCRATCH
|
||||
? GET_MODE (op) : PSEUDO_REGNO_MODE (regno));
|
||||
cl = NO_REGS;
|
||||
alternative_mask enabled = recog_data.enabled_alternatives;
|
||||
alternative_mask preferred = preferred_alternatives;
|
||||
for (; (c = *p); p += CONSTRAINT_LEN (c, p))
|
||||
if (c == '#')
|
||||
enabled &= ~ALTERNATIVE_BIT (0);
|
||||
preferred &= ~ALTERNATIVE_BIT (0);
|
||||
else if (c == ',')
|
||||
enabled >>= 1;
|
||||
else if (enabled & 1)
|
||||
preferred >>= 1;
|
||||
else if (preferred & 1)
|
||||
{
|
||||
cl = reg_class_for_constraint (lookup_constraint (p));
|
||||
if (cl != NO_REGS)
|
||||
|
@ -1174,6 +1176,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
|
|||
}
|
||||
|
||||
extract_insn (insn);
|
||||
preferred_alternatives = get_preferred_alternatives (insn);
|
||||
preprocess_constraints (insn);
|
||||
process_single_reg_class_operands (false, freq);
|
||||
|
||||
|
|
|
@ -1788,6 +1788,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
|
|||
int commutative = -1;
|
||||
|
||||
extract_insn (insn);
|
||||
alternative_mask preferred = get_preferred_alternatives (insn);
|
||||
CLEAR_HARD_REG_SET (alts);
|
||||
insn_constraints.release ();
|
||||
insn_constraints.safe_grow_cleared (recog_data.n_operands
|
||||
|
@ -1817,7 +1818,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
|
|||
}
|
||||
for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
|
||||
{
|
||||
if (!TEST_BIT (recog_data.enabled_alternatives, nalt)
|
||||
if (!TEST_BIT (preferred, nalt)
|
||||
|| TEST_HARD_REG_BIT (alts, nalt))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1685,14 +1685,14 @@ process_alt_operands (int only_alternative)
|
|||
together, the second alternatives go together, etc.
|
||||
|
||||
First loop over alternatives. */
|
||||
alternative_mask enabled = curr_id->enabled_alternatives;
|
||||
alternative_mask preferred = curr_id->preferred_alternatives;
|
||||
if (only_alternative >= 0)
|
||||
enabled &= ALTERNATIVE_BIT (only_alternative);
|
||||
preferred &= ALTERNATIVE_BIT (only_alternative);
|
||||
|
||||
for (nalt = 0; nalt < n_alternatives; nalt++)
|
||||
{
|
||||
/* Loop over operands for one constraint alternative. */
|
||||
if (!TEST_BIT (enabled, nalt))
|
||||
if (!TEST_BIT (preferred, nalt))
|
||||
continue;
|
||||
|
||||
overall = losers = reject = reload_nregs = reload_sum = 0;
|
||||
|
|
|
@ -233,8 +233,8 @@ struct lra_insn_recog_data
|
|||
value can be NULL or points to array of the hard register numbers
|
||||
ending with a negative value. */
|
||||
int *arg_hard_regs;
|
||||
/* Alternative enabled for the insn. NULL for debug insns. */
|
||||
alternative_mask enabled_alternatives;
|
||||
/* Cached value of get_preferred_alternatives. */
|
||||
alternative_mask preferred_alternatives;
|
||||
/* The following member value is always NULL for a debug insn. */
|
||||
struct lra_insn_reg *regs;
|
||||
};
|
||||
|
|
28
gcc/lra.c
28
gcc/lra.c
|
@ -921,7 +921,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
|
|||
data->insn_static_data = &debug_insn_static_data;
|
||||
data->dup_loc = NULL;
|
||||
data->arg_hard_regs = NULL;
|
||||
data->enabled_alternatives = ALL_ALTERNATIVES;
|
||||
data->preferred_alternatives = ALL_ALTERNATIVES;
|
||||
data->operand_loc = XNEWVEC (rtx *, 1);
|
||||
data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
|
||||
return data;
|
||||
|
@ -981,7 +981,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
|
|||
= (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
|
||||
: insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
|
||||
: OP_IN);
|
||||
data->enabled_alternatives = ALL_ALTERNATIVES;
|
||||
data->preferred_alternatives = ALL_ALTERNATIVES;
|
||||
if (nop > 0)
|
||||
{
|
||||
operand_alternative *op_alt = XCNEWVEC (operand_alternative,
|
||||
|
@ -1015,7 +1015,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
|
|||
memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
|
||||
}
|
||||
data->dup_loc = locs;
|
||||
data->enabled_alternatives = get_enabled_alternatives (insn);
|
||||
data->preferred_alternatives = get_preferred_alternatives (insn);
|
||||
const operand_alternative *op_alt = preprocess_insn_constraints (icode);
|
||||
if (!insn_static_data->operand_alternative)
|
||||
setup_operand_alternative (data, op_alt);
|
||||
|
@ -1206,27 +1206,7 @@ lra_update_insn_recog_data (rtx_insn *insn)
|
|||
n = insn_static_data->n_dups;
|
||||
if (n != 0)
|
||||
memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *));
|
||||
#if HAVE_ATTR_enabled
|
||||
#ifdef ENABLE_CHECKING
|
||||
{
|
||||
int i;
|
||||
alternative_mask enabled;
|
||||
|
||||
n = insn_static_data->n_alternatives;
|
||||
enabled = data->enabled_alternatives;
|
||||
lra_assert (n >= 0);
|
||||
/* Cache the insn to prevent extract_insn call from
|
||||
get_attr_enabled. */
|
||||
recog_data.insn = insn;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
which_alternative = i;
|
||||
lra_assert (TEST_BIT (enabled, i)
|
||||
== (bool) get_attr_enabled (insn));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
lra_assert (check_bool_attrs (insn));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -497,6 +497,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
|
|||
SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
|
||||
}
|
||||
|
||||
alternative_mask preferred = get_preferred_alternatives (insn);
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
|
@ -570,7 +571,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
|
|||
alternative yet and the operand being replaced is not
|
||||
a cheap CONST_INT. */
|
||||
if (op_alt_regno[i][j] == -1
|
||||
&& TEST_BIT (recog_data.enabled_alternatives, j)
|
||||
&& TEST_BIT (preferred, j)
|
||||
&& reg_fits_class_p (testreg, rclass, 0, mode)
|
||||
&& (!CONST_INT_P (recog_data.operand[i])
|
||||
|| (set_src_cost (recog_data.operand[i],
|
||||
|
|
128
gcc/recog.c
128
gcc/recog.c
|
@ -2060,25 +2060,46 @@ mode_dependent_address_p (rtx addr, addr_space_t addrspace)
|
|||
return targetm.mode_dependent_address_p (addr, addrspace);
|
||||
}
|
||||
|
||||
/* Return the mask of operand alternatives that are allowed for INSN.
|
||||
This mask depends only on INSN and on the current target; it does not
|
||||
depend on things like the values of operands. */
|
||||
/* Return true if boolean attribute ATTR is supported. */
|
||||
|
||||
alternative_mask
|
||||
get_enabled_alternatives (rtx_insn *insn)
|
||||
static bool
|
||||
have_bool_attr (bool_attr attr)
|
||||
{
|
||||
/* Quick exit for asms and for targets that don't use the "enabled"
|
||||
attribute. */
|
||||
int code = INSN_CODE (insn);
|
||||
if (code < 0 || !HAVE_ATTR_enabled)
|
||||
return ALL_ALTERNATIVES;
|
||||
switch (attr)
|
||||
{
|
||||
case BA_ENABLED:
|
||||
return HAVE_ATTR_enabled;
|
||||
case BA_PREFERRED_FOR_SIZE:
|
||||
return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_size;
|
||||
case BA_PREFERRED_FOR_SPEED:
|
||||
return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_speed;
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Calling get_attr_enabled can be expensive, so cache the mask
|
||||
for speed. */
|
||||
if (this_target_recog->x_enabled_alternatives[code])
|
||||
return this_target_recog->x_enabled_alternatives[code];
|
||||
/* Return the value of ATTR for instruction INSN. */
|
||||
|
||||
/* Temporarily install enough information for get_attr_enabled to assume
|
||||
static bool
|
||||
get_bool_attr (rtx_insn *insn, bool_attr attr)
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case BA_ENABLED:
|
||||
return get_attr_enabled (insn);
|
||||
case BA_PREFERRED_FOR_SIZE:
|
||||
return get_attr_enabled (insn) && get_attr_preferred_for_size (insn);
|
||||
case BA_PREFERRED_FOR_SPEED:
|
||||
return get_attr_enabled (insn) && get_attr_preferred_for_speed (insn);
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Like get_bool_attr_mask, but don't use the cache. */
|
||||
|
||||
static alternative_mask
|
||||
get_bool_attr_mask_uncached (rtx_insn *insn, bool_attr attr)
|
||||
{
|
||||
/* Temporarily install enough information for get_attr_<foo> to assume
|
||||
that the insn operands are already cached. As above, the attribute
|
||||
mustn't depend on the values of operands, so we don't provide their
|
||||
real values here. */
|
||||
|
@ -2086,20 +2107,81 @@ get_enabled_alternatives (rtx_insn *insn)
|
|||
int old_alternative = which_alternative;
|
||||
|
||||
recog_data.insn = insn;
|
||||
alternative_mask enabled = ALL_ALTERNATIVES;
|
||||
int n_alternatives = insn_data[code].n_alternatives;
|
||||
alternative_mask mask = ALL_ALTERNATIVES;
|
||||
int n_alternatives = insn_data[INSN_CODE (insn)].n_alternatives;
|
||||
for (int i = 0; i < n_alternatives; i++)
|
||||
{
|
||||
which_alternative = i;
|
||||
if (!get_attr_enabled (insn))
|
||||
enabled &= ~ALTERNATIVE_BIT (i);
|
||||
if (!get_bool_attr (insn, attr))
|
||||
mask &= ~ALTERNATIVE_BIT (i);
|
||||
}
|
||||
|
||||
recog_data.insn = old_insn;
|
||||
which_alternative = old_alternative;
|
||||
return mask;
|
||||
}
|
||||
|
||||
this_target_recog->x_enabled_alternatives[code] = enabled;
|
||||
return enabled;
|
||||
/* Return the mask of operand alternatives that are allowed for INSN
|
||||
by boolean attribute ATTR. This mask depends only on INSN and on
|
||||
the current target; it does not depend on things like the values of
|
||||
operands. */
|
||||
|
||||
static alternative_mask
|
||||
get_bool_attr_mask (rtx_insn *insn, bool_attr attr)
|
||||
{
|
||||
/* Quick exit for asms and for targets that don't use these attributes. */
|
||||
int code = INSN_CODE (insn);
|
||||
if (code < 0 || !have_bool_attr (attr))
|
||||
return ALL_ALTERNATIVES;
|
||||
|
||||
/* Calling get_attr_<foo> can be expensive, so cache the mask
|
||||
for speed. */
|
||||
if (!this_target_recog->x_bool_attr_masks[code][attr])
|
||||
this_target_recog->x_bool_attr_masks[code][attr]
|
||||
= get_bool_attr_mask_uncached (insn, attr);
|
||||
return this_target_recog->x_bool_attr_masks[code][attr];
|
||||
}
|
||||
|
||||
/* Return the set of alternatives of INSN that are allowed by the current
|
||||
target. */
|
||||
|
||||
alternative_mask
|
||||
get_enabled_alternatives (rtx_insn *insn)
|
||||
{
|
||||
return get_bool_attr_mask (insn, BA_ENABLED);
|
||||
}
|
||||
|
||||
/* Return the set of alternatives of INSN that are allowed by the current
|
||||
target and are preferred for the current size/speed optimization
|
||||
choice. */
|
||||
|
||||
alternative_mask
|
||||
get_preferred_alternatives (rtx_insn *insn)
|
||||
{
|
||||
if (optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)))
|
||||
return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED);
|
||||
else
|
||||
return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
|
||||
}
|
||||
|
||||
/* Assert that the cached boolean attributes for INSN are still accurate.
|
||||
The backend is required to define these attributes in a way that only
|
||||
depends on the current target (rather than operands, compiler phase,
|
||||
etc.). */
|
||||
|
||||
bool
|
||||
check_bool_attrs (rtx_insn *insn)
|
||||
{
|
||||
int code = INSN_CODE (insn);
|
||||
if (code >= 0)
|
||||
for (int i = 0; i <= BA_LAST; ++i)
|
||||
{
|
||||
enum bool_attr attr = (enum bool_attr) i;
|
||||
if (this_target_recog->x_bool_attr_masks[code][attr])
|
||||
gcc_assert (this_target_recog->x_bool_attr_masks[code][attr]
|
||||
== get_bool_attr_mask_uncached (insn, attr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Like extract_insn, but save insn extracted and don't extract again, when
|
||||
|
@ -4048,8 +4130,8 @@ recog_init ()
|
|||
this_target_recog->x_initialized = true;
|
||||
return;
|
||||
}
|
||||
memset (this_target_recog->x_enabled_alternatives, 0,
|
||||
sizeof (this_target_recog->x_enabled_alternatives));
|
||||
memset (this_target_recog->x_bool_attr_masks, 0,
|
||||
sizeof (this_target_recog->x_bool_attr_masks));
|
||||
for (int i = 0; i < LAST_INSN_CODE; ++i)
|
||||
if (this_target_recog->x_op_alt[i])
|
||||
{
|
||||
|
|
13
gcc/recog.h
13
gcc/recog.h
|
@ -389,10 +389,19 @@ extern int peep2_current_count;
|
|||
#ifndef GENERATOR_FILE
|
||||
#include "insn-codes.h"
|
||||
|
||||
/* An enum of boolean attributes that may only depend on the current
|
||||
subtarget, not on things like operands or compiler phase. */
|
||||
enum bool_attr {
|
||||
BA_ENABLED,
|
||||
BA_PREFERRED_FOR_SPEED,
|
||||
BA_PREFERRED_FOR_SIZE,
|
||||
BA_LAST = BA_PREFERRED_FOR_SIZE
|
||||
};
|
||||
|
||||
/* Target-dependent globals. */
|
||||
struct target_recog {
|
||||
bool x_initialized;
|
||||
alternative_mask x_enabled_alternatives[LAST_INSN_CODE];
|
||||
alternative_mask x_bool_attr_masks[LAST_INSN_CODE][BA_LAST + 1];
|
||||
operand_alternative *x_op_alt[LAST_INSN_CODE];
|
||||
};
|
||||
|
||||
|
@ -404,6 +413,8 @@ extern struct target_recog *this_target_recog;
|
|||
#endif
|
||||
|
||||
alternative_mask get_enabled_alternatives (rtx_insn *);
|
||||
alternative_mask get_preferred_alternatives (rtx_insn *);
|
||||
bool check_bool_attrs (rtx_insn *);
|
||||
|
||||
void recog_init ();
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue