system.h (REG_CLASS_FROM_CONSTRAINT): Poison.

gcc/
	* system.h (REG_CLASS_FROM_CONSTRAINT): Poison.
	(REG_CLASS_FOR_CONSTRAINT, EXTRA_CONSTRAINT_STR): Likewise.
	(EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Likewise.
	* genpreds.c (print_type_tree): New function.
	(write_tm_preds_h): Remove REG_CLASS_FROM_CONSTRAINT,
	REG_CLASS_FOR_CONSTRAINT, EXTRA_MEMORY_CONSTRAINT,
	EXTRA_ADDRESS_CONSTRAINT and EXTRA_CONSTRAINT_STR.
	Write out enum constraint_type and get_constraint_type.
	* lra-constraints.c (satisfies_memory_constraint_p): Take a
	constraint_num rather than a constraint string.
	(satisfies_address_constraint_p): Likewise.
	(reg_class_from_constraints): Avoid old constraint macros.
	(process_alt_operands, process_address_1): Likewise.
	(curr_insn_transform): Likewise.
	* ira-costs.c (record_reg_classes): Likewise.
	(record_operand_costs): Likewise.
	* ira-lives.c (single_reg_class): Likewise.
	(ira_implicitly_set_insn_hard_regs): Likewise.
	* ira.c (ira_setup_alts, ira_get_dup_out_num): Likewise.
	* postreload.c (reload_cse_simplify_operands): Likewise.
	* recog.c (asm_operand_ok, preprocess_constraints): Likewise.
	(constrain_operands, peep2_find_free_register): Likewise.
	* reload.c (push_secondary_reload, scratch_reload_class): Likewise.
	(find_reloads, alternative_allows_const_pool_ref): Likewise.
	* reload1.c (maybe_fix_stack_asms): Likewise.
	* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
	* targhooks.c (default_secondary_reload): Likewise.
	* config/m32c/m32c.c (m32c_matches_constraint_p): Avoid reference
	to EXTRA_CONSTRAINT_STR.
	* config/sparc/constraints.md (U): Likewise REG_CLASS_FROM_CONSTRAINT.

From-SVN: r211471
This commit is contained in:
Richard Sandiford 2014-06-11 16:58:35 +00:00 committed by Richard Sandiford
parent 9e6b787414
commit 777e635f1a
15 changed files with 352 additions and 290 deletions

View File

@ -1,3 +1,36 @@
2014-06-11 Richard Sandiford <rdsandiford@googlemail.com>
* system.h (REG_CLASS_FROM_CONSTRAINT): Poison.
(REG_CLASS_FOR_CONSTRAINT, EXTRA_CONSTRAINT_STR): Likewise.
(EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Likewise.
* genpreds.c (print_type_tree): New function.
(write_tm_preds_h): Remove REG_CLASS_FROM_CONSTRAINT,
REG_CLASS_FOR_CONSTRAINT, EXTRA_MEMORY_CONSTRAINT,
EXTRA_ADDRESS_CONSTRAINT and EXTRA_CONSTRAINT_STR.
Write out enum constraint_type and get_constraint_type.
* lra-constraints.c (satisfies_memory_constraint_p): Take a
constraint_num rather than a constraint string.
(satisfies_address_constraint_p): Likewise.
(reg_class_from_constraints): Avoid old constraint macros.
(process_alt_operands, process_address_1): Likewise.
(curr_insn_transform): Likewise.
* ira-costs.c (record_reg_classes): Likewise.
(record_operand_costs): Likewise.
* ira-lives.c (single_reg_class): Likewise.
(ira_implicitly_set_insn_hard_regs): Likewise.
* ira.c (ira_setup_alts, ira_get_dup_out_num): Likewise.
* postreload.c (reload_cse_simplify_operands): Likewise.
* recog.c (asm_operand_ok, preprocess_constraints): Likewise.
(constrain_operands, peep2_find_free_register): Likewise.
* reload.c (push_secondary_reload, scratch_reload_class): Likewise.
(find_reloads, alternative_allows_const_pool_ref): Likewise.
* reload1.c (maybe_fix_stack_asms): Likewise.
* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
* targhooks.c (default_secondary_reload): Likewise.
* config/m32c/m32c.c (m32c_matches_constraint_p): Avoid reference
to EXTRA_CONSTRAINT_STR.
* config/sparc/constraints.md (U): Likewise REG_CLASS_FROM_CONSTRAINT.
2014-06-11 Richard Sandiford <rdsandiford@googlemail.com>
* genpreds.c (write_constraint_satisfied_p_1): Replace with...

View File

@ -854,7 +854,7 @@ m32c_cannot_change_mode_class (enum machine_mode from,
#define A0_OR_PSEUDO(x) (IS_REG(x, A0_REGNO) || REGNO (x) >= FIRST_PSEUDO_REGISTER)
/* Implements EXTRA_CONSTRAINT_STR (see next function too). 'S' is
/* Implements matching for constraints (see next function too). 'S' is
for memory constraints, plus "Rpa" for PARALLEL rtx's we use for
call return values. */
bool

View File

@ -171,7 +171,7 @@
;; define_register_constraint would. This currently means that we cannot
;; use LRA on Sparc, since the constraint processing of LRA really depends
;; upon whether an extra constraint is for registers or not. It uses
;; REG_CLASS_FROM_CONSTRAINT, and checks it against NO_REGS.
;; reg_class_for_constraint, and checks it against NO_REGS.
(define_constraint "U"
"Pseudo-register or hard even-numbered integer register"
(and (match_test "TARGET_ARCH32")

View File

@ -1232,6 +1232,33 @@ write_range_function (const char *name, unsigned int start, unsigned int end)
"}\n\n", name);
}
/* VEC is a list of key/value pairs, with the keys being lower bounds
of a range. Output a decision tree that handles the keys covered by
[VEC[START], VEC[END]), returning FALLBACK for keys lower then VEC[START]'s.
INDENT is the number of spaces to indent the code. */
static void
print_type_tree (const vec <std::pair <unsigned int, const char *> > &vec,
unsigned int start, unsigned int end, const char *fallback,
unsigned int indent)
{
while (start < end)
{
unsigned int mid = (start + end) / 2;
printf ("%*sif (c >= CONSTRAINT_%s)\n",
indent, "", enum_order[vec[mid].first]->c_name);
if (mid + 1 == end)
print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 2);
else
{
printf ("%*s{\n", indent + 2, "");
print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 4);
printf ("%*s}\n", indent + 2, "");
}
end = mid;
}
printf ("%*sreturn %s;\n", indent, "", fallback);
}
/* Write tm-preds.h. Unfortunately, it is impossible to forward-declare
an enumeration in portable C, so we have to condition all these
prototypes on HAVE_MACHINE_MODES. */
@ -1321,21 +1348,13 @@ write_tm_preds_h (void)
" if (insn_extra_register_constraint (c))\n"
" return reg_class_for_constraint_1 (c);\n"
" return NO_REGS;\n"
"}\n"
"\n"
"#define REG_CLASS_FROM_CONSTRAINT(c_,s_) \\\n"
" reg_class_for_constraint (lookup_constraint (s_))\n"
"#define REG_CLASS_FOR_CONSTRAINT(x_) \\\n"
" reg_class_for_constraint (x_)\n");
"}\n");
else
puts ("static inline enum reg_class\n"
"reg_class_for_constraint (enum constraint_num)\n"
"{\n"
" return NO_REGS;\n"
"}\n\n"
"#define REG_CLASS_FROM_CONSTRAINT(c_,s_) NO_REGS\n"
"#define REG_CLASS_FOR_CONSTRAINT(x_) \\\n"
" NO_REGS\n");
"}\n");
if (have_const_int_constraints)
puts ("extern bool insn_const_int_ok_for_constraint "
"(HOST_WIDE_INT, enum constraint_num);\n"
@ -1347,19 +1366,27 @@ write_tm_preds_h (void)
" constraint_satisfied_p (v_, lookup_constraint (s_))\n");
else
puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) 0\n");
if (have_extra_constraints)
puts ("#define EXTRA_CONSTRAINT_STR(v_,c_,s_) \\\n"
" constraint_satisfied_p (v_, lookup_constraint (s_))\n");
if (have_memory_constraints)
puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) "
"insn_extra_memory_constraint (lookup_constraint (s_))\n");
else
puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) false\n");
if (have_address_constraints)
puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) "
"insn_extra_address_constraint (lookup_constraint (s_))\n");
else
puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) false\n");
puts ("enum constraint_type\n"
"{\n"
" CT_REGISTER,\n"
" CT_MEMORY,\n"
" CT_ADDRESS,\n"
" CT_FIXED_FORM\n"
"};\n"
"\n"
"static inline enum constraint_type\n"
"get_constraint_type (enum constraint_num c)\n"
"{");
auto_vec <std::pair <unsigned int, const char *>, 3> values;
if (memory_start != memory_end)
values.safe_push (std::make_pair (memory_start, "CT_MEMORY"));
if (address_start != address_end)
values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
if (address_end != num_constraints)
values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM"));
print_type_tree (values, 0, values.length (), "CT_REGISTER", 2);
puts ("}");
}
puts ("#endif /* tm-preds.h */");

View File

@ -753,25 +753,28 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
break;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) != NO_REGS)
classes[i] = ira_reg_class_subunion[classes[i]]
[REG_CLASS_FROM_CONSTRAINT (c, p)];
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, p))
win = 1;
if (EXTRA_MEMORY_CONSTRAINT (c, p))
enum constraint_num cn = lookup_constraint (p);
enum reg_class cl;
switch (get_constraint_type (cn))
{
case CT_REGISTER:
cl = reg_class_for_constraint (cn);
if (cl != NO_REGS)
classes[i] = ira_reg_class_subunion[classes[i]][cl];
break;
case CT_MEMORY:
/* Every MEM can be reloaded to fit. */
insn_allows_mem[i] = allows_mem[i] = 1;
if (MEM_P (op))
win = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
break;
case CT_ADDRESS:
/* Every address can be reloaded to fit. */
allows_addr = 1;
if (address_operand (op, GET_MODE (op)))
if (address_operand (op, GET_MODE (op))
|| constraint_satisfied_p (op, cn))
win = 1;
/* We know this operand is an address, so we
want it to be allocated to a hard register
@ -781,8 +784,13 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
= ira_reg_class_subunion[classes[i]]
[base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)];
break;
case CT_FIXED_FORM:
if (constraint_satisfied_p (op, cn))
win = 1;
break;
}
#endif
break;
}
p += CONSTRAINT_LEN (c, p);
@ -1275,8 +1283,8 @@ record_operand_costs (rtx insn, enum reg_class *pref)
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]))
|| (insn_extra_address_constraint
(lookup_constraint (constraints[i]))))
record_address_regs (VOIDmode, ADDR_SPACE_GENERIC,
recog_data.operand[i], 0, ADDRESS, SCRATCH,
frequency * 2);

View File

@ -759,6 +759,7 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
{
int c;
enum reg_class cl, next_cl;
enum constraint_num cn;
cl = NO_REGS;
alternative_mask enabled = recog_data.enabled_alternatives;
@ -849,20 +850,19 @@ single_reg_class (const char *constraints, rtx op, rtx equiv_const)
case 'A': case 'B': case 'C': case 'D':
case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'W': case 'Y': case 'Z':
#ifdef EXTRA_CONSTRAINT_STR
/* ??? Is this the best way to handle memory constraints? */
if (EXTRA_MEMORY_CONSTRAINT (c, constraints)
|| EXTRA_ADDRESS_CONSTRAINT (c, constraints))
cn = lookup_constraint (constraints);
if (insn_extra_memory_constraint (cn)
|| insn_extra_address_constraint (cn))
return NO_REGS;
if (EXTRA_CONSTRAINT_STR (op, c, constraints)
if (constraint_satisfied_p (op, cn)
|| (equiv_const != NULL_RTX
&& CONSTANT_P (equiv_const)
&& EXTRA_CONSTRAINT_STR (equiv_const, c, constraints)))
&& constraint_satisfied_p (equiv_const, cn)))
return NO_REGS;
#endif
next_cl = (c == 'r'
? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (c, constraints));
: reg_class_for_constraint (cn));
if (next_cl == NO_REGS)
break;
if (cl == NO_REGS
@ -950,7 +950,7 @@ ira_implicitly_set_insn_hard_regs (HARD_REG_SET *set)
case 'W': case 'Y': case 'Z':
cl = (c == 'r'
? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (c, p));
: reg_class_for_constraint (lookup_constraint (p)));
if (cl != NO_REGS)
{
/* There is no register pressure problem if all of the

View File

@ -1922,24 +1922,29 @@ ira_setup_alts (rtx insn, HARD_REG_SET &alts)
break;
case 'o':
case 'r':
goto op_success;
break;
default:
{
enum reg_class cl;
cl = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
if (cl != NO_REGS)
goto op_success;
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, p))
goto op_success;
else if (EXTRA_MEMORY_CONSTRAINT (c, p))
goto op_success;
else if (EXTRA_ADDRESS_CONSTRAINT (c, p))
goto op_success;
#endif
enum constraint_num cn = lookup_constraint (p);
switch (get_constraint_type (cn))
{
case CT_REGISTER:
if (reg_class_for_constraint (cn) != NO_REGS)
goto op_success;
break;
case CT_ADDRESS:
case CT_MEMORY:
goto op_success;
case CT_FIXED_FORM:
if (constraint_satisfied_p (op, cn))
goto op_success;
break;
}
break;
}
}
@ -1972,9 +1977,6 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
int curr_alt, c, original, dup;
bool ignore_p, use_commut_op_p;
const char *str;
#ifdef EXTRA_CONSTRAINT_STR
rtx op;
#endif
if (op_num < 0 || recog_data.n_alternatives == 0)
return -1;
@ -1985,9 +1987,7 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
use_commut_op_p = false;
for (;;)
{
#ifdef EXTRA_CONSTRAINT_STR
op = recog_data.operand[op_num];
#endif
rtx op = recog_data.operand[op_num];
for (curr_alt = 0, ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt),
original = -1;;)
@ -2010,6 +2010,9 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
case 'g':
goto fail;
case 'r':
if (!targetm.class_likely_spilled_p (GENERAL_REGS))
goto fail;
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'h': case 'j': case 'k': case 'l':
case 'q': case 't': case 'u':
@ -2018,19 +2021,13 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'W': case 'Y': case 'Z':
{
enum reg_class cl;
cl = (c == 'r'
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
if (cl != NO_REGS)
{
if (! targetm.class_likely_spilled_p (cl))
goto fail;
}
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, str))
enum constraint_num cn = lookup_constraint (str);
enum reg_class cl = reg_class_for_constraint (cn);
if (cl != NO_REGS
&& !targetm.class_likely_spilled_p (cl))
goto fail;
if (constraint_satisfied_p (op, cn))
goto fail;
#endif
break;
}

View File

@ -394,40 +394,38 @@ valid_address_p (struct address_info *ad)
return valid_address_p (ad->mode, *ad->outer, ad->as);
}
#ifdef EXTRA_CONSTRAINT_STR
/* Return true if the eliminated form of memory reference OP satisfies
extra memory constraint CONSTRAINT. */
static bool
satisfies_memory_constraint_p (rtx op, const char *constraint)
satisfies_memory_constraint_p (rtx op, enum constraint_num constraint)
{
struct address_info ad;
decompose_mem_address (&ad, op);
address_eliminator eliminator (&ad);
return EXTRA_CONSTRAINT_STR (op, *constraint, constraint);
return constraint_satisfied_p (op, constraint);
}
/* Return true if the eliminated form of address AD satisfies extra
address constraint CONSTRAINT. */
static bool
satisfies_address_constraint_p (struct address_info *ad,
const char *constraint)
enum constraint_num constraint)
{
address_eliminator eliminator (ad);
return EXTRA_CONSTRAINT_STR (*ad->outer, *constraint, constraint);
return constraint_satisfied_p (*ad->outer, constraint);
}
/* Return true if the eliminated form of address OP satisfies extra
address constraint CONSTRAINT. */
static bool
satisfies_address_constraint_p (rtx op, const char *constraint)
satisfies_address_constraint_p (rtx op, enum constraint_num constraint)
{
struct address_info ad;
decompose_lea_address (&ad, &op);
return satisfies_address_constraint_p (&ad, constraint);
}
#endif
/* Initiate equivalences for LRA. As we keep original equivalences
before any elimination, we need to make copies otherwise any change
@ -982,21 +980,20 @@ reg_class_from_constraints (const char *p)
break;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
enum constraint_num cn = lookup_constraint (p);
enum reg_class cl = reg_class_for_constraint (cn);
if (cl == NO_REGS)
{
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
if (insn_extra_address_constraint (cn))
op_class
= (reg_class_subunion
[op_class][base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)]);
#endif
break;
}
op_class
= reg_class_subunion[op_class][REG_CLASS_FROM_CONSTRAINT (c, p)];
break;
op_class = reg_class_subunion[op_class][cl];
break;
}
while ((p += len), c);
return op_class;
@ -1712,6 +1709,7 @@ process_alt_operands (int only_alternative)
bool this_alternative_offmemok;
bool scratch_p;
enum machine_mode mode;
enum constraint_num cn;
opalt_num = nalt * n_operands + nop;
if (curr_static_id->operand_alternative[opalt_num].anything_ok)
@ -2030,76 +2028,55 @@ process_alt_operands (int only_alternative)
/* Drop through into 'r' case. */
case 'r':
this_alternative
= reg_class_subunion[this_alternative][GENERAL_REGS];
IOR_HARD_REG_SET (this_alternative_set,
reg_class_contents[GENERAL_REGS]);
if (costly_p)
{
this_costly_alternative
= (reg_class_subunion
[this_costly_alternative][GENERAL_REGS]);
IOR_HARD_REG_SET (this_costly_alternative_set,
reg_class_contents[GENERAL_REGS]);
}
cl = GENERAL_REGS;
goto reg;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
cn = lookup_constraint (p);
switch (get_constraint_type (cn))
{
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
if (MEM_P (op)
&& satisfies_memory_constraint_p (op, p))
win = true;
else if (spilled_pseudo_p (op))
win = true;
case CT_REGISTER:
cl = reg_class_for_constraint (cn);
if (cl != NO_REGS)
goto reg;
break;
/* If we didn't already win, we can reload
constants via force_const_mem or put the
pseudo value into memory, or make other
memory by reloading the address like for
'o'. */
if (CONST_POOL_OK_P (mode, op)
|| MEM_P (op) || REG_P (op))
badop = false;
constmemok = true;
offmemok = true;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
if (satisfies_address_constraint_p (op, p))
win = true;
/* If we didn't already win, we can reload
the address into a base register. */
cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH);
this_alternative
= reg_class_subunion[this_alternative][cl];
IOR_HARD_REG_SET (this_alternative_set,
reg_class_contents[cl]);
if (costly_p)
{
this_costly_alternative
= (reg_class_subunion
[this_costly_alternative][cl]);
IOR_HARD_REG_SET (this_costly_alternative_set,
reg_class_contents[cl]);
}
badop = false;
break;
}
if (EXTRA_CONSTRAINT_STR (op, c, p))
case CT_MEMORY:
if (MEM_P (op)
&& satisfies_memory_constraint_p (op, cn))
win = true;
else if (spilled_pseudo_p (op))
win = true;
/* If we didn't already win, we can reload constants
via force_const_mem or put the pseudo value into
memory, or make other memory by reloading the
address like for 'o'. */
if (CONST_POOL_OK_P (mode, op)
|| MEM_P (op) || REG_P (op))
badop = false;
constmemok = true;
offmemok = true;
break;
case CT_ADDRESS:
/* If we didn't already win, we can reload the address
into a base register. */
if (satisfies_address_constraint_p (op, cn))
win = true;
cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH);
badop = false;
goto reg;
case CT_FIXED_FORM:
if (constraint_satisfied_p (op, cn))
win = true;
#endif
break;
}
break;
cl = REG_CLASS_FROM_CONSTRAINT (c, p);
reg:
this_alternative = reg_class_subunion[this_alternative][cl];
IOR_HARD_REG_SET (this_alternative_set,
reg_class_contents[cl]);
@ -2110,7 +2087,6 @@ process_alt_operands (int only_alternative)
IOR_HARD_REG_SET (this_costly_alternative_set,
reg_class_contents[cl]);
}
reg:
if (mode == BLKmode)
break;
winreg = true;
@ -2856,10 +2832,11 @@ process_address_1 (int nop, rtx *before, rtx *after)
rtx new_reg;
rtx op = *curr_id->operand_loc[nop];
const char *constraint = curr_static_id->operand[nop].constraint;
enum constraint_num cn = lookup_constraint (constraint);
bool change_p;
if (constraint[0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint))
|| insn_extra_address_constraint (cn))
decompose_lea_address (&ad, curr_id->operand_loc[nop]);
else if (MEM_P (op))
decompose_mem_address (&ad, op);
@ -2888,14 +2865,12 @@ process_address_1 (int nop, rtx *before, rtx *after)
&& process_addr_reg (ad.index_term, before, NULL, INDEX_REG_CLASS))
change_p = true;
#ifdef EXTRA_CONSTRAINT_STR
/* Target hooks sometimes reject extra constraint addresses -- use
EXTRA_CONSTRAINT_STR for the validation. */
/* Target hooks sometimes don't treat extra-constraint addresses as
legitimate address_operands, so handle them specially. */
if (constraint[0] != 'p'
&& EXTRA_ADDRESS_CONSTRAINT (constraint[0], constraint)
&& satisfies_address_constraint_p (&ad, constraint))
&& insn_extra_address_constraint (cn)
&& satisfies_address_constraint_p (&ad, cn))
return change_p;
#endif
/* There are three cases where the shape of *AD.INNER may now be invalid:
@ -3617,11 +3592,10 @@ curr_insn_transform (void)
{
if (c == TARGET_MEM_CONSTRAINT || c == 'o')
break;
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
&& satisfies_memory_constraint_p (tem, constraint))
enum constraint_num cn = lookup_constraint (constraint);
if (insn_extra_memory_constraint (cn)
&& satisfies_memory_constraint_p (tem, cn))
break;
#endif
}
if (c == '\0' || c == ',' || c == '#')
continue;

View File

@ -574,8 +574,8 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
default:
rclass
= (reg_class_subunion
[(int) rclass]
[(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
[rclass]
[reg_class_for_constraint (lookup_constraint (p))]);
break;
case ',': case '\0':

View File

@ -1729,6 +1729,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
while (*constraint)
{
enum constraint_num cn;
char c = *constraint;
int len;
switch (c)
@ -1902,27 +1903,37 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
result = 1;
break;
default:
/* For all other letters, we first check for a register class,
otherwise it is an EXTRA_CONSTRAINT. */
if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
{
case 'r':
if (GET_MODE (op) == BLKmode)
break;
if (register_operand (op, VOIDmode))
result = 1;
}
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
/* Every memory operand can be reloaded to fit. */
result = result || memory_operand (op, VOIDmode);
else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
/* Every address operand can be reloaded to fit. */
result = result || address_operand (op, VOIDmode);
else if (EXTRA_CONSTRAINT_STR (op, c, constraint))
case 'r':
reg:
if (!result
&& GET_MODE (op) != BLKmode
&& register_operand (op, VOIDmode))
result = 1;
#endif
break;
default:
cn = lookup_constraint (constraint);
switch (get_constraint_type (cn))
{
case CT_REGISTER:
if (reg_class_for_constraint (cn) != NO_REGS)
goto reg;
break;
case CT_MEMORY:
/* Every memory operand can be reloaded to fit. */
result = result || memory_operand (op, VOIDmode);
break;
case CT_ADDRESS:
/* Every address operand can be reloaded to fit. */
result = result || address_operand (op, VOIDmode);
break;
case CT_FIXED_FORM:
result = result || constraint_satisfied_p (op, cn);
break;
}
break;
}
len = CONSTRAINT_LEN (c, constraint);
@ -2434,13 +2445,21 @@ preprocess_constraints (int n_operands, int n_alternatives,
break;
default:
if (EXTRA_MEMORY_CONSTRAINT (c, p))
enum constraint_num cn = lookup_constraint (p);
enum reg_class cl;
switch (get_constraint_type (cn))
{
case CT_REGISTER:
cl = reg_class_for_constraint (cn);
if (cl != NO_REGS)
op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl];
break;
case CT_MEMORY:
op_alt[i].memory_ok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
case CT_ADDRESS:
op_alt[i].is_address = 1;
op_alt[i].cl
= (reg_class_subunion
@ -2448,12 +2467,10 @@ preprocess_constraints (int n_operands, int n_alternatives,
[(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)]);
break;
}
op_alt[i].cl
= (reg_class_subunion
[(int) op_alt[i].cl]
[(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
case CT_FIXED_FORM:
break;
}
break;
}
p += CONSTRAINT_LEN (c, p);
@ -2846,9 +2863,12 @@ constrain_operands (int strict)
default:
{
enum reg_class cl;
enum constraint_num cn = (c == 'r'
? CONSTRAINT__UNKNOWN
: lookup_constraint (p));
cl = (c == 'r'
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
? GENERAL_REGS : reg_class_for_constraint (cn));
if (cl != NO_REGS)
{
if (strict < 0
@ -2860,11 +2880,11 @@ constrain_operands (int strict)
&& reg_fits_class_p (op, cl, offset, mode)))
win = 1;
}
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, p))
else if (constraint_satisfied_p (op, cn))
win = 1;
else if (EXTRA_MEMORY_CONSTRAINT (c, p)
else if (insn_extra_memory_constraint (cn)
/* Every memory operand can be reloaded to fit. */
&& ((strict < 0 && MEM_P (op))
/* Before reload, accept what reload can turn
@ -2874,7 +2894,7 @@ constrain_operands (int strict)
|| (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)))
win = 1;
else if (EXTRA_ADDRESS_CONSTRAINT (c, p)
else if (insn_extra_address_constraint (cn)
/* Every address operand can be reloaded to fit. */
&& strict < 0)
win = 1;
@ -2885,10 +2905,9 @@ constrain_operands (int strict)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (op)] < 0
&& reg_equiv_mem (REGNO (op)) != 0
&& EXTRA_CONSTRAINT_STR
(reg_equiv_mem (REGNO (op)), c, p))
&& constraint_satisfied_p
(reg_equiv_mem (REGNO (op)), cn))
win = 1;
#endif
break;
}
}
@ -3283,7 +3302,7 @@ peep2_find_free_register (int from, int to, const char *class_str,
}
cl = (class_str[0] == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
: reg_class_for_constraint (lookup_constraint (class_str)));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{

View File

@ -401,8 +401,8 @@ push_secondary_reload (int in_p, rtx x, int opnum, int optional,
scratch_constraint++;
letter = *scratch_constraint;
scratch_class = (letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
scratch_constraint));
: (reg_class_for_constraint
(lookup_constraint (scratch_constraint))));
rclass = scratch_class;
mode = insn_data[(int) icode].operand[2].mode;
@ -560,8 +560,7 @@ scratch_reload_class (enum insn_code icode)
scratch_letter = *scratch_constraint;
if (scratch_letter == 'r')
return GENERAL_REGS;
rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
scratch_constraint);
rclass = reg_class_for_constraint (lookup_constraint (scratch_constraint));
gcc_assert (rclass != NO_REGS);
return rclass;
}
@ -2852,7 +2851,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* Ignore things like match_operator operands. */
;
else if (constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
|| (insn_extra_address_constraint
(lookup_constraint (constraints[i]))))
{
address_operand_reloaded[i]
= find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
@ -3094,6 +3094,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
operand. */
int constmemok = 0;
int earlyclobber = 0;
enum constraint_num cn;
enum reg_class cl;
/* If the predicate accepts a unary operator, it means that
we need to reload the operand, but do not do this for
@ -3489,71 +3491,74 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
/* Drop through into 'r' case. */
case 'r':
this_alternative[i]
= reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
cl = GENERAL_REGS;
goto reg;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
cn = lookup_constraint (p);
switch (get_constraint_type (cn))
{
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
if (force_reload)
break;
if (EXTRA_CONSTRAINT_STR (operand, c, p))
win = 1;
/* If the address was already reloaded,
we win as well. */
else if (MEM_P (operand)
&& address_reloaded[i] == 1)
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
we have to check. */
else if (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
&& ((reg_equiv_mem (REGNO (operand)) != 0
&& EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
|| (reg_equiv_address (REGNO (operand)) != 0)))
win = 1;
case CT_REGISTER:
cl = reg_class_for_constraint (cn);
if (cl != NO_REGS)
goto reg;
break;
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
offmemok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
if (EXTRA_CONSTRAINT_STR (operand, c, p))
win = 1;
/* If we didn't already win, we can reload
the address into a base register. */
this_alternative[i]
= base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH);
badop = 0;
break;
}
if (EXTRA_CONSTRAINT_STR (operand, c, p))
case CT_MEMORY:
if (force_reload)
break;
if (constraint_satisfied_p (operand, cn))
win = 1;
/* If the address was already reloaded,
we win as well. */
else if (MEM_P (operand) && address_reloaded[i] == 1)
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
we have to check. */
else if (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
&& ((reg_equiv_mem (REGNO (operand)) != 0
&& (constraint_satisfied_p
(reg_equiv_mem (REGNO (operand)),
cn)))
|| (reg_equiv_address (REGNO (operand))
!= 0)))
win = 1;
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
offmemok = 1;
break;
case CT_ADDRESS:
if (constraint_satisfied_p (operand, cn))
win = 1;
/* If we didn't already win, we can reload
the address into a base register. */
this_alternative[i]
= base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH);
badop = 0;
break;
case CT_FIXED_FORM:
if (constraint_satisfied_p (operand, cn))
win = 1;
#endif
break;
}
break;
this_alternative[i]
= (reg_class_subunion
[this_alternative[i]]
[(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
reg:
this_alternative[i]
= reg_class_subunion[this_alternative[i]][cl];
if (GET_MODE (operand) == BLKmode)
break;
winreg = 1;
@ -4687,11 +4692,10 @@ alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
{
if (c == TARGET_MEM_CONSTRAINT || c == 'o')
return true;
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
&& (mem == NULL || EXTRA_CONSTRAINT_STR (mem, c, constraint)))
enum constraint_num cn = lookup_constraint (constraint);
if (insn_extra_memory_constraint (cn)
&& (mem == NULL || constraint_satisfied_p (mem, cn)))
return true;
#endif
}
return false;
}

View File

@ -1437,13 +1437,15 @@ maybe_fix_stack_asms (void)
break;
default:
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
enum constraint_num cn = lookup_constraint (p);
if (insn_extra_address_constraint (cn))
cls = (int) reg_class_subunion[cls]
[(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
ADDRESS, SCRATCH)];
else
cls = (int) reg_class_subunion[cls]
[(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
[reg_class_for_constraint (cn)];
break;
}
p += CONSTRAINT_LEN (c, p);
}

View File

@ -322,12 +322,11 @@ parse_output_constraint (const char **constraint_p, int operand_num,
default:
if (!ISALPHA (*p))
break;
if (REG_CLASS_FROM_CONSTRAINT (*p, p) != NO_REGS)
enum constraint_num cn = lookup_constraint (p);
if (reg_class_for_constraint (cn) != NO_REGS
|| insn_extra_address_constraint (cn))
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_ADDRESS_CONSTRAINT (*p, p))
*allows_reg = true;
else if (EXTRA_MEMORY_CONSTRAINT (*p, p))
else if (insn_extra_memory_constraint (cn))
*allows_mem = true;
else
{
@ -337,7 +336,6 @@ parse_output_constraint (const char **constraint_p, int operand_num,
*allows_reg = true;
*allows_mem = true;
}
#endif
break;
}
@ -454,13 +452,11 @@ parse_input_constraint (const char **constraint_p, int input_num,
error ("invalid punctuation %qc in constraint", constraint[j]);
return false;
}
if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
!= NO_REGS)
enum constraint_num cn = lookup_constraint (constraint + j);
if (reg_class_for_constraint (cn) != NO_REGS
|| insn_extra_address_constraint (cn))
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j], constraint + j))
*allows_reg = true;
else if (EXTRA_MEMORY_CONSTRAINT (constraint[j], constraint + j))
else if (insn_extra_memory_constraint (cn))
*allows_mem = true;
else
{
@ -470,7 +466,6 @@ parse_input_constraint (const char **constraint_p, int input_num,
*allows_reg = true;
*allows_mem = true;
}
#endif
break;
}

View File

@ -930,7 +930,10 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
GO_IF_MODE_DEPENDENT_ADDRESS DELAY_SLOTS_FOR_EPILOGUE \
ELIGIBLE_FOR_EPILOGUE_DELAY TARGET_C99_FUNCTIONS TARGET_HAS_SINCOS \
REG_CLASS_FROM_LETTER CONST_OK_FOR_LETTER_P \
CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT
CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT \
REG_CLASS_FROM_CONSTRAINT REG_CLASS_FOR_CONSTRAINT \
EXTRA_CONSTRAINT_STR EXTRA_MEMORY_CONSTRAINT \
EXTRA_ADDRESS_CONSTRAINT
/* Hooks that are no longer used. */
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \

View File

@ -936,8 +936,8 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
insn_letter = *insn_constraint;
insn_class
= (insn_letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
insn_constraint));
: (reg_class_for_constraint
(lookup_constraint (insn_constraint))));
gcc_assert (insn_class != NO_REGS);
}
@ -954,8 +954,8 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
scratch_letter = *scratch_constraint;
scratch_class
= (scratch_letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
scratch_constraint));
: (reg_class_for_constraint
(lookup_constraint (scratch_constraint))));
if (reg_class_subset_p (reload_class, insn_class))
{