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

From-SVN: r61119

13 files changed:
gcc/ChangeLog
gcc/config/s390/s390.h
gcc/defaults.h
gcc/doc/tm.texi
gcc/genoutput.c
gcc/local-alloc.c
gcc/ra-build.c
gcc/recog.c
gcc/regclass.c
gcc/regmove.c
gcc/reload.c
gcc/reload1.c
gcc/stmt.c

index 0d37abbee54fca0caaaffbd091c8fa3920100a14..5a61481aa480fd6d19c0b28627ddde8e646da666 100644 (file)
@@ -1,4 +1,33 @@
-Thu Jan  9 17:23:19 2003  J"orn Rennecke <joern.rennecke@superh.com>
+Thu Jan  9 17:26:40 2003  J"orn Rennecke <joern.rennecke@superh.com>
+
+       * defaults.h (EXTRA_MEMORY_CONSTRAINT): Add STR argument.
+       (EXTRA_ADDRESS_CONSTRAINT): Likewise.
+       (CONSTRAINT_LEN): Provide default definition.
+       (CONST_OK_FOR_CONSTRAINT_P): Likewise.
+       (CONST_DOUBLE_OK_FOR_CONSTRAINT_P): Likewise.
+       (EXTRA_CONSTRAINT_STR): Likewise.
+       (REG_CLASS_FROM_CONSTRAINT): Define.
+       * genoutput.c (check_constraint_len, constraint_len): New functions.
+       (validate_insn_alternatives): Check CONSTRAINT_LEN for each
+       constraint / modifier.
+       (gen_insn): Call check_constraint_len.
+       * local-alloc.c (block_alloc): Update to use new macros / pass
+       second argument to EXTRA_{MEMORY,ADDRESS}_CONSTRAINT.
+       * ra-build.c (handle_asm_insn): Likewise.
+       * recog.c (asm_operand_ok, preprocess_constraints): Likewise.
+       (constrain_operands, peep2_find_free_register): Likewise.
+       * regclass.c (record_operand_costs, record_reg_classes): Likewise.
+       * regmove.c (find_matches): Likewise.
+       * reload.c (push_secondary_reload, find_reloads): Likewise.
+       (alternative_allows_memconst): Likewise.
+       * reload1.c (maybe_fix_stack_asms): Likewise.
+       (reload_cse_simplify_operands): Likewise.
+       * stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
+       * doc/tm.texi (CONSTRAINT_LEN, REG_CLASS_FROM_CONSTRAINT): Document.
+       (CONST_OK_FOR_CONSTRAINT_P): Likewise.
+       (CONST_DOUBLE_OK_FOR_CONSTRAINT_P, EXTRA_CONSTRAINT_STR): Likewise.
+       (EXTRA_MEMORY_CONSTRAINT, EXTRA_ADDRESS_CONSTRAINT): Add STR argument.
+       * config/s390/s390.h (EXTRA_MEMORY_CONSTRAINT): Likewise.
 
        * sh.h (OVERRIDE_OPTIONS): Allow first scheduling pass for SH5.
 
index 7ac78fa1bf6b6256b380fbd52a43d3b5c18f4e53..fce6c48867d5392e3cb587852d372d7ef69055ce 100644 (file)
@@ -473,7 +473,7 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
      ((C) == 'Q' ?  q_constraint (OP) :                        \
       (C) == 'S' ?  larl_operand (OP, GET_MODE (OP)) : 0)
 
-#define EXTRA_MEMORY_CONSTRAINT(C) ((C) == 'Q')
+#define EXTRA_MEMORY_CONSTRAINT(C,STR) ((C) == 'Q')
 
 
 /* Stack layout and calling conventions.  */
index 445aa5a5f5da6c5ffedf3704b23c9e5259806519..39f9d09838116b4519df33fec3abb88e09338a6e 100644 (file)
@@ -604,13 +604,38 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
 /* Determine whether extra constraint letter should be handled
    via address reload (like 'o').  */
 #ifndef EXTRA_MEMORY_CONSTRAINT
-#define EXTRA_MEMORY_CONSTRAINT(C) 0
+#define EXTRA_MEMORY_CONSTRAINT(C,STR) 0
 #endif
 
 /* Determine whether extra constraint letter should be handled
    as an address (like 'p').  */
 #ifndef EXTRA_ADDRESS_CONSTRAINT
-#define EXTRA_ADDRESS_CONSTRAINT(C) 0
+#define EXTRA_ADDRESS_CONSTRAINT(C,STR) 0
+#endif
+
+/* When a port defines CONSTRAINT_LEN, it should use DEFAULT_CONSTRAINT_LEN
+   for all the characters that it does not want to change, so things like the
+  'length' of a digit in a matching constraint is an implementation detail,
+   and not part of the interface.  */
+#define DEFAULT_CONSTRAINT_LEN(C,STR) 1
+
+#ifndef CONSTRAINT_LEN
+#define CONSTRAINT_LEN(C,STR) DEFAULT_CONSTRAINT_LEN (C, STR)
+#endif
+
+#if defined (CONST_OK_FOR_LETTER_P) && ! defined (CONST_OK_FOR_CONSTRAINT_P)
+#define CONST_OK_FOR_CONSTRAINT_P(VAL,C,STR) CONST_OK_FOR_LETTER_P (VAL, C)
+#endif
+
+#if defined (CONST_DOUBLE_OK_FOR_LETTER_P) && ! defined (CONST_DOUBLE_OK_FOR_CONSTRAINT_P)
+#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(OP,C,STR) \
+  CONST_DOUBLE_OK_FOR_LETTER_P (OP, C)
+#endif
+
+#define REG_CLASS_FROM_CONSTRAINT(C,STR) REG_CLASS_FROM_LETTER (C)
+
+#if defined (EXTRA_CONSTRAINT) && ! defined (EXTRA_CONSTRAINT_STR)
+#define EXTRA_CONSTRAINT_STR(OP, C,STR) EXTRA_CONSTRAINT (OP, C)
 #endif
 
 #endif  /* ! GCC_DEFAULTS_H */
index 71fac171629006c425537073f00e7eddfcd5b875..fa4248c1c67c7772df72e22526e59df62867191d 100644 (file)
@@ -1910,7 +1910,8 @@ If the usage of an entire class of registers depends on the target
 flags, you may indicate this to GCC by using this macro to modify
 @code{fixed_regs} and @code{call_used_regs} to 1 for each of the
 registers in the classes which should not be used by GCC@.  Also define
-the macro @code{REG_CLASS_FROM_LETTER} to return @code{NO_REGS} if it
+the macro @code{REG_CLASS_FROM_LETTER} / @code{REG_CLASS_FROM_CONSTRAINT}
+to return @code{NO_REGS} if it
 is called with a letter for a class that shouldn't be used.
 
 (However, if this class is not included in @code{GENERAL_REGS} and all
@@ -2330,6 +2331,21 @@ index register must belong.  An index register is one used in an
 address where its value is either multiplied by a scale factor or
 added to another register (as well as added to a displacement).
 
+@findex CONSTRAINT_LEN
+@item CONSTRAINT_LEN (@var{char}, @var{str})
+For the constraint at the start of @var{str}, which starts with the letter
+@var{c}, return the length.  This allows you to have register class /
+constant / extra constraints that are longer than a single letter;
+you don't need to define this macro if you can do with single-letter
+constraints only.  The definition of this macro should use
+DEFAULT_CONSTRAINT_LEN for all the characters that you don't want
+to handle specially.
+There are some sanity checks in genoutput.c that check the constraint lengths
+for the md file, so you can also use this macro to help you while you are
+transitioning from a byzantine single-letter-constraint scheme: when you
+return a negative length for a constraint you want to re-use, genoutput
+will complain about every instance where it is used in the md file.
+
 @findex REG_CLASS_FROM_LETTER
 @item REG_CLASS_FROM_LETTER (@var{char})
 A C expression which defines the machine-dependent operand constraint
@@ -2339,6 +2355,12 @@ the value should be @code{NO_REGS}.  The register letter @samp{r},
 corresponding to class @code{GENERAL_REGS}, will not be passed
 to this macro; you do not need to handle it.
 
+@findex REG_CLASS_FROM_CONSTRAINT
+@item REG_CLASS_FROM_CONSTRAINT (@var{char}, @var{str})
+Like @code{REG_CLASS_FROM_LETTER}, but you also get the constraint string
+passed in @var{str}, so that you can use suffixes to distinguish between
+different variants.
+
 @findex REGNO_OK_FOR_BASE_P
 @item REGNO_OK_FOR_BASE_P (@var{num})
 A C expression which is nonzero if register number @var{num} is
@@ -2608,6 +2630,12 @@ the appropriate range and return 1 if so, 0 otherwise.  If @var{c} is
 not one of those letters, the value should be 0 regardless of
 @var{value}.
 
+@findex CONST_OK_FOR_CONSTRAINT_P
+@item CONST_OK_FOR_CONSTRAINT_P (@var{value}, @var{c}, @var{str})
+Like @code{CONST_OK_FOR_LETTER_P}, but you also get the constraint
+string passed in @var{str}, so that you can use suffixes to distinguish
+between different variants.
+
 @findex CONST_DOUBLE_OK_FOR_LETTER_P
 @item CONST_DOUBLE_OK_FOR_LETTER_P (@var{value}, @var{c})
 A C expression that defines the machine-dependent operand constraint
@@ -2624,12 +2652,19 @@ letters, the value should be 0 regardless of @var{value}.
 or both kinds of values.  It can use @code{GET_MODE} to distinguish
 between these kinds.
 
+@findex CONST_DOUBLE_OK_FOR_CONSTRAINT_P
+@item CONST_DOUBLE_OK_FOR_CONSTRAINT_P (@var{value}, @var{c}, @var{str})
+Like @code{CONST_DOUBLE_OK_FOR_LETTER_P}, but you also get the constraint
+string passed in @var{str}, so that you can use suffixes to distinguish
+between different variants.
+
 @findex EXTRA_CONSTRAINT
 @item EXTRA_CONSTRAINT (@var{value}, @var{c})
 A C expression that defines the optional machine-dependent constraint
 letters that can be used to segregate specific types of operands, usually
 memory references, for the target machine.  Any letter that is not
-elsewhere defined and not matched by @code{REG_CLASS_FROM_LETTER}
+elsewhere defined and not matched by @code{REG_CLASS_FROM_LETTER} /
+@code{REG_CLASS_FROM_CONSTRAINT}
 may be used.  Normally this macro will not be defined.
 
 If it is required for a particular target machine, it should return 1
@@ -2645,14 +2680,21 @@ a @samp{Q} constraint on the input and @samp{r} on the output.  The next
 alternative specifies @samp{m} on the input and a register class that
 does not include r0 on the output.
 
+@findex EXTRA_CONSTRAINT_STR
+@item EXTRA_CONSTRAINT_STR (@var{value}, @var{c}, @var{str})
+Like @code{EXTRA_CONSTRAINT}, but you also get the constraint string passed
+in @var{str}, so that you can use suffixes to distinguish between different
+variants.
+
 @findex EXTRA_MEMORY_CONSTRAINT
-@item EXTRA_MEMORY_CONSTRAINT (@var{c})
+@item EXTRA_MEMORY_CONSTRAINT (@var{c}, @var{str})
 A C expression that defines the optional machine-dependent constraint
 letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
 be treated like memory constraints by the reload pass.
 
 It should return 1 if the operand type represented by the constraint 
-letter @var{c} comprises a subset of all memory references including
+at the start of @var{str}, the first letter of which is the letter @var{c},
+ comprises a subset of all memory references including
 all those whose address is simply a base register.  This allows the reload 
 pass to reload an operand, if it does not directly correspond to the operand 
 type of @var{c}, by copying its address into a base register.
@@ -2668,16 +2710,18 @@ into a base register if required.  This is analogous to the way
 a @samp{o} constraint can handle any memory operand.
 
 @findex EXTRA_ADDRESS_CONSTRAINT
-@item EXTRA_ADDRESS_CONSTRAINT (@var{c})
+@item EXTRA_ADDRESS_CONSTRAINT (@var{c}, @var{str})
 A C expression that defines the optional machine-dependent constraint
-letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+letters, amongst those accepted by @code{EXTRA_CONSTRAINT} /
+@code{EXTRA_CONSTRAINT_STR}, that should
 be treated like address constraints by the reload pass.
 
 It should return 1 if the operand type represented by the constraint 
-letter @var{c} comprises a subset of all memory addresses including
+at the startr of @{str}, which starts with the letter @var{c}, comprises
+a subset of all memory addresses including
 all those that consist of just a base register.  This allows the reload 
 pass to reload an operand, if it does not directly correspond to the operand 
-type of @var{c}, by copying it into a base register.
+type of @var{str}, by copying it into a base register.
 
 Any constraint marked as @code{EXTRA_ADDRESS_CONSTRAINT} can only
 be used with the @code{address_operand} predicate.  It is treated 
index 662a6b0465beee60d66e4e7e2776efcaf6b571b4..3a1ad817908b3b502c68924ee242dcc9dbf322b3 100644 (file)
@@ -189,6 +189,8 @@ static void gen_insn PARAMS ((rtx, int));
 static void gen_peephole PARAMS ((rtx, int));
 static void gen_expand PARAMS ((rtx, int));
 static void gen_split PARAMS ((rtx, int));
+static void check_constraint_len PARAMS ((void));
+static int constraint_len PARAMS ((const char *, int));
 \f
 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
+}
index 7f07be6c1446735a16ddd2f5672041d92da3bc7d..ff252a3c66497d39d0c92d4b2cd69292d7d3b72b 100644 (file)
@@ -1338,7 +1338,8 @@ block_alloc (b)
                     There may be more than one register, but we only try one
                     of them.  */
                  if (recog_data.constraints[i][0] == 'p'
-                     || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
+                     || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0],
+                                                  recog_data.constraints[i]))
                    while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
                      r1 = XEXP (r1, 0);
 
@@ -2424,50 +2425,56 @@ requires_inout (p)
   int found_zero = 0;
   int reg_allowed = 0;
   int num_matching_alts = 0;
+  int len;
 
-  while ((c = *p++))
-    switch (c)
-      {
-      case '=':  case '+':  case '?':
-      case '#':  case '&':  case '!':
-      case '*':  case '%':
-      case 'm':  case '<':  case '>':  case 'V':  case 'o':
-      case 'E':  case 'F':  case 'G':  case 'H':
-      case 's':  case 'i':  case 'n':
-      case 'I':  case 'J':  case 'K':  case 'L':
-      case 'M':  case 'N':  case 'O':  case 'P':
-      case 'X':
-       /* These don't say anything we care about.  */
-       break;
+  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++;
index 5f0b3e1030bc29f7165c811a6ed03b526634064d..2272fa5998110ea2ed8d3c9600834b61d0cbae77 100644 (file)
@@ -2933,13 +2933,13 @@ handle_asm_insn (df, insn)
       CLEAR_HARD_REG_SET (allowed);
       while (1)
        {
-         char c = *p++;
+         char c = *p;
 
          if (c == '\0' || c == ',' || c == '#')
            {
              /* End of one alternative - mark the regs in the current
-              class, and reset the class.
-              */
+              class, and reset the class.  */
+             p++;
              IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
              if (cls != NO_REGS)
                nothing_allowed = 0;
@@ -2977,8 +2977,10 @@ handle_asm_insn (df, insn)
              default:
                cls =
                  (int) reg_class_subunion[cls][(int)
-                                               REG_CLASS_FROM_LETTER (c)];
+                                               REG_CLASS_FROM_CONSTRAINT (c,
+                                                                          p)];
            }
+         p += CONSTRAINT_LEN (c, p);
        }
 
       /* Now make conflicts between this web, and all hardregs, which
index 340b2ee8b8260529a5fb15e6fd7e218ae52b8ce6..8d36e513e37deaf280ff26e1f68d6598f059f027 100644 (file)
@@ -1681,18 +1681,21 @@ asm_operand_ok (op, constraint)
 
   while (*constraint)
     {
-      char c = *constraint++;
+      char c = *constraint;
+      int len;
       switch (c)
        {
+       case ',':
+         constraint++;
+         continue;
        case '=':
        case '+':
        case '*':
        case '%':
-       case '?':
        case '!':
        case '#':
        case '&':
-       case ',':
+       case '?':
          break;
 
        case '0': case '1': case '2': case '3': case '4':
@@ -1701,25 +1704,27 @@ asm_operand_ok (op, constraint)
             proper matching constraint, but we can't actually fail
             the check if they didn't.  Indicate that results are
             inconclusive.  */
-         while (ISDIGIT (*constraint))
+         do
            constraint++;
-         result = -1;
-         break;
+         while (ISDIGIT (*constraint));
+         if (! result)
+           result = -1;
+         continue;
 
        case 'p':
          if (address_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'm':
        case 'V': /* non-offsettable */
          if (memory_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'o': /* offsettable */
          if (offsettable_nonstrict_memref_p (op))
-           return 1;
+           result = 1;
          break;
 
        case '<':
@@ -1734,7 +1739,7 @@ asm_operand_ok (op, constraint)
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_DEC
                  || GET_CODE (XEXP (op, 0)) == POST_DEC))
-           return 1;
+           result = 1;
          break;
 
        case '>':
@@ -1742,7 +1747,7 @@ asm_operand_ok (op, constraint)
              && (1
                  || GET_CODE (XEXP (op, 0)) == PRE_INC
                  || GET_CODE (XEXP (op, 0)) == POST_INC))
-           return 1;
+           result = 1;
          break;
 
        case 'E':
@@ -1750,18 +1755,18 @@ asm_operand_ok (op, constraint)
          if (GET_CODE (op) == CONST_DOUBLE
              || (GET_CODE (op) == CONST_VECTOR
                  && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
-           return 1;
+           result = 1;
          break;
 
        case 'G':
          if (GET_CODE (op) == CONST_DOUBLE
-             && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
-           return 1;
+             && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint))
+           result = 1;
          break;
        case 'H':
          if (GET_CODE (op) == CONST_DOUBLE
-             && CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
-           return 1;
+             && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint))
+           result = 1;
          break;
 
        case 's':
@@ -1777,94 +1782,100 @@ asm_operand_ok (op, constraint)
              && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
 #endif
              )
-           return 1;
+           result = 1;
          break;
 
        case 'n':
          if (GET_CODE (op) == CONST_INT
              || (GET_CODE (op) == CONST_DOUBLE
                  && GET_MODE (op) == VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        case 'I':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint))
+           result = 1;
          break;
        case 'J':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint))
+           result = 1;
          break;
        case 'K':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint))
+           result = 1;
          break;
        case 'L':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint))
+           result = 1;
          break;
        case 'M':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint))
+           result = 1;
          break;
        case 'N':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint))
+           result = 1;
          break;
        case 'O':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint))
+           result = 1;
          break;
        case 'P':
          if (GET_CODE (op) == CONST_INT
-             && CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
-           return 1;
+             && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint))
+           result = 1;
          break;
 
        case 'X':
-         return 1;
+         result = 1;
 
        case 'g':
          if (general_operand (op, VOIDmode))
-           return 1;
+           result = 1;
          break;
 
        default:
          /* For all other letters, we first check for a register class,
             otherwise it is an EXTRA_CONSTRAINT.  */
-         if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+         if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS)
            {
            case 'r':
              if (GET_MODE (op) == BLKmode)
                break;
              if (register_operand (op, VOIDmode))
-               return 1;
+               result = 1;
            }
-#ifdef EXTRA_CONSTRAINT
-         if (EXTRA_CONSTRAINT (op, c))
-           return 1;
-         if (EXTRA_MEMORY_CONSTRAINT (c))
+#ifdef EXTRA_CONSTRAINT_STR
+         if (EXTRA_CONSTRAINT_STR (op, c, constraint))
+           result = 1;
+         if (EXTRA_MEMORY_CONSTRAINT (c, constraint))
            {
              /* Every memory operand can be reloaded to fit.  */
              if (memory_operand (op, VOIDmode))
-               return 1;
+               result = 1;
            }
-         if (EXTRA_ADDRESS_CONSTRAINT (c))
+         if (EXTRA_ADDRESS_CONSTRAINT (c, constraint))
            {
              /* Every address operand can be reloaded to fit.  */
              if (address_operand (op, VOIDmode))
-               return 1;
+               result = 1;
            }
 #endif
          break;
        }
+      len = CONSTRAINT_LEN (c, constraint);
+      do
+       constraint++;
+      while (--len && *constraint);
+      if (len)
+       return 0;
     }
 
   return result;
@@ -2233,13 +2244,16 @@ preprocess_constraints ()
 
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
              if (c == '#')
                do
-                 c = *p++;
+                 c = *++p;
                while (c != ',' && c != '\0');
              if (c == ',' || c == '\0')
-               break;
+               {
+                 p++;
+                 break;
+               }
 
              switch (c)
                {
@@ -2265,11 +2279,11 @@ preprocess_constraints ()
                case '5': case '6': case '7': case '8': case '9':
                  {
                    char *end;
-                   op_alt[j].matches = strtoul (p - 1, &end, 10);
+                   op_alt[j].matches = strtoul (p, &end, 10);
                    recog_op_alt[op_alt[j].matches][j].matched = i;
                    p = end;
                  }
-                 break;
+                 continue;
 
                case 'm':
                  op_alt[j].memory_ok = 1;
@@ -2301,22 +2315,28 @@ preprocess_constraints ()
                  break;
 
                default:
-                 if (EXTRA_MEMORY_CONSTRAINT (c))
+                 if (EXTRA_MEMORY_CONSTRAINT (c, p))
                    {
                      op_alt[j].memory_ok = 1;
                      break;
                    }
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    {
                      op_alt[j].is_address = 1;
-                     op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
-                       [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                     op_alt[j].class
+                       = (reg_class_subunion
+                          [(int) op_alt[j].class]
+                          [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
                      break;
                    }
 
-                 op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
+                 op_alt[j].class
+                   = (reg_class_subunion
+                      [(int) op_alt[j].class]
+                      [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
                  break;
                }
+             p += CONSTRAINT_LEN (c, p);
            }
        }
     }
@@ -2331,7 +2351,7 @@ preprocess_constraints ()
    alternative of constraints was matched: 0 for the first alternative,
    1 for the next, etc.
 
-   In addition, when two operands are match
+   In addition, when two operands are required to match
    and it happens that the output operand is (reg) while the
    input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
    make the output operand look like the input.
@@ -2390,6 +2410,7 @@ constrain_operands (strict)
          int offset = 0;
          int win = 0;
          int val;
+         int len;
 
          earlyclobber[opno] = 0;
 
@@ -2414,9 +2435,16 @@ constrain_operands (strict)
          if (*p == 0 || *p == ',')
            win = 1;
 
-         while (*p && (c = *p++) != ',')
-           switch (c)
+         do
+           switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
              {
+             case '\0':
+               len = 0;
+               break;
+             case ',':
+               c = '\0';
+               break;
+
              case '?':  case '!': case '*':  case '%':
              case '=':  case '+':
                break;
@@ -2424,8 +2452,10 @@ constrain_operands (strict)
              case '#':
                /* Ignore rest of this alternative as far as
                   constraint checking is concerned.  */
-               while (*p && *p != ',')
+               do
                  p++;
+               while (*p && *p != ',');
+               len = 0;
                break;
 
              case '&':
@@ -2447,7 +2477,7 @@ constrain_operands (strict)
                  char *end;
                  int match;
 
-                 match = strtoul (p - 1, &end, 10);
+                 match = strtoul (p, &end, 10);
                  p = end;
 
                  if (strict < 0)
@@ -2482,6 +2512,7 @@ constrain_operands (strict)
                      funny_match[funny_match_index++].other = match;
                    }
                }
+               len = 0;
                break;
 
              case 'p':
@@ -2551,7 +2582,7 @@ constrain_operands (strict)
              case 'G':
              case 'H':
                if (GET_CODE (op) == CONST_DOUBLE
-                   && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
+                   && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
                  win = 1;
                break;
 
@@ -2581,7 +2612,7 @@ constrain_operands (strict)
              case 'O':
              case 'P':
                if (GET_CODE (op) == CONST_INT
-                   && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
+                   && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
                  win = 1;
                break;
 
@@ -2612,7 +2643,8 @@ constrain_operands (strict)
                {
                  enum reg_class class;
 
-                 class = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (c));
+                 class = (c == 'r'
+                          ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
                  if (class != NO_REGS)
                    {
                      if (strict < 0
@@ -2624,11 +2656,11 @@ constrain_operands (strict)
                              && reg_fits_class_p (op, class, offset, mode)))
                        win = 1;
                    }
-#ifdef EXTRA_CONSTRAINT
-                 else if (EXTRA_CONSTRAINT (op, c))
+#ifdef EXTRA_CONSTRAINT_STR
+                 else if (EXTRA_CONSTRAINT_STR (op, c, p))
                    win = 1;
 
-                 if (EXTRA_MEMORY_CONSTRAINT (c))
+                 if (EXTRA_MEMORY_CONSTRAINT (c, p))
                    {
                      /* Every memory operand can be reloaded to fit.  */
                      if (strict < 0 && GET_CODE (op) == MEM)
@@ -2643,7 +2675,7 @@ constrain_operands (strict)
                          && REGNO (op) >= FIRST_PSEUDO_REGISTER)
                        win = 1;
                    }
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    {
                      /* Every address operand can be reloaded to fit.  */
                      if (strict < 0)
@@ -2653,6 +2685,7 @@ constrain_operands (strict)
                  break;
                }
              }
+         while (p += len, c);
 
          constraints[opno] = p;
          /* If this operand did not win somehow,
@@ -3009,7 +3042,7 @@ peep2_find_free_register (from, to, class_str, mode, reg_set)
     }
 
   class = (class_str[0] == 'r' ? GENERAL_REGS
-          : REG_CLASS_FROM_LETTER (class_str[0]));
+          : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str));
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
index 6b6a6dd0adbb0c9bb402adfd6fdd2ec4aead9df1..334bc21b408026cb80a80ad9403b7585a87b54eb 100644 (file)
@@ -977,7 +977,7 @@ record_operand_costs (insn, op_costs, reg_pref)
        record_address_regs (XEXP (recog_data.operand[i], 0),
                             MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
       else if (constraints[i][0] == 'p'
-              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
+              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
        record_address_regs (recog_data.operand[i],
                             MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
     }
@@ -1548,154 +1548,161 @@ record_reg_classes (n_alts, n_ops, ops, modes,
             any of the constraints.  Collect the valid register classes
             and see if this operand accepts memory.  */
 
-         while (*p && (c = *p++) != ',')
-           switch (c)
-             {
-             case '*':
-               /* Ignore the next letter for this pass.  */
-               p++;
-               break;
-
-             case '?':
-               alt_cost += 2;
-             case '!':  case '#':  case '&':
-             case '0':  case '1':  case '2':  case '3':  case '4':
-             case '5':  case '6':  case '7':  case '8':  case '9':
-               break;
+         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;
 
index 653d1587c84bed913daea3b506985564ebdaccb4..eb5141f8bea4b7a031d7bfc3bbd64c20fddd50eb 100644 (file)
@@ -1570,47 +1570,50 @@ find_matches (insn, matchp)
        if (*p == ',')
          i++;
 
-      while ((c = *p++) != '\0' && c != ',')
-       switch (c)
-         {
-         case '=':
-           break;
-         case '+':
-           break;
-         case '&':
-           matchp->early_clobber[op_no] = 1;
-           break;
-         case '%':
-           matchp->commutative[op_no] = op_no + 1;
-           matchp->commutative[op_no + 1] = op_no;
-           break;
-
-         case '0': case '1': case '2': case '3': case '4':
-         case '5': case '6': case '7': case '8': case '9':
+      while ((c = *p) != '\0' && c != ',')
+       {
+         switch (c)
            {
-             char *end;
-             unsigned long match_ul = strtoul (p - 1, &end, 10);
-             int match = match_ul;
+           case '=':
+             break;
+           case '+':
+             break;
+           case '&':
+             matchp->early_clobber[op_no] = 1;
+             break;
+           case '%':
+             matchp->commutative[op_no] = op_no + 1;
+             matchp->commutative[op_no + 1] = op_no;
+             break;
 
-             p = end;
+           case '0': case '1': case '2': case '3': case '4':
+           case '5': case '6': case '7': case '8': case '9':
+             {
+               char *end;
+               unsigned long match_ul = strtoul (p, &end, 10);
+               int match = match_ul;
 
-             if (match < op_no && likely_spilled[match])
-               break;
-             matchp->with[op_no] = match;
-             any_matches = 1;
-             if (matchp->commutative[op_no] >= 0)
-               matchp->with[matchp->commutative[op_no]] = match;
-           }
-           break;
+               p = end;
+
+               if (match < op_no && likely_spilled[match])
+                 continue;
+               matchp->with[op_no] = match;
+               any_matches = 1;
+               if (matchp->commutative[op_no] >= 0)
+                 matchp->with[matchp->commutative[op_no]] = match;
+             }
+           continue;
 
          case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h':
          case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u':
          case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
          case 'C': case 'D': case 'W': case 'Y': case 'Z':
-           if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_LETTER ((unsigned char) c)))
+           if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p) ))
              likely_spilled[op_no] = 1;
            break;
          }
+         p += CONSTRAINT_LEN (c, p);
+       }
     }
   return any_matches;
 }
index e61c3b12f8ef999f05a0eab2df4fd18ce9747bcc..11fe356710aca93e1fa14c10b1542a6b8f9c465f 100644 (file)
@@ -381,11 +381,13 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
        insn_class = ALL_REGS;
       else
        {
-         char insn_letter
-           = insn_data[(int) icode].operand[!in_p].constraint[in_p];
+         const char *insn_constraint
+           = &insn_data[(int) icode].operand[!in_p].constraint[in_p];
+         char insn_letter = *insn_constraint;
          insn_class
            = (insn_letter == 'r' ? GENERAL_REGS
-              : REG_CLASS_FROM_LETTER ((unsigned char) insn_letter));
+              : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+                                           insn_constraint));
 
           if (insn_class == NO_REGS)
            abort ();
@@ -403,11 +405,14 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
        mode = insn_data[(int) icode].operand[2].mode;
       else
        {
-         char t_letter = insn_data[(int) icode].operand[2].constraint[2];
+         const char *t_constraint
+           = &insn_data[(int) icode].operand[2].constraint[2];
+         char t_letter = *t_constraint;
          class = insn_class;
          t_mode = insn_data[(int) icode].operand[2].mode;
          t_class = (t_letter == 'r' ? GENERAL_REGS
-                    : REG_CLASS_FROM_LETTER ((unsigned char) t_letter));
+                    : REG_CLASS_FROM_CONSTRAINT ((unsigned char) t_letter,
+                                                 t_constraint));
          t_icode = icode;
          icode = CODE_FOR_nothing;
        }
@@ -2587,8 +2592,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       /* Scan this operand's constraint to see if it is an output operand,
         an in-out operand, is commutative, or should match another.  */
 
-      while ((c = *p++))
+      while ((c = *p))
        {
+         p += CONSTRAINT_LEN (c, p);
          if (c == '=')
            modified[i] = RELOAD_WRITE;
          else if (c == '+')
@@ -2664,7 +2670,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        /* Ignore things like match_operator operands.  */
        ;
       else if (constraints[i][0] == 'p'
-              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
+              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
        {
          find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
                                recog_data.operand[i],
@@ -2829,6 +2835,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       for (i = 0; i < noperands; i++)
        {
          char *p = constraints[i];
+         char *end;
+         int len;
          int win = 0;
          int did_match = 0;
          /* 0 => this operand can be reloaded somehow for this alternative.  */
@@ -2836,6 +2844,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          /* 0 => this operand can be reloaded if the alternative allows regs.  */
          int winreg = 0;
          int c;
+         int m;
          rtx operand = recog_data.operand[i];
          int offset = 0;
          /* Nonzero means this is a MEM that must be reloaded into a reg
@@ -2964,9 +2973,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
             or set WINREG if this operand could fit after reloads
             provided the constraint allows some registers.  */
 
-         while (*p && (c = *p++) != ',')
-           switch (c)
+         do
+           switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c)
              {
+             case '\0':
+               len = 0;
+               break;
+             case ',':
+               c = '\0';
+               break;
+
              case '=':  case '+':  case '*':
                break;
 
@@ -2987,15 +3003,19 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case '#':
                /* Ignore rest of this alternative as far as
                   reloading is concerned.  */
-               while (*p && *p != ',')
+               do
                  p++;
+               while (*p && *p != ',');
+               len = 0;
                break;
 
              case '0':  case '1':  case '2':  case '3':  case '4':
              case '5':  case '6':  case '7':  case '8':  case '9':
-               c = strtoul (p - 1, &p, 10);
+               m = strtoul (p, &end, 10);
+               p = end;
+               len = 0;
 
-               this_alternative_matches[i] = c;
+               this_alternative_matches[i] = m;
                /* We are supposed to match a previous operand.
                   If we do, we win if that one did.
                   If we do not, count both of the operands as losers.
@@ -3003,7 +3023,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                   only a single reload insn will be needed to make
                   the two operands win.  As a result, this alternative
                   may be rejected when it is actually desirable.)  */
-               if ((swapped && (c != commutative || i != commutative + 1))
+               if ((swapped && (m != commutative || i != commutative + 1))
                    /* If we are matching as if two operands were swapped,
                       also pretend that operands_match had been computed
                       with swapped.
@@ -3011,22 +3031,22 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                       don't exchange them, because operands_match is valid
                       only on one side of its diagonal.  */
                    ? (operands_match
-                      [(c == commutative || c == commutative + 1)
-                      ? 2 * commutative + 1 - c : c]
+                      [(m == commutative || m == commutative + 1)
+                      ? 2 * commutative + 1 - m : m]
                       [(i == commutative || i == commutative + 1)
                       ? 2 * commutative + 1 - i : i])
-                   : operands_match[c][i])
+                   : operands_match[m][i])
                  {
                    /* If we are matching a non-offsettable address where an
                       offsettable address was expected, then we must reject
                       this combination, because we can't reload it.  */
-                   if (this_alternative_offmemok[c]
-                       && GET_CODE (recog_data.operand[c]) == MEM
-                       && this_alternative[c] == (int) NO_REGS
-                       && ! this_alternative_win[c])
+                   if (this_alternative_offmemok[m]
+                       && GET_CODE (recog_data.operand[m]) == MEM
+                       && this_alternative[m] == (int) NO_REGS
+                       && ! this_alternative_win[m])
                      bad = 1;
 
-                   did_match = this_alternative_win[c];
+                   did_match = this_alternative_win[m];
                  }
                else
                  {
@@ -3034,21 +3054,21 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                    rtx value;
                    /* Retroactively mark the operand we had to match
                       as a loser, if it wasn't already.  */
-                   if (this_alternative_win[c])
+                   if (this_alternative_win[m])
                      losers++;
-                   this_alternative_win[c] = 0;
-                   if (this_alternative[c] == (int) NO_REGS)
+                   this_alternative_win[m] = 0;
+                   if (this_alternative[m] == (int) NO_REGS)
                      bad = 1;
                    /* But count the pair only once in the total badness of
                       this alternative, if the pair can be a dummy reload.  */
                    value
                      = find_dummy_reload (recog_data.operand[i],
-                                          recog_data.operand[c],
+                                          recog_data.operand[m],
                                           recog_data.operand_loc[i],
-                                          recog_data.operand_loc[c],
-                                          operand_mode[i], operand_mode[c],
-                                          this_alternative[c], -1,
-                                          this_alternative_earlyclobber[c]);
+                                          recog_data.operand_loc[m],
+                                          operand_mode[i], operand_mode[m],
+                                          this_alternative[m], -1,
+                                          this_alternative_earlyclobber[m]);
 
                    if (value != 0)
                      losers--;
@@ -3056,7 +3076,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                /* This can be fixed with reloads if the operand
                   we are supposed to match can be fixed with reloads.  */
                badop = 0;
-               this_alternative[i] = this_alternative[c];
+               this_alternative[i] = this_alternative[m];
 
                /* If we have to reload this operand and some previous
                   operand also had to match the same thing as this
@@ -3175,7 +3195,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case 'G':
              case 'H':
                if (GET_CODE (operand) == CONST_DOUBLE
-                   && CONST_DOUBLE_OK_FOR_LETTER_P (operand, c))
+                   && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
                  win = 1;
                break;
 
@@ -3209,7 +3229,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case 'O':
              case 'P':
                if (GET_CODE (operand) == CONST_INT
-                   && CONST_OK_FOR_LETTER_P (INTVAL (operand), c))
+                   && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
                  win = 1;
                break;
 
@@ -3242,14 +3262,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                goto reg;
 
              default:
-               if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+               if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
                  {
-#ifdef EXTRA_CONSTRAINT
-                   if (EXTRA_MEMORY_CONSTRAINT (c))
+#ifdef EXTRA_CONSTRAINT_STR
+                   if (EXTRA_MEMORY_CONSTRAINT (c, p))
                      {
                        if (force_reload)
                          break;
-                       if (EXTRA_CONSTRAINT (operand, c))
+                       if (EXTRA_CONSTRAINT_STR (operand, c, p))
                          win = 1;
                        /* If the address was already reloaded,
                           we win as well.  */
@@ -3262,7 +3282,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                            && REGNO (operand) >= FIRST_PSEUDO_REGISTER
                            && reg_renumber[REGNO (operand)] < 0
                            && ((reg_equiv_mem[REGNO (operand)] != 0
-                                && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
+                                && EXTRA_CONSTRAINT_STR (reg_equiv_mem[REGNO (operand)], c, p))
                                || (reg_equiv_address[REGNO (operand)] != 0)))
                          win = 1;
 
@@ -3276,9 +3296,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        offmemok = 1;
                        break;
                      }
-                   if (EXTRA_ADDRESS_CONSTRAINT (c))
+                   if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                      {
-                       if (EXTRA_CONSTRAINT (operand, c))
+                       if (EXTRA_CONSTRAINT_STR (operand, c, p))
                          win = 1;
 
                        /* If we didn't already win, we can reload
@@ -3292,14 +3312,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                        break;
                      }
 
-                   if (EXTRA_CONSTRAINT (operand, c))
+                   if (EXTRA_CONSTRAINT_STR (operand, c, p))
                      win = 1;
 #endif
                    break;
                  }
 
                this_alternative[i]
-                 = (int) reg_class_subunion[this_alternative[i]][(int) REG_CLASS_FROM_LETTER (c)];
+                 = (int) (reg_class_subunion
+                          [this_alternative[i]]
+                          [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
              reg:
                if (GET_MODE (operand) == BLKmode)
                  break;
@@ -3310,6 +3332,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
                  win = 1;
                break;
              }
+         while ((p += len), c);
 
          constraints[i] = p;
 
@@ -4358,8 +4381,9 @@ alternative_allows_memconst (constraint, altnum)
     }
   /* Scan the requested alternative for 'm' or 'o'.
      If one of them is present, this alternative accepts memory constants.  */
-  while ((c = *constraint++) && c != ',' && c != '#')
-    if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
+  for (; (c = *constraint) && c != ',' && c != '#';
+       constraint += CONSTRAINT_LEN (c, constraint))
+    if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c, constraint))
       return 1;
   return 0;
 }
index 40204074af7c3a7a247fe508e5a6bd8a51734ec0..4fd401c89bb5ab97c553b107da19fe5b17d3d36c 100644 (file)
@@ -1355,7 +1355,7 @@ maybe_fix_stack_asms ()
 
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
 
              if (c == '\0' || c == ',' || c == '#')
                {
@@ -1363,6 +1363,7 @@ maybe_fix_stack_asms ()
                     class, and reset the class.  */
                  IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
                  cls = NO_REGS;
+                 p++;
                  if (c == '#')
                    do {
                      c = *p++;
@@ -1393,13 +1394,14 @@ maybe_fix_stack_asms ()
                  break;
 
                default:
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    cls = (int) reg_class_subunion[cls]
                      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
                  else
                    cls = (int) reg_class_subunion[cls]
-                     [(int) REG_CLASS_FROM_LETTER (c)];
+                     [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
                }
+             p += CONSTRAINT_LEN (c, p);
            }
        }
       /* Those of the registers which are clobbered, but allowed by the
@@ -8418,7 +8420,7 @@ reload_cse_simplify_operands (insn, testreg)
          p = constraints[i];
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
 
              switch (c)
                {
@@ -8442,7 +8444,9 @@ reload_cse_simplify_operands (insn, testreg)
 
                default:
                  class
-                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
+                   = (reg_class_subunion
+                      [(int) class]
+                      [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
                  break;
 
                case ',': case '\0':
@@ -8462,6 +8466,7 @@ reload_cse_simplify_operands (insn, testreg)
                  j++;
                  break;
                }
+             p += CONSTRAINT_LEN (c, p);
 
              if (c == '\0')
                break;
index ac0aa15bef2952a267a2a77649008abac207ee72..960bea0f24e6726902fbccd6d69cfd4e29ec96e2 100644 (file)
@@ -1197,7 +1197,7 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
     }
 
   /* Loop through the constraint string.  */
-  for (p = constraint + 1; *p; ++p)
+  for (p = constraint + 1; *p; p += CONSTRAINT_LEN (*p, p))
     switch (*p)
       {
       case '+':
@@ -1249,12 +1249,12 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
       default:
        if (!ISALPHA (*p))
          break;
-       if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
+       if (REG_CLASS_FROM_CONSTRAINT (*p, p) != NO_REGS)
          *allows_reg = true;
-#ifdef EXTRA_CONSTRAINT
-       else if (EXTRA_ADDRESS_CONSTRAINT (*p))
+#ifdef EXTRA_CONSTRAINT_STR
+       else if (EXTRA_ADDRESS_CONSTRAINT (*p, p))
          *allows_reg = true;
-       else if (EXTRA_MEMORY_CONSTRAINT (*p))
+       else if (EXTRA_MEMORY_CONSTRAINT (*p, p))
          *allows_mem = true;
        else
          {
@@ -1297,7 +1297,7 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
 
   /* Make sure constraint has neither `=', `+', nor '&'.  */
 
-  for (j = 0; j < c_len; j++)
+  for (j = 0; j < c_len; j += CONSTRAINT_LEN (constraint[j], constraint+j))
     switch (constraint[j])
       {
       case '+':  case '=':  case '&':
@@ -1356,10 +1356,16 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
              *constraint_p = constraint;
              c_len = strlen (constraint);
              j = 0;
+             /* ??? At the end of the loop, we will skip the first part of
+                the matched constraint.  This assumes not only that the
+                other constraint is an output constraint, but also that
+                the '=' or '+' come first.  */
              break;
            }
          else
            j = end - constraint;
+         /* Anticipate increment at end of loop.  */
+         j--;
        }
        /* Fall through.  */
 
@@ -1378,12 +1384,13 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
            error ("invalid punctuation `%c' in constraint", constraint[j]);
            return false;
          }
-       if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
+       if (REG_CLASS_FROM_CONSTRAINT (constraint[j], constraint + j)
+           != NO_REGS)
          *allows_reg = true;
-#ifdef EXTRA_CONSTRAINT
-       else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
+#ifdef EXTRA_CONSTRAINT_STR
+       else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j], constraint + j))
          *allows_reg = true;
-       else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
+       else if (EXTRA_MEMORY_CONSTRAINT (constraint[j], constraint + j))
          *allows_mem = true;
        else
          {