diff options
author | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-09 17:28:49 +0000 |
---|---|---|
committer | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-01-09 17:28:49 +0000 |
commit | 48ea55773270391b07804f5d6b4dfb28b7b3bd3f (patch) | |
tree | 71e3146782ec281fdcd5e689d1f1cbbe5f3c2286 | |
parent | f35a3d21a719693dc824d933f7e8ce2d1245addf (diff) | |
download | gcc-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
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 2 | ||||
-rw-r--r-- | gcc/defaults.h | 29 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 60 | ||||
-rw-r--r-- | gcc/genoutput.c | 87 | ||||
-rw-r--r-- | gcc/local-alloc.c | 83 | ||||
-rw-r--r-- | gcc/ra-build.c | 10 | ||||
-rw-r--r-- | gcc/recog.c | 169 | ||||
-rw-r--r-- | gcc/regclass.c | 261 | ||||
-rw-r--r-- | gcc/regmove.c | 63 | ||||
-rw-r--r-- | gcc/reload.c | 110 | ||||
-rw-r--r-- | gcc/reload1.c | 15 | ||||
-rw-r--r-- | gcc/stmt.c | 27 |
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 { |