summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2003-01-09 17:28:49 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2003-01-09 17:28:49 +0000
commit48ea55773270391b07804f5d6b4dfb28b7b3bd3f (patch)
tree71e3146782ec281fdcd5e689d1f1cbbe5f3c2286 /gcc
parentf35a3d21a719693dc824d933f7e8ce2d1245addf (diff)
downloadgcc-48ea55773270391b07804f5d6b4dfb28b7b3bd3f.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61119 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/config/s390/s390.h2
-rw-r--r--gcc/defaults.h29
-rw-r--r--gcc/doc/tm.texi60
-rw-r--r--gcc/genoutput.c87
-rw-r--r--gcc/local-alloc.c83
-rw-r--r--gcc/ra-build.c10
-rw-r--r--gcc/recog.c169
-rw-r--r--gcc/regclass.c261
-rw-r--r--gcc/regmove.c63
-rw-r--r--gcc/reload.c110
-rw-r--r--gcc/reload1.c15
-rw-r--r--gcc/stmt.c27
13 files changed, 609 insertions, 338 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d37abbee54..5a61481aa48 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 7ac78fa1bf6..fce6c48867d 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -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. */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 445aa5a5f5d..39f9d098381 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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 */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 71fac171629..fa4248c1c67 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 662a6b0465b..3a1ad817908 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -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
+}
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index 7f07be6c144..ff252a3c664 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -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;
+ 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;
- case ',':
- if (found_zero && ! reg_allowed)
- num_matching_alts++;
+ case ',':
+ if (found_zero && ! reg_allowed)
+ num_matching_alts++;
- found_zero = reg_allowed = 0;
- break;
+ found_zero = reg_allowed = 0;
+ break;
- case '0':
- found_zero = 1;
- 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;
+ 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_LETTER (c) == NO_REGS
- && !EXTRA_ADDRESS_CONSTRAINT (c))
+ 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;
- /* FALLTHRU */
- case 'p':
- case 'g': case 'r':
- reg_allowed = 1;
- break;
- }
+ }
+ }
if (found_zero && ! reg_allowed)
num_matching_alts++;
diff --git a/gcc/ra-build.c b/gcc/ra-build.c
index 5f0b3e1030b..2272fa59981 100644
--- a/gcc/ra-build.c
+++ b/gcc/ra-build.c
@@ -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
diff --git a/gcc/recog.c b/gcc/recog.c
index 340b2ee8b82..8d36e513e37 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -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++)
{
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 6b6a6dd0adb..334bc21b408 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -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;
+ while ((c = *p))
+ {
+ switch (c)
+ {
+ case ',':
+ break;
+ case '*':
+ /* Ignore the next letter for this pass. */
+ c = *++p;
+ 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 '?':
+ 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 '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 '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 '<':
- if (GET_CODE (op) == MEM
- && (GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == POST_DEC))
- win = 1;
- 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_INC
- || GET_CODE (XEXP (op, 0)) == POST_INC))
- 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 '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 '>':
+ if (GET_CODE (op) == MEM
+ && (GET_CODE (XEXP (op, 0)) == PRE_INC
+ || GET_CODE (XEXP (op, 0)) == POST_INC))
+ 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 '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 's':
- if (GET_CODE (op) == CONST_INT
- || (GET_CODE (op) == CONST_DOUBLE
- && GET_MODE (op) == VOIDmode))
+ case 'G':
+ case 'H':
+ if (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
+ win = 1;
break;
- case 'i':
- if (CONSTANT_P (op)
+
+ 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))
+ && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
#endif
- )
- win = 1;
- break;
+ )
+ win = 1;
+ break;
- case 'n':
- if (GET_CODE (op) == CONST_INT
- || (GET_CODE (op) == CONST_DOUBLE
- && GET_MODE (op) == VOIDmode))
- 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_LETTER_P (INTVAL (op), c))
- 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 'X':
+ win = 1;
+ break;
- case 'g':
- if (GET_CODE (op) == MEM
- || (CONSTANT_P (op)
+ case 'g':
+ if (GET_CODE (op) == MEM
+ || (CONSTANT_P (op)
#ifdef LEGITIMATE_PIC_OPERAND_P
- && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
+ && (! 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)
+ ))
+ win = 1;
+ allows_mem[i] = 1;
+ case 'r':
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;
+ = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
+ 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. */
+ 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;
diff --git a/gcc/regmove.c b/gcc/regmove.c
index 653d1587c84..eb5141f8bea 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -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;
}
diff --git a/gcc/reload.c b/gcc/reload.c
index e61c3b12f8e..11fe356710a 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -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;
}
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 40204074af7..4fd401c89bb 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index ac0aa15bef2..960bea0f24e 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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
{