defaults.h (EXTRA_MEMORY_CONSTRAINT): Add STR argument.

* defaults.h (EXTRA_MEMORY_CONSTRAINT): Add STR argument.
	(EXTRA_ADDRESS_CONSTRAINT): Likewise.
	(CONSTRAINT_LEN): Provide default definition.
	(CONST_OK_FOR_CONSTRAINT_P): Likewise.
	(CONST_DOUBLE_OK_FOR_CONSTRAINT_P): Likewise.
	(EXTRA_CONSTRAINT_STR): Likewise.
	(REG_CLASS_FROM_CONSTRAINT): Define.
	* genoutput.c (check_constraint_len, constraint_len): New functions.
	(validate_insn_alternatives): Check CONSTRAINT_LEN for each
	constraint / modifier.
	(gen_insn): Call check_constraint_len.
	* local-alloc.c (block_alloc): Update to use new macros / pass
	second argument to EXTRA_{MEMORY,ADDRESS}_CONSTRAINT.
	* ra-build.c (handle_asm_insn): Likewise.
	* recog.c (asm_operand_ok, preprocess_constraints): Likewise.
	(constrain_operands, peep2_find_free_register): Likewise.
	* regclass.c (record_operand_costs, record_reg_classes): Likewise.
	* regmove.c (find_matches): Likewise.
	* reload.c (push_secondary_reload, find_reloads): Likewise.
	(alternative_allows_memconst): Likewise.
	* reload1.c (maybe_fix_stack_asms): Likewise.
	(reload_cse_simplify_operands): Likewise.
	* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
	* doc/tm.texi (CONSTRAINT_LEN, REG_CLASS_FROM_CONSTRAINT): Document.
	(CONST_OK_FOR_CONSTRAINT_P): Likewise.
	(CONST_DOUBLE_OK_FOR_CONSTRAINT_P, EXTRA_CONSTRAINT_STR): Likewise.
	(EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Add STR argument.
	* config/s390/s390.h (EXTRA_MEMORY_CONSTRAINT): Likewise.

From-SVN: r61119
This commit is contained in:
J"orn Rennecke 2003-01-09 17:28:49 +00:00 committed by Joern Rennecke
parent e2c734c181
commit 9748887028
13 changed files with 626 additions and 355 deletions

View File

@ -1,4 +1,33 @@
Thu Jan 9 17:23:19 2003 J"orn Rennecke <joern.rennecke@superh.com>
Thu Jan 9 17:26:40 2003 J"orn Rennecke <joern.rennecke@superh.com>
* defaults.h (EXTRA_MEMORY_CONSTRAINT): Add STR argument.
(EXTRA_ADDRESS_CONSTRAINT): Likewise.
(CONSTRAINT_LEN): Provide default definition.
(CONST_OK_FOR_CONSTRAINT_P): Likewise.
(CONST_DOUBLE_OK_FOR_CONSTRAINT_P): Likewise.
(EXTRA_CONSTRAINT_STR): Likewise.
(REG_CLASS_FROM_CONSTRAINT): Define.
* genoutput.c (check_constraint_len, constraint_len): New functions.
(validate_insn_alternatives): Check CONSTRAINT_LEN for each
constraint / modifier.
(gen_insn): Call check_constraint_len.
* local-alloc.c (block_alloc): Update to use new macros / pass
second argument to EXTRA_{MEMORY,ADDRESS}_CONSTRAINT.
* ra-build.c (handle_asm_insn): Likewise.
* recog.c (asm_operand_ok, preprocess_constraints): Likewise.
(constrain_operands, peep2_find_free_register): Likewise.
* regclass.c (record_operand_costs, record_reg_classes): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (push_secondary_reload, find_reloads): Likewise.
(alternative_allows_memconst): Likewise.
* reload1.c (maybe_fix_stack_asms): Likewise.
(reload_cse_simplify_operands): Likewise.
* stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
* doc/tm.texi (CONSTRAINT_LEN, REG_CLASS_FROM_CONSTRAINT): Document.
(CONST_OK_FOR_CONSTRAINT_P): Likewise.
(CONST_DOUBLE_OK_FOR_CONSTRAINT_P, EXTRA_CONSTRAINT_STR): Likewise.
(EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Add STR argument.
* config/s390/s390.h (EXTRA_MEMORY_CONSTRAINT): Likewise.
* sh.h (OVERRIDE_OPTIONS): Allow first scheduling pass for SH5.

View File

@ -473,7 +473,7 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
((C) == 'Q' ? q_constraint (OP) : \
(C) == 'S' ? larl_operand (OP, GET_MODE (OP)) : 0)
#define EXTRA_MEMORY_CONSTRAINT(C) ((C) == 'Q')
#define EXTRA_MEMORY_CONSTRAINT(C,STR) ((C) == 'Q')
/* Stack layout and calling conventions. */

View File

@ -604,13 +604,38 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
/* Determine whether extra constraint letter should be handled
via address reload (like 'o'). */
#ifndef EXTRA_MEMORY_CONSTRAINT
#define EXTRA_MEMORY_CONSTRAINT(C) 0
#define EXTRA_MEMORY_CONSTRAINT(C,STR) 0
#endif
/* Determine whether extra constraint letter should be handled
as an address (like 'p'). */
#ifndef EXTRA_ADDRESS_CONSTRAINT
#define EXTRA_ADDRESS_CONSTRAINT(C) 0
#define EXTRA_ADDRESS_CONSTRAINT(C,STR) 0
#endif
/* When a port defines CONSTRAINT_LEN, it should use DEFAULT_CONSTRAINT_LEN
for all the characters that it does not want to change, so things like the
'length' of a digit in a matching constraint is an implementation detail,
and not part of the interface. */
#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
#ifndef CONSTRAINT_LEN
#define CONSTRAINT_LEN(C,STR) DEFAULT_CONSTRAINT_LEN (C, STR)
#endif
#if defined (CONST_OK_FOR_LETTER_P) && ! defined (CONST_OK_FOR_CONSTRAINT_P)
#define CONST_OK_FOR_CONSTRAINT_P(VAL,C,STR) CONST_OK_FOR_LETTER_P (VAL, C)
#endif
#if defined (CONST_DOUBLE_OK_FOR_LETTER_P) && ! defined (CONST_DOUBLE_OK_FOR_CONSTRAINT_P)
#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(OP,C,STR) \
CONST_DOUBLE_OK_FOR_LETTER_P (OP, C)
#endif
#define REG_CLASS_FROM_CONSTRAINT(C,STR) REG_CLASS_FROM_LETTER (C)
#if defined (EXTRA_CONSTRAINT) && ! defined (EXTRA_CONSTRAINT_STR)
#define EXTRA_CONSTRAINT_STR(OP, C,STR) EXTRA_CONSTRAINT (OP, C)
#endif
#endif /* ! GCC_DEFAULTS_H */

View File

@ -1910,7 +1910,8 @@ If the usage of an entire class of registers depends on the target
flags, you may indicate this to GCC by using this macro to modify
@code{fixed_regs} and @code{call_used_regs} to 1 for each of the
registers in the classes which should not be used by GCC@. Also define
the macro @code{REG_CLASS_FROM_LETTER} to return @code{NO_REGS} if it
the macro @code{REG_CLASS_FROM_LETTER} / @code{REG_CLASS_FROM_CONSTRAINT}
to return @code{NO_REGS} if it
is called with a letter for a class that shouldn't be used.
(However, if this class is not included in @code{GENERAL_REGS} and all
@ -2330,6 +2331,21 @@ index register must belong. An index register is one used in an
address where its value is either multiplied by a scale factor or
added to another register (as well as added to a displacement).
@findex CONSTRAINT_LEN
@item CONSTRAINT_LEN (@var{char}, @var{str})
For the constraint at the start of @var{str}, which starts with the letter
@var{c}, return the length. This allows you to have register class /
constant / extra constraints that are longer than a single letter;
you don't need to define this macro if you can do with single-letter
constraints only. The definition of this macro should use
DEFAULT_CONSTRAINT_LEN for all the characters that you don't want
to handle specially.
There are some sanity checks in genoutput.c that check the constraint lengths
for the md file, so you can also use this macro to help you while you are
transitioning from a byzantine single-letter-constraint scheme: when you
return a negative length for a constraint you want to re-use, genoutput
will complain about every instance where it is used in the md file.
@findex REG_CLASS_FROM_LETTER
@item REG_CLASS_FROM_LETTER (@var{char})
A C expression which defines the machine-dependent operand constraint
@ -2339,6 +2355,12 @@ the value should be @code{NO_REGS}. The register letter @samp{r},
corresponding to class @code{GENERAL_REGS}, will not be passed
to this macro; you do not need to handle it.
@findex REG_CLASS_FROM_CONSTRAINT
@item REG_CLASS_FROM_CONSTRAINT (@var{char}, @var{str})
Like @code{REG_CLASS_FROM_LETTER}, but you also get the constraint string
passed in @var{str}, so that you can use suffixes to distinguish between
different variants.
@findex REGNO_OK_FOR_BASE_P
@item REGNO_OK_FOR_BASE_P (@var{num})
A C expression which is nonzero if register number @var{num} is
@ -2608,6 +2630,12 @@ the appropriate range and return 1 if so, 0 otherwise. If @var{c} is
not one of those letters, the value should be 0 regardless of
@var{value}.
@findex CONST_OK_FOR_CONSTRAINT_P
@item CONST_OK_FOR_CONSTRAINT_P (@var{value}, @var{c}, @var{str})
Like @code{CONST_OK_FOR_LETTER_P}, but you also get the constraint
string passed in @var{str}, so that you can use suffixes to distinguish
between different variants.
@findex CONST_DOUBLE_OK_FOR_LETTER_P
@item CONST_DOUBLE_OK_FOR_LETTER_P (@var{value}, @var{c})
A C expression that defines the machine-dependent operand constraint
@ -2624,12 +2652,19 @@ letters, the value should be 0 regardless of @var{value}.
or both kinds of values. It can use @code{GET_MODE} to distinguish
between these kinds.
@findex CONST_DOUBLE_OK_FOR_CONSTRAINT_P
@item CONST_DOUBLE_OK_FOR_CONSTRAINT_P (@var{value}, @var{c}, @var{str})
Like @code{CONST_DOUBLE_OK_FOR_LETTER_P}, but you also get the constraint
string passed in @var{str}, so that you can use suffixes to distinguish
between different variants.
@findex EXTRA_CONSTRAINT
@item EXTRA_CONSTRAINT (@var{value}, @var{c})
A C expression that defines the optional machine-dependent constraint
letters that can be used to segregate specific types of operands, usually
memory references, for the target machine. Any letter that is not
elsewhere defined and not matched by @code{REG_CLASS_FROM_LETTER}
elsewhere defined and not matched by @code{REG_CLASS_FROM_LETTER} /
@code{REG_CLASS_FROM_CONSTRAINT}
may be used. Normally this macro will not be defined.
If it is required for a particular target machine, it should return 1
@ -2645,14 +2680,21 @@ a @samp{Q} constraint on the input and @samp{r} on the output. The next
alternative specifies @samp{m} on the input and a register class that
does not include r0 on the output.
@findex EXTRA_CONSTRAINT_STR
@item EXTRA_CONSTRAINT_STR (@var{value}, @var{c}, @var{str})
Like @code{EXTRA_CONSTRAINT}, but you also get the constraint string passed
in @var{str}, so that you can use suffixes to distinguish between different
variants.
@findex EXTRA_MEMORY_CONSTRAINT
@item EXTRA_MEMORY_CONSTRAINT (@var{c})
@item EXTRA_MEMORY_CONSTRAINT (@var{c}, @var{str})
A C expression that defines the optional machine-dependent constraint
letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
be treated like memory constraints by the reload pass.
It should return 1 if the operand type represented by the constraint
letter @var{c} comprises a subset of all memory references including
at the start of @var{str}, the first letter of which is the letter @var{c},
comprises a subset of all memory references including
all those whose address is simply a base register. This allows the reload
pass to reload an operand, if it does not directly correspond to the operand
type of @var{c}, by copying its address into a base register.
@ -2668,16 +2710,18 @@ into a base register if required. This is analogous to the way
a @samp{o} constraint can handle any memory operand.
@findex EXTRA_ADDRESS_CONSTRAINT
@item EXTRA_ADDRESS_CONSTRAINT (@var{c})
@item EXTRA_ADDRESS_CONSTRAINT (@var{c}, @var{str})
A C expression that defines the optional machine-dependent constraint
letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
letters, amongst those accepted by @code{EXTRA_CONSTRAINT} /
@code{EXTRA_CONSTRAINT_STR}, that should
be treated like address constraints by the reload pass.
It should return 1 if the operand type represented by the constraint
letter @var{c} comprises a subset of all memory addresses including
at the startr of @{str}, which starts with the letter @var{c}, comprises
a subset of all memory addresses including
all those that consist of just a base register. This allows the reload
pass to reload an operand, if it does not directly correspond to the operand
type of @var{c}, by copying it into a base register.
type of @var{str}, by copying it into a base register.
Any constraint marked as @code{EXTRA_ADDRESS_CONSTRAINT} can only
be used with the @code{address_operand} predicate. It is treated

View File

@ -189,6 +189,8 @@ static void gen_insn PARAMS ((rtx, int));
static void gen_peephole PARAMS ((rtx, int));
static void gen_expand PARAMS ((rtx, int));
static void gen_split PARAMS ((rtx, int));
static void check_constraint_len PARAMS ((void));
static int constraint_len PARAMS ((const char *, int));
const char *
get_insn_name (index)
@ -749,7 +751,51 @@ validate_insn_alternatives (d)
for (start = 0; start < d->n_operands; start++)
if (d->operand[start].n_alternatives > 0)
{
if (n == 0)
int len, i;
const char *p;
char c;
int which_alternative = 0;
int alternative_count_unsure = 0;
for (p = d->operand[start].constraint; (c = *p); p += len)
{
len = CONSTRAINT_LEN (c, p);
if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
{
message_with_line (d->lineno,
"invalid length %d for char '%c' in alternative %d of operand %d",
len, c, which_alternative, start);
len = 1;
have_error = 1;
}
if (c == ',')
{
which_alternative++;
continue;
}
for (i = 1; i < len; i++)
if (p[i] == '\0')
{
message_with_line (d->lineno,
"NUL in alternative %d of operand %d",
which_alternative, start);
alternative_count_unsure = 1;
break;
}
else if (strchr (",#*", p[i]))
{
message_with_line (d->lineno,
"'%c' in alternative %d of operand %d",
p[i], which_alternative, start);
alternative_count_unsure = 1;
}
}
if (alternative_count_unsure)
have_error = 1;
else if (n == 0)
n = d->operand[start].n_alternatives;
else if (n != d->operand[start].n_alternatives)
{
@ -816,6 +862,7 @@ gen_insn (insn, lineno)
d->n_operands = max_opno + 1;
d->n_dups = num_dups;
check_constraint_len ();
validate_insn_operands (d);
validate_insn_alternatives (d);
place_operands (d);
@ -1043,3 +1090,41 @@ strip_whitespace (s)
*p = '\0';
return q;
}
/* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not
tampered with. This isn't bullet-proof, but it should catch
most genuine mistakes. */
static void
check_constraint_len ()
{
const char *p;
int d;
for (p = ",#*+=&%!1234567890"; *p; p++)
for (d = -9; d < 9; d++)
if (constraint_len (p, d) != d)
abort ();
}
static int
constraint_len (p, genoutput_default_constraint_len)
const char *p;
int genoutput_default_constraint_len;
{
/* Check that we still match defaults.h . First we do a generation-time
check that fails if the value is not the expected one... */
if (DEFAULT_CONSTRAINT_LEN (*p, p) != 1)
abort ();
/* And now a comile-time check that should give a diagnostic if the
definition doesn't exactly match. */
#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
/* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is
being used. */
#undef DEFAULT_CONSTRAINT_LEN
#define DEFAULT_CONSTRAINT_LEN(C,STR) \
((C) != *p || STR != p ? -1 : genoutput_default_constraint_len)
return CONSTRAINT_LEN (*p, p);
/* And set it back. */
#undef DEFAULT_CONSTRAINT_LEN
#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
}

View File

@ -1338,7 +1338,8 @@ block_alloc (b)
There may be more than one register, but we only try one
of them. */
if (recog_data.constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
|| EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0],
recog_data.constraints[i]))
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
r1 = XEXP (r1, 0);
@ -2424,50 +2425,56 @@ requires_inout (p)
int found_zero = 0;
int reg_allowed = 0;
int num_matching_alts = 0;
int len;
while ((c = *p++))
switch (c)
{
case '=': case '+': case '?':
case '#': case '&': case '!':
case '*': case '%':
case 'm': case '<': case '>': case 'V': case 'o':
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
case 'X':
/* These don't say anything we care about. */
break;
case ',':
if (found_zero && ! reg_allowed)
num_matching_alts++;
found_zero = reg_allowed = 0;
break;
case '0':
found_zero = 1;
break;
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
/* Skip the balance of the matching constraint. */
while (ISDIGIT (*p))
p++;
break;
default:
if (REG_CLASS_FROM_LETTER (c) == NO_REGS
&& !EXTRA_ADDRESS_CONSTRAINT (c))
for ( ; c = *p; p += len)
{
len = CONSTRAINT_LEN (c, p);
switch (c)
{
case '=': case '+': case '?':
case '#': case '&': case '!':
case '*': case '%':
case 'm': case '<': case '>': case 'V': case 'o':
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
case 'X':
/* These don't say anything we care about. */
break;
/* FALLTHRU */
case 'p':
case 'g': case 'r':
reg_allowed = 1;
break;
}
case ',':
if (found_zero && ! reg_allowed)
num_matching_alts++;
found_zero = reg_allowed = 0;
break;
case '0':
found_zero = 1;
break;
case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9':
/* Skip the balance of the matching constraint. */
do
p++;
while (ISDIGIT (*p));
len = 0;
break;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS
&& !EXTRA_ADDRESS_CONSTRAINT (c, p))
break;
/* FALLTHRU */
case 'p':
case 'g': case 'r':
reg_allowed = 1;
break;
}
}
if (found_zero && ! reg_allowed)
num_matching_alts++;

View File

@ -2933,13 +2933,13 @@ handle_asm_insn (df, insn)
CLEAR_HARD_REG_SET (allowed);
while (1)
{
char c = *p++;
char c = *p;
if (c == '\0' || c == ',' || c == '#')
{
/* End of one alternative - mark the regs in the current
class, and reset the class.
*/
class, and reset the class. */
p++;
IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
if (cls != NO_REGS)
nothing_allowed = 0;
@ -2977,8 +2977,10 @@ handle_asm_insn (df, insn)
default:
cls =
(int) reg_class_subunion[cls][(int)
REG_CLASS_FROM_LETTER (c)];
REG_CLASS_FROM_CONSTRAINT (c,
p)];
}
p += CONSTRAINT_LEN (c, p);
}
/* Now make conflicts between this web, and all hardregs, which

View File

@ -1681,18 +1681,21 @@ asm_operand_ok (op, constraint)
while (*constraint)
{
char c = *constraint++;
char c = *constraint;
int len;
switch (c)
{
case ',':
constraint++;
continue;
case '=':
case '+':
case '*':
case '%':
case '?':
case '!':
case '#':
case '&':
case ',':
case '?':
break;
case '0': case '1': case '2': case '3': case '4':
@ -1701,25 +1704,27 @@ asm_operand_ok (op, constraint)
proper matching constraint, but we can't actually fail
the check if they didn't. Indicate that results are
inconclusive. */
while (ISDIGIT (*constraint))
do
constraint++;
result = -1;
break;
while (ISDIGIT (*constraint));
if (! result)
result = -1;
continue;
case 'p':
if (address_operand (op, VOIDmode))
return 1;
result = 1;
break;
case 'm':
case 'V': /* non-offsettable */
if (memory_operand (op, VOIDmode))
return 1;
result = 1;
break;
case 'o': /* offsettable */
if (offsettable_nonstrict_memref_p (op))
return 1;
result = 1;
break;
case '<':
@ -1734,7 +1739,7 @@ asm_operand_ok (op, constraint)
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
return 1;
result = 1;
break;
case '>':
@ -1742,7 +1747,7 @@ asm_operand_ok (op, constraint)
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
return 1;
result = 1;
break;
case 'E':
@ -1750,18 +1755,18 @@ asm_operand_ok (op, constraint)
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
return 1;
result = 1;
break;
case 'G':
if (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
return 1;
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
result = 1;
break;
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
return 1;
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
result = 1;
break;
case 's':
@ -1777,94 +1782,100 @@ asm_operand_ok (op, constraint)
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
)
return 1;
result = 1;
break;
case 'n':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
return 1;
result = 1;
break;
case 'I':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
result = 1;
break;
case 'J':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
result = 1;
break;
case 'K':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
result = 1;
break;
case 'L':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
result = 1;
break;
case 'M':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
result = 1;
break;
case 'N':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
result = 1;
break;
case 'O':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
result = 1;
break;
case 'P':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
return 1;
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
result = 1;
break;
case 'X':
return 1;
result = 1;
case 'g':
if (general_operand (op, VOIDmode))
return 1;
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_LETTER (c) != NO_REGS)
if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
{
case 'r':
if (GET_MODE (op) == BLKmode)
break;
if (register_operand (op, VOIDmode))
return 1;
result = 1;
}
#ifdef EXTRA_CONSTRAINT
if (EXTRA_CONSTRAINT (op, c))
return 1;
if (EXTRA_MEMORY_CONSTRAINT (c))
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_CONSTRAINT_STR (op, c, constraint))
result = 1;
if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
{
/* Every memory operand can be reloaded to fit. */
if (memory_operand (op, VOIDmode))
return 1;
result = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
{
/* Every address operand can be reloaded to fit. */
if (address_operand (op, VOIDmode))
return 1;
result = 1;
}
#endif
break;
}
len = CONSTRAINT_LEN (c, constraint);
do
constraint++;
while (--len && *constraint);
if (len)
return 0;
}
return result;
@ -2233,13 +2244,16 @@ preprocess_constraints ()
for (;;)
{
char c = *p++;
char c = *p;
if (c == '#')
do
c = *p++;
c = *++p;
while (c != ',' && c != '\0');
if (c == ',' || c == '\0')
break;
{
p++;
break;
}
switch (c)
{
@ -2265,11 +2279,11 @@ preprocess_constraints ()
case '5': case '6': case '7': case '8': case '9':
{
char *end;
op_alt[j].matches = strtoul (p - 1, &end, 10);
op_alt[j].matches = strtoul (p, &end, 10);
recog_op_alt[op_alt[j].matches][j].matched = i;
p = end;
}
break;
continue;
case 'm':
op_alt[j].memory_ok = 1;
@ -2301,22 +2315,28 @@ preprocess_constraints ()
break;
default:
if (EXTRA_MEMORY_CONSTRAINT (c))
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
op_alt[j].memory_ok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
op_alt[j].is_address = 1;
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
op_alt[j].class
= (reg_class_subunion
[(int) op_alt[j].class]
[(int) MODE_BASE_REG_CLASS (VOIDmode)]);
break;
}
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
op_alt[j].class
= (reg_class_subunion
[(int) op_alt[j].class]
[(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
break;
}
p += CONSTRAINT_LEN (c, p);
}
}
}
@ -2331,7 +2351,7 @@ preprocess_constraints ()
alternative of constraints was matched: 0 for the first alternative,
1 for the next, etc.
In addition, when two operands are match
In addition, when two operands are required to match
and it happens that the output operand is (reg) while the
input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
make the output operand look like the input.
@ -2390,6 +2410,7 @@ constrain_operands (strict)
int offset = 0;
int win = 0;
int val;
int len;
earlyclobber[opno] = 0;
@ -2414,9 +2435,16 @@ constrain_operands (strict)
if (*p == 0 || *p == ',')
win = 1;
while (*p && (c = *p++) != ',')
switch (c)
do
switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
{
case '\0':
len = 0;
break;
case ',':
c = '\0';
break;
case '?': case '!': case '*': case '%':
case '=': case '+':
break;
@ -2424,8 +2452,10 @@ constrain_operands (strict)
case '#':
/* Ignore rest of this alternative as far as
constraint checking is concerned. */
while (*p && *p != ',')
do
p++;
while (*p && *p != ',');
len = 0;
break;
case '&':
@ -2447,7 +2477,7 @@ constrain_operands (strict)
char *end;
int match;
match = strtoul (p - 1, &end, 10);
match = strtoul (p, &end, 10);
p = end;
if (strict < 0)
@ -2482,6 +2512,7 @@ constrain_operands (strict)
funny_match[funny_match_index++].other = match;
}
}
len = 0;
break;
case 'p':
@ -2551,7 +2582,7 @@ constrain_operands (strict)
case 'G':
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
win = 1;
break;
@ -2581,7 +2612,7 @@ constrain_operands (strict)
case 'O':
case 'P':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), c))
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
win = 1;
break;
@ -2612,7 +2643,8 @@ constrain_operands (strict)
{
enum reg_class class;
class = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (c));
class = (c == 'r'
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
if (class != NO_REGS)
{
if (strict < 0
@ -2624,11 +2656,11 @@ constrain_operands (strict)
&& reg_fits_class_p (op, class, offset, mode)))
win = 1;
}
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, p))
win = 1;
if (EXTRA_MEMORY_CONSTRAINT (c))
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
/* Every memory operand can be reloaded to fit. */
if (strict < 0 && GET_CODE (op) == MEM)
@ -2643,7 +2675,7 @@ constrain_operands (strict)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
win = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
/* Every address operand can be reloaded to fit. */
if (strict < 0)
@ -2653,6 +2685,7 @@ constrain_operands (strict)
break;
}
}
while (p += len, c);
constraints[opno] = p;
/* If this operand did not win somehow,
@ -3009,7 +3042,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
}
class = (class_str[0] == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_LETTER (class_str[0]));
: REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{

View File

@ -977,7 +977,7 @@ record_operand_costs (insn, op_costs, reg_pref)
record_address_regs (XEXP (recog_data.operand[i], 0),
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
else if (constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
record_address_regs (recog_data.operand[i],
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
}
@ -1548,154 +1548,161 @@ record_reg_classes (n_alts, n_ops, ops, modes,
any of the constraints. Collect the valid register classes
and see if this operand accepts memory. */
while (*p && (c = *p++) != ',')
switch (c)
{
case '*':
/* Ignore the next letter for this pass. */
p++;
break;
case '?':
alt_cost += 2;
case '!': case '#': case '&':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
case 'p':
allows_addr = 1;
win = address_operand (op, GET_MODE (op));
/* We know this operand is an address, so we want it to be
allocated to a register that can be the base of an
address, ie BASE_REG_CLASS. */
classes[i]
= reg_class_subunion[(int) classes[i]]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
break;
case 'm': case 'o': case 'V':
/* It doesn't seem worth distinguishing between offsettable
and non-offsettable addresses here. */
allows_mem[i] = 1;
if (GET_CODE (op) == MEM)
win = 1;
break;
case '<':
if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
win = 1;
break;
case '>':
if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
win = 1;
break;
case 'E':
case 'F':
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& (GET_MODE_CLASS (GET_MODE (op))
== MODE_VECTOR_FLOAT)))
win = 1;
break;
case 'G':
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
win = 1;
break;
case 's':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
while ((c = *p))
{
switch (c)
{
case ',':
break;
case '*':
/* Ignore the next letter for this pass. */
c = *++p;
break;
case 'i':
if (CONSTANT_P (op)
#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
)
win = 1;
break;
case 'n':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
win = 1;
break;
case '?':
alt_cost += 2;
case '!': case '#': case '&':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op), c))
win = 1;
break;
case 'X':
win = 1;
break;
case 'g':
if (GET_CODE (op) == MEM
|| (CONSTANT_P (op)
#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
))
win = 1;
allows_mem[i] = 1;
case 'r':
classes[i]
= reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
break;
default:
if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
case 'p':
allows_addr = 1;
win = address_operand (op, GET_MODE (op));
/* We know this operand is an address, so we want it to be
allocated to a register that can be the base of an
address, ie BASE_REG_CLASS. */
classes[i]
= reg_class_subunion[(int) classes[i]]
[(int) REG_CLASS_FROM_LETTER (c)];
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
break;
if (EXTRA_MEMORY_CONSTRAINT (c))
{
/* Every MEM can be reloaded to fit. */
allows_mem[i] = 1;
if (GET_CODE (op) == MEM)
win = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (op))
{
/* Every address can be reloaded to fit. */
allows_addr = 1;
if (address_operand (op, GET_MODE (op)))
win = 1;
/* We know this operand is an address, so we want it to be
allocated to a register that can be the base of an
address, ie BASE_REG_CLASS. */
case 'm': case 'o': case 'V':
/* It doesn't seem worth distinguishing between offsettable
and non-offsettable addresses here. */
allows_mem[i] = 1;
if (GET_CODE (op) == MEM)
win = 1;
break;
case '<':
if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
win = 1;
break;
case '>':
if (GET_CODE (op) == MEM
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
win = 1;
break;
case 'E':
case 'F':
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& (GET_MODE_CLASS (GET_MODE (op))
== MODE_VECTOR_FLOAT)))
win = 1;
break;
case 'G':
case 'H':
if (GET_CODE (op) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
win = 1;
break;
case 's':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
break;
case 'i':
if (CONSTANT_P (op)
#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
)
win = 1;
break;
case 'n':
if (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
win = 1;
break;
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
if (GET_CODE (op) == CONST_INT
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
win = 1;
break;
case 'X':
win = 1;
break;
case 'g':
if (GET_CODE (op) == MEM
|| (CONSTANT_P (op)
#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
))
win = 1;
allows_mem[i] = 1;
case 'r':
classes[i]
= reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
break;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) != NO_REGS)
classes[i]
= reg_class_subunion[(int) classes[i]]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
}
[(int) 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))
{
/* Every MEM can be reloaded to fit. */
allows_mem[i] = 1;
if (GET_CODE (op) == MEM)
win = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
/* Every address can be reloaded to fit. */
allows_addr = 1;
if (address_operand (op, GET_MODE (op)))
win = 1;
/* We know this operand is an address, so we want it to
be allocated to a register that can be the base of an
address, ie BASE_REG_CLASS. */
classes[i]
= reg_class_subunion[(int) classes[i]]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
}
#endif
break;
}
p += CONSTRAINT_LEN (c, p);
if (c == ',')
break;
}
}
constraints[i] = p;

View File

@ -1570,47 +1570,50 @@ find_matches (insn, matchp)
if (*p == ',')
i++;
while ((c = *p++) != '\0' && c != ',')
switch (c)
{
case '=':
break;
case '+':
break;
case '&':
matchp->early_clobber[op_no] = 1;
break;
case '%':
matchp->commutative[op_no] = op_no + 1;
matchp->commutative[op_no + 1] = op_no;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
while ((c = *p) != '\0' && c != ',')
{
switch (c)
{
char *end;
unsigned long match_ul = strtoul (p - 1, &end, 10);
int match = match_ul;
case '=':
break;
case '+':
break;
case '&':
matchp->early_clobber[op_no] = 1;
break;
case '%':
matchp->commutative[op_no] = op_no + 1;
matchp->commutative[op_no + 1] = op_no;
break;
p = end;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
char *end;
unsigned long match_ul = strtoul (p, &end, 10);
int match = match_ul;
if (match < op_no && likely_spilled[match])
break;
matchp->with[op_no] = match;
any_matches = 1;
if (matchp->commutative[op_no] >= 0)
matchp->with[matchp->commutative[op_no]] = match;
}
break;
p = end;
if (match < op_no && likely_spilled[match])
continue;
matchp->with[op_no] = match;
any_matches = 1;
if (matchp->commutative[op_no] >= 0)
matchp->with[matchp->commutative[op_no]] = match;
}
continue;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h':
case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
case 'C': case 'D': case 'W': case 'Y': case 'Z':
if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_LETTER ((unsigned char) c)))
if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p) ))
likely_spilled[op_no] = 1;
break;
}
p += CONSTRAINT_LEN (c, p);
}
}
return any_matches;
}

View File

@ -381,11 +381,13 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
insn_class = ALL_REGS;
else
{
char insn_letter
= insn_data[(int) icode].operand[!in_p].constraint[in_p];
const char *insn_constraint
= &insn_data[(int) icode].operand[!in_p].constraint[in_p];
char insn_letter = *insn_constraint;
insn_class
= (insn_letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_LETTER ((unsigned char) insn_letter));
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
insn_constraint));
if (insn_class == NO_REGS)
abort ();
@ -403,11 +405,14 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
mode = insn_data[(int) icode].operand[2].mode;
else
{
char t_letter = insn_data[(int) icode].operand[2].constraint[2];
const char *t_constraint
= &insn_data[(int) icode].operand[2].constraint[2];
char t_letter = *t_constraint;
class = insn_class;
t_mode = insn_data[(int) icode].operand[2].mode;
t_class = (t_letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_LETTER ((unsigned char) t_letter));
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) t_letter,
t_constraint));
t_icode = icode;
icode = CODE_FOR_nothing;
}
@ -2587,8 +2592,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* Scan this operand's constraint to see if it is an output operand,
an in-out operand, is commutative, or should match another. */
while ((c = *p++))
while ((c = *p))
{
p += CONSTRAINT_LEN (c, p);
if (c == '=')
modified[i] = RELOAD_WRITE;
else if (c == '+')
@ -2664,7 +2670,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* Ignore things like match_operator operands. */
;
else if (constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
{
find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
recog_data.operand[i],
@ -2829,6 +2835,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
for (i = 0; i < noperands; i++)
{
char *p = constraints[i];
char *end;
int len;
int win = 0;
int did_match = 0;
/* 0 => this operand can be reloaded somehow for this alternative. */
@ -2836,6 +2844,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* 0 => this operand can be reloaded if the alternative allows regs. */
int winreg = 0;
int c;
int m;
rtx operand = recog_data.operand[i];
int offset = 0;
/* Nonzero means this is a MEM that must be reloaded into a reg
@ -2964,9 +2973,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
or set WINREG if this operand could fit after reloads
provided the constraint allows some registers. */
while (*p && (c = *p++) != ',')
switch (c)
do
switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c)
{
case '\0':
len = 0;
break;
case ',':
c = '\0';
break;
case '=': case '+': case '*':
break;
@ -2987,15 +3003,19 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
case '#':
/* Ignore rest of this alternative as far as
reloading is concerned. */
while (*p && *p != ',')
do
p++;
while (*p && *p != ',');
len = 0;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = strtoul (p - 1, &p, 10);
m = strtoul (p, &end, 10);
p = end;
len = 0;
this_alternative_matches[i] = c;
this_alternative_matches[i] = m;
/* We are supposed to match a previous operand.
If we do, we win if that one did.
If we do not, count both of the operands as losers.
@ -3003,7 +3023,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
only a single reload insn will be needed to make
the two operands win. As a result, this alternative
may be rejected when it is actually desirable.) */
if ((swapped && (c != commutative || i != commutative + 1))
if ((swapped && (m != commutative || i != commutative + 1))
/* If we are matching as if two operands were swapped,
also pretend that operands_match had been computed
with swapped.
@ -3011,22 +3031,22 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
don't exchange them, because operands_match is valid
only on one side of its diagonal. */
? (operands_match
[(c == commutative || c == commutative + 1)
? 2 * commutative + 1 - c : c]
[(m == commutative || m == commutative + 1)
? 2 * commutative + 1 - m : m]
[(i == commutative || i == commutative + 1)
? 2 * commutative + 1 - i : i])
: operands_match[c][i])
: operands_match[m][i])
{
/* If we are matching a non-offsettable address where an
offsettable address was expected, then we must reject
this combination, because we can't reload it. */
if (this_alternative_offmemok[c]
&& GET_CODE (recog_data.operand[c]) == MEM
&& this_alternative[c] == (int) NO_REGS
&& ! this_alternative_win[c])
if (this_alternative_offmemok[m]
&& GET_CODE (recog_data.operand[m]) == MEM
&& this_alternative[m] == (int) NO_REGS
&& ! this_alternative_win[m])
bad = 1;
did_match = this_alternative_win[c];
did_match = this_alternative_win[m];
}
else
{
@ -3034,21 +3054,21 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx value;
/* Retroactively mark the operand we had to match
as a loser, if it wasn't already. */
if (this_alternative_win[c])
if (this_alternative_win[m])
losers++;
this_alternative_win[c] = 0;
if (this_alternative[c] == (int) NO_REGS)
this_alternative_win[m] = 0;
if (this_alternative[m] == (int) NO_REGS)
bad = 1;
/* But count the pair only once in the total badness of
this alternative, if the pair can be a dummy reload. */
value
= find_dummy_reload (recog_data.operand[i],
recog_data.operand[c],
recog_data.operand[m],
recog_data.operand_loc[i],
recog_data.operand_loc[c],
operand_mode[i], operand_mode[c],
this_alternative[c], -1,
this_alternative_earlyclobber[c]);
recog_data.operand_loc[m],
operand_mode[i], operand_mode[m],
this_alternative[m], -1,
this_alternative_earlyclobber[m]);
if (value != 0)
losers--;
@ -3056,7 +3076,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
/* This can be fixed with reloads if the operand
we are supposed to match can be fixed with reloads. */
badop = 0;
this_alternative[i] = this_alternative[c];
this_alternative[i] = this_alternative[m];
/* If we have to reload this operand and some previous
operand also had to match the same thing as this
@ -3175,7 +3195,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
case 'G':
case 'H':
if (GET_CODE (operand) == CONST_DOUBLE
&& CONST_DOUBLE_OK_FOR_LETTER_P (operand, c))
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
win = 1;
break;
@ -3209,7 +3229,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
case 'O':
case 'P':
if (GET_CODE (operand) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (operand), c))
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
win = 1;
break;
@ -3242,14 +3262,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
goto reg;
default:
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
{
#ifdef EXTRA_CONSTRAINT
if (EXTRA_MEMORY_CONSTRAINT (c))
#ifdef EXTRA_CONSTRAINT_STR
if (EXTRA_MEMORY_CONSTRAINT (c, p))
{
if (force_reload)
break;
if (EXTRA_CONSTRAINT (operand, c))
if (EXTRA_CONSTRAINT_STR (operand, c, p))
win = 1;
/* If the address was already reloaded,
we win as well. */
@ -3262,7 +3282,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
&& ((reg_equiv_mem[REGNO (operand)] != 0
&& EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
&& EXTRA_CONSTRAINT_STR (reg_equiv_mem[REGNO (operand)], c, p))
|| (reg_equiv_address[REGNO (operand)] != 0)))
win = 1;
@ -3276,9 +3296,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
offmemok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
{
if (EXTRA_CONSTRAINT (operand, c))
if (EXTRA_CONSTRAINT_STR (operand, c, p))
win = 1;
/* If we didn't already win, we can reload
@ -3292,14 +3312,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
break;
}
if (EXTRA_CONSTRAINT (operand, c))
if (EXTRA_CONSTRAINT_STR (operand, c, p))
win = 1;
#endif
break;
}
this_alternative[i]
= (int) reg_class_subunion[this_alternative[i]][(int) REG_CLASS_FROM_LETTER (c)];
= (int) (reg_class_subunion
[this_alternative[i]]
[(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
reg:
if (GET_MODE (operand) == BLKmode)
break;
@ -3310,6 +3332,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
win = 1;
break;
}
while ((p += len), c);
constraints[i] = p;
@ -4358,8 +4381,9 @@ alternative_allows_memconst (constraint, altnum)
}
/* Scan the requested alternative for 'm' or 'o'.
If one of them is present, this alternative accepts memory constants. */
while ((c = *constraint++) && c != ',' && c != '#')
if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
for (; (c = *constraint) && c != ',' && c != '#';
constraint += CONSTRAINT_LEN (c, constraint))
if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c, constraint))
return 1;
return 0;
}

View File

@ -1355,7 +1355,7 @@ maybe_fix_stack_asms ()
for (;;)
{
char c = *p++;
char c = *p;
if (c == '\0' || c == ',' || c == '#')
{
@ -1363,6 +1363,7 @@ maybe_fix_stack_asms ()
class, and reset the class. */
IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
cls = NO_REGS;
p++;
if (c == '#')
do {
c = *p++;
@ -1393,13 +1394,14 @@ maybe_fix_stack_asms ()
break;
default:
if (EXTRA_ADDRESS_CONSTRAINT (c))
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
cls = (int) reg_class_subunion[cls]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
else
cls = (int) reg_class_subunion[cls]
[(int) REG_CLASS_FROM_LETTER (c)];
[(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
}
p += CONSTRAINT_LEN (c, p);
}
}
/* Those of the registers which are clobbered, but allowed by the
@ -8418,7 +8420,7 @@ reload_cse_simplify_operands (insn, testreg)
p = constraints[i];
for (;;)
{
char c = *p++;
char c = *p;
switch (c)
{
@ -8442,7 +8444,9 @@ reload_cse_simplify_operands (insn, testreg)
default:
class
= reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
= (reg_class_subunion
[(int) class]
[(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
break;
case ',': case '\0':
@ -8462,6 +8466,7 @@ reload_cse_simplify_operands (insn, testreg)
j++;
break;
}
p += CONSTRAINT_LEN (c, p);
if (c == '\0')
break;

View File

@ -1197,7 +1197,7 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
}
/* Loop through the constraint string. */
for (p = constraint + 1; *p; ++p)
for (p = constraint + 1; *p; p += CONSTRAINT_LEN (*p, p))
switch (*p)
{
case '+':
@ -1249,12 +1249,12 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
default:
if (!ISALPHA (*p))
break;
if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
if (REG_CLASS_FROM_CONSTRAINT (*p, p) != NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_ADDRESS_CONSTRAINT (*p))
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_ADDRESS_CONSTRAINT (*p, p))
*allows_reg = true;
else if (EXTRA_MEMORY_CONSTRAINT (*p))
else if (EXTRA_MEMORY_CONSTRAINT (*p, p))
*allows_mem = true;
else
{
@ -1297,7 +1297,7 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
/* Make sure constraint has neither `=', `+', nor '&'. */
for (j = 0; j < c_len; j++)
for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j))
switch (constraint[j])
{
case '+': case '=': case '&':
@ -1356,10 +1356,16 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
*constraint_p = constraint;
c_len = strlen (constraint);
j = 0;
/* ??? At the end of the loop, we will skip the first part of
the matched constraint. This assumes not only that the
other constraint is an output constraint, but also that
the '=' or '+' come first. */
break;
}
else
j = end - constraint;
/* Anticipate increment at end of loop. */
j--;
}
/* Fall through. */
@ -1378,12 +1384,13 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
error ("invalid punctuation `%c' in constraint", constraint[j]);
return false;
}
if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
!= NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j], constraint + j))
*allows_reg = true;
else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
else if (EXTRA_MEMORY_CONSTRAINT (constraint[j], constraint + j))
*allows_mem = true;
else
{