system.h (TEST_BIT): New macro.

gcc/
	* system.h (TEST_BIT): New macro.
	* recog.h (alternative_mask): New type.
	(ALL_ALTERNATIVES, ALTERNATIVE_BIT): New macros.
	(recog_data_d): Replace alternative_enabled_p array with
	enabled_alternatives.
	(target_recog): New structure.
	(default_target_recog, this_target_recog): Declare.
	(get_enabled_alternatives, recog_init): Likewise.
	* recog.c (default_target_recog, this_target_recog): New variables.
	(get_enabled_alternatives): New function.
	(extract_insn): Use it.
	(recog_init): New function.
	(preprocess_constraints, constrain_operands): Adjust for change to
	recog_data.
	* postreload.c (reload_cse_simplify_operands): Likewise.
	* reload.c (find_reloads): Likewise.
	* ira-costs.c (record_reg_classes): Likewise.
	* ira-lives.c (single_reg_class): Likewise.  Fix bug in which
	all alternatives after a disabled one would be skipped.
	(ira_implicitly_set_insn_hard_regs): Likewise.
	* ira.c (ira_setup_alts): Adjust for change to recog_data.
	* lra-int.h (lra_insn_recog_data): Replace alternative_enabled_p
	with enabled_alternatives.
	* lra.c (free_insn_recog_data): Update accordingly.
	(lra_update_insn_recog_data): Likewise.
	(lra_set_insn_recog_data): Likewise.  Use get_enabled_alternatives.
	* lra-constraints.c (process_alt_operands): Likewise.  Handle
	only_alternative as part of the enabled mask.
	* target-globals.h (this_target_recog): Declare.
	(target_globals): Add a recog field.
	(restore_target_globals): Restore this_target_recog.
	* target-globals.c: Include recog.h.
	(default_target_globals): Initialize recog field.
	(save_target_globals): Likewise.
	* reginfo.c (reinit_regs): Call recog_init.
	* toplev.c (backend_init_target): Likewise.

From-SVN: r210964
This commit is contained in:
Richard Sandiford 2014-05-27 10:06:22 +00:00 committed by Richard Sandiford
parent 9921417d94
commit 4cc8d9d2df
16 changed files with 187 additions and 87 deletions

View File

@ -1,3 +1,42 @@
2014-05-27 Richard Sandiford <rdsandiford@googlemail.com>
* system.h (TEST_BIT): New macro.
* recog.h (alternative_mask): New type.
(ALL_ALTERNATIVES, ALTERNATIVE_BIT): New macros.
(recog_data_d): Replace alternative_enabled_p array with
enabled_alternatives.
(target_recog): New structure.
(default_target_recog, this_target_recog): Declare.
(get_enabled_alternatives, recog_init): Likewise.
* recog.c (default_target_recog, this_target_recog): New variables.
(get_enabled_alternatives): New function.
(extract_insn): Use it.
(recog_init): New function.
(preprocess_constraints, constrain_operands): Adjust for change to
recog_data.
* postreload.c (reload_cse_simplify_operands): Likewise.
* reload.c (find_reloads): Likewise.
* ira-costs.c (record_reg_classes): Likewise.
* ira-lives.c (single_reg_class): Likewise. Fix bug in which
all alternatives after a disabled one would be skipped.
(ira_implicitly_set_insn_hard_regs): Likewise.
* ira.c (ira_setup_alts): Adjust for change to recog_data.
* lra-int.h (lra_insn_recog_data): Replace alternative_enabled_p
with enabled_alternatives.
* lra.c (free_insn_recog_data): Update accordingly.
(lra_update_insn_recog_data): Likewise.
(lra_set_insn_recog_data): Likewise. Use get_enabled_alternatives.
* lra-constraints.c (process_alt_operands): Likewise. Handle
only_alternative as part of the enabled mask.
* target-globals.h (this_target_recog): Declare.
(target_globals): Add a recog field.
(restore_target_globals): Restore this_target_recog.
* target-globals.c: Include recog.h.
(default_target_globals): Initialize recog field.
(save_target_globals): Likewise.
* reginfo.c (reinit_regs): Call recog_init.
* toplev.c (backend_init_target): Likewise.
2014-05-27 Richard Sandiford <rdsandiford@googlemail.com>
* gencodes.c (main): Make LAST_INSN_CODE higher than any insn code,

View File

@ -423,7 +423,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
int alt_fail = 0;
int alt_cost = 0, op_cost_add;
if (!recog_data.alternative_enabled_p[alt])
if (!TEST_BIT (recog_data.enabled_alternatives, alt))
{
for (i = 0; i < recog_data.n_operands; i++)
constraints[i] = skip_alternative (constraints[i]);

View File

@ -743,22 +743,17 @@ mark_hard_reg_early_clobbers (rtx insn, bool live_p)
static enum reg_class
single_reg_class (const char *constraints, rtx op, rtx equiv_const)
{
int curr_alt, c;
bool ignore_p;
int c;
enum reg_class cl, next_cl;
cl = NO_REGS;
for (ignore_p = false, curr_alt = 0;
(c = *constraints);
constraints += CONSTRAINT_LEN (c, constraints))
if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
ignore_p = true;
alternative_mask enabled = recog_data.enabled_alternatives;
for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
if (c == '#')
enabled &= ~ALTERNATIVE_BIT (0);
else if (c == ',')
{
curr_alt++;
ignore_p = false;
}
else if (! ignore_p)
enabled >>= 1;
else if (enabled & 1)
switch (c)
{
case ' ':
@ -887,8 +882,7 @@ single_reg_operand_class (int op_num)
void
ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
{
int i, curr_alt, c, regno = 0;
bool ignore_p;
int i, c, regno = 0;
enum reg_class cl;
rtx op;
enum machine_mode mode;
@ -909,17 +903,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;
for (ignore_p = false, curr_alt = 0;
(c = *p);
p += CONSTRAINT_LEN (c, p))
if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
ignore_p = true;
alternative_mask enabled = recog_data.enabled_alternatives;
for (; (c = *p); p += CONSTRAINT_LEN (c, p))
if (c == '#')
enabled &= ~ALTERNATIVE_BIT (0);
else if (c == ',')
{
curr_alt++;
ignore_p = false;
}
else if (! ignore_p)
enabled >>= 1;
else if (enabled & 1)
switch (c)
{
case 'r':

View File

@ -1844,7 +1844,8 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
}
for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
{
if (! recog_data.alternative_enabled_p[nalt] || TEST_HARD_REG_BIT (alts, nalt))
if (!TEST_BIT (recog_data.enabled_alternatives, nalt)
|| TEST_HARD_REG_BIT (alts, nalt))
continue;
for (nop = 0; nop < recog_data.n_operands; nop++)

View File

@ -1557,18 +1557,15 @@ process_alt_operands (int only_alternative)
together, the second alternatives go together, etc.
First loop over alternatives. */
alternative_mask enabled = curr_id->enabled_alternatives;
if (only_alternative >= 0)
enabled &= ALTERNATIVE_BIT (only_alternative);
for (nalt = 0; nalt < n_alternatives; nalt++)
{
/* Loop over operands for one constraint alternative. */
#if HAVE_ATTR_enabled
if (curr_id->alternative_enabled_p != NULL
&& ! curr_id->alternative_enabled_p[nalt])
if (!TEST_BIT (enabled, nalt))
continue;
#endif
if (only_alternative >= 0 && nalt != only_alternative)
continue;
overall = losers = reject = reload_nregs = reload_sum = 0;
for (nop = 0; nop < n_operands; nop++)

View File

@ -227,7 +227,7 @@ struct lra_insn_recog_data
ending with a negative value. */
int *arg_hard_regs;
/* Alternative enabled for the insn. NULL for debug insns. */
bool *alternative_enabled_p;
alternative_mask enabled_alternatives;
/* The following member value is always NULL for a debug insn. */
struct lra_insn_reg *regs;
};

View File

@ -724,8 +724,6 @@ free_insn_recog_data (lra_insn_recog_data_t data)
free (data->dup_loc);
if (data->arg_hard_regs != NULL)
free (data->arg_hard_regs);
if (HAVE_ATTR_enabled && data->alternative_enabled_p != NULL)
free (data->alternative_enabled_p);
if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
{
if (data->insn_static_data->operand_alternative != NULL)
@ -1072,7 +1070,7 @@ lra_set_insn_recog_data (rtx insn)
data->insn_static_data = &debug_insn_static_data;
data->dup_loc = NULL;
data->arg_hard_regs = NULL;
data->alternative_enabled_p = NULL;
data->enabled_alternatives = ALL_ALTERNATIVES;
data->operand_loc = XNEWVEC (rtx *, 1);
data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
return data;
@ -1132,7 +1130,7 @@ lra_set_insn_recog_data (rtx insn)
= (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
: insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
: OP_IN);
data->alternative_enabled_p = NULL;
data->enabled_alternatives = ALL_ALTERNATIVES;
}
else
{
@ -1159,27 +1157,7 @@ lra_set_insn_recog_data (rtx insn)
memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
}
data->dup_loc = locs;
if (HAVE_ATTR_enabled)
{
bool *bp;
n = insn_static_data->n_alternatives;
lra_assert (n >= 0);
data->alternative_enabled_p = bp = XNEWVEC (bool, n);
/* Cache the insn because we don't want to call extract_insn
from get_attr_enabled as extract_insn modifies
which_alternative. The attribute enabled should not depend
on insn operands, operand modes, operand types, and operand
constraints. It should depend on the architecture. If it
is not true, we should rewrite this file code to use
extract_insn instead of less expensive insn_extract. */
recog_data.insn = insn;
for (i = 0; i < n; i++)
{
which_alternative = i;
bp[i] = get_attr_enabled (insn);
}
}
data->enabled_alternatives = get_enabled_alternatives (insn);
}
if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == USE)
insn_static_data->hard_regs = NULL;
@ -1370,18 +1348,19 @@ lra_update_insn_recog_data (rtx insn)
#ifdef ENABLE_CHECKING
{
int i;
bool *bp;
alternative_mask enabled;
n = insn_static_data->n_alternatives;
bp = data->alternative_enabled_p;
lra_assert (n >= 0 && bp != NULL);
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 (bp[i] == get_attr_enabled (insn));
lra_assert (TEST_BIT (enabled, i)
== (bool) get_attr_enabled (insn));
}
}
#endif

View File

@ -584,7 +584,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
&& recog_data.alternative_enabled_p[j]
&& TEST_BIT (recog_data.enabled_alternatives, j)
&& reg_fits_class_p (testreg, rclass, 0, mode)
&& (!CONST_INT_P (recog_data.operand[i])
|| (set_src_cost (recog_data.operand[i],

View File

@ -61,6 +61,11 @@ static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx, bool);
static void validate_replace_src_1 (rtx *, void *);
static rtx split_insn (rtx);
struct target_recog default_target_recog;
#if SWITCHABLE_TARGET
struct target_recog *this_target_recog = &default_target_recog;
#endif
/* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling
the functions in optabs.c and expmed.c (most of the time).
@ -2137,6 +2142,48 @@ 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. */
alternative_mask
get_enabled_alternatives (rtx insn)
{
/* 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;
/* 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];
/* Temporarily install enough information for get_attr_enabled 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. */
rtx old_insn = recog_data.insn;
int old_alternative = which_alternative;
recog_data.insn = insn;
alternative_mask enabled = ALL_ALTERNATIVES;
int n_alternatives = insn_data[code].n_alternatives;
for (int i = 0; i < n_alternatives; i++)
{
which_alternative = i;
if (!get_attr_enabled (insn))
enabled &= ~ALTERNATIVE_BIT (i);
}
recog_data.insn = old_insn;
which_alternative = old_alternative;
this_target_recog->x_enabled_alternatives[code] = enabled;
return enabled;
}
/* Like extract_insn, but save insn extracted and don't extract again, when
called again for the same insn expecting that recog_data still contain the
valid information. This is used primary by gen_attr infrastructure that
@ -2269,19 +2316,7 @@ extract_insn (rtx insn)
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]
= HAVE_ATTR_enabled ? get_attr_enabled (insn) : 1;
}
}
recog_data.enabled_alternatives = get_enabled_alternatives (insn);
recog_data.insn = NULL;
which_alternative = -1;
@ -2314,7 +2349,7 @@ preprocess_constraints (void)
op_alt[j].matches = -1;
op_alt[j].matched = -1;
if (!recog_data.alternative_enabled_p[j])
if (!TEST_BIT (recog_data.enabled_alternatives, j))
{
p = skip_alternative (p);
continue;
@ -2490,7 +2525,7 @@ constrain_operands (int strict)
int lose = 0;
funny_match_index = 0;
if (!recog_data.alternative_enabled_p[which_alternative])
if (!TEST_BIT (recog_data.enabled_alternatives, which_alternative))
{
int i;
@ -4164,3 +4199,19 @@ make_pass_split_for_shorten_branches (gcc::context *ctxt)
{
return new pass_split_for_shorten_branches (ctxt);
}
/* (Re)initialize the target information after a change in target. */
void
recog_init ()
{
/* The information is zero-initialized, so we don't need to do anything
first time round. */
if (!this_target_recog->x_initialized)
{
this_target_recog->x_initialized = true;
return;
}
memset (this_target_recog->x_enabled_alternatives, 0,
sizeof (this_target_recog->x_enabled_alternatives));
}

View File

@ -20,8 +20,17 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_RECOG_H
#define GCC_RECOG_H
/* Random number that should be large enough for all purposes. */
/* Random number that should be large enough for all purposes. Also define
a type that has at least MAX_RECOG_ALTERNATIVES + 1 bits, with the extra
bit giving an invalid value that can be used to mean "uninitialized". */
#define MAX_RECOG_ALTERNATIVES 30
typedef unsigned int alternative_mask;
/* A mask of all alternatives. */
#define ALL_ALTERNATIVES ((alternative_mask) -1)
/* A mask containing just alternative X. */
#define ALTERNATIVE_BIT(X) ((alternative_mask) 1 << (X))
/* Types of operands. */
enum op_type {
@ -235,11 +244,11 @@ struct recog_data_d
/* True if insn is ASM_OPERANDS. */
bool is_asm;
/* 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];
/* 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 bits are always set to 1 in expand_insn.
Bits beyond the last alternative are also set to 1. */
alternative_mask enabled_alternatives;
/* In case we are caching, hold insn data was generated for. */
rtx insn;
@ -361,4 +370,25 @@ struct insn_data_d
extern const struct insn_data_d insn_data[];
extern int peep2_current_count;
#ifndef GENERATOR_FILE
#include "insn-codes.h"
/* Target-dependent globals. */
struct target_recog {
bool x_initialized;
alternative_mask x_enabled_alternatives[LAST_INSN_CODE];
};
extern struct target_recog default_target_recog;
#if SWITCHABLE_TARGET
extern struct target_recog *this_target_recog;
#else
#define this_target_recog (&default_target_recog)
#endif
alternative_mask get_enabled_alternatives (rtx);
void recog_init ();
#endif
#endif /* GCC_RECOG_H */

View File

@ -534,6 +534,7 @@ reinit_regs (void)
/* caller_save needs to be re-initialized. */
caller_save_initialized_p = false;
ira_init ();
recog_init ();
}
/* Initialize some fake stack-frame MEM references for use in

View File

@ -3010,7 +3010,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
{
int swapped;
if (!recog_data.alternative_enabled_p[this_alternative_number])
if (!TEST_BIT (recog_data.enabled_alternatives, this_alternative_number))
{
int i;

View File

@ -1071,6 +1071,9 @@ helper_const_non_const_cast (const char *p)
#define DEBUG_VARIABLE
#endif
/* General macro to extract bit Y of X. */
#define TEST_BIT(X, Y) (((X) >> (Y)) & 1)
/* Get definitions of HOST_WIDE_INT. */
#include "hwint.h"

View File

@ -43,12 +43,14 @@ along with GCC; see the file COPYING3. If not see
#include "gcse.h"
#include "bb-reorder.h"
#include "lower-subreg.h"
#include "recog.h"
#if SWITCHABLE_TARGET
struct target_globals default_target_globals = {
&default_target_flag_state,
&default_target_regs,
&default_target_rtl,
&default_target_recog,
&default_target_hard_regs,
&default_target_reload,
&default_target_expmed,
@ -84,6 +86,7 @@ save_target_globals (void)
g->flag_state = &p->flag_state;
g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
g->rtl = ggc_cleared_alloc<target_rtl> ();
g->recog = ggc_internal_cleared_alloc (sizeof (struct target_recog));
g->hard_regs
= ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));

View File

@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
extern struct target_flag_state *this_target_flag_state;
extern struct target_regs *this_target_regs;
extern struct target_rtl *this_target_rtl;
extern struct target_recog *this_target_recog;
extern struct target_hard_regs *this_target_hard_regs;
extern struct target_reload *this_target_reload;
extern struct target_expmed *this_target_expmed;
@ -43,6 +44,7 @@ struct GTY(()) target_globals {
struct target_flag_state *GTY((skip)) flag_state;
void *GTY((atomic)) regs;
struct target_rtl *rtl;
void *GTY((atomic)) recog;
void *GTY((atomic)) hard_regs;
void *GTY((atomic)) reload;
void *GTY((atomic)) expmed;
@ -70,6 +72,7 @@ restore_target_globals (struct target_globals *g)
this_target_flag_state = g->flag_state;
this_target_regs = (struct target_regs *) g->regs;
this_target_rtl = g->rtl;
this_target_recog = (struct target_recog *) g->recog;
this_target_hard_regs = (struct target_hard_regs *) g->hard_regs;
this_target_reload = (struct target_reload *) g->reload;
this_target_expmed = (struct target_expmed *) g->expmed;

View File

@ -1601,6 +1601,9 @@ backend_init_target (void)
/* Depends on HARD_FRAME_POINTER_REGNUM. */
init_reload ();
/* Depends on the enabled attribute. */
recog_init ();
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
init_dummy_function_start ();