RFA: Alternative iterator implementation

Tejas Belagod tbelagod@arm.com
Mon Jun 11 17:12:00 GMT 2012


Richard Sandiford wrote:
> As discussed in the context of the AARCH64 submission, this patch
> rewrites the iterator handling in read-rtl.c so that we record
> iterator positions using an on-the-side VEC rather than placeholder
> modes and codes.  We then substitute in-place for each sequence of
> iterator values and take a deep copy of the result.  We do any string
> substitutions during the copy.
> 
> The patch also generalises the current use of attributes for rtx modes
> ("(zero_extend:<WIDER_MODE> ...)", etc.) so that the same kind of thing
> can be done with future iterator types, including the int iterators.
> Not sure whether that'll be useful or not, but it made the patch
> easier to write.
> 
> Tested by making sure that the insn-*.c output didn't change for
> x86_64-linux-gnu, except that we now do a better job of retaining
> #line information (not seen as a good thing by everbody, I realise).
> Also made sure that things like insn-output.c are still generated
> in the blink of an eye.
> 
> Bootstrapped & regression-tested on x86_64-linux-gnu and i686-pc-linux-gnu.
> OK to install?
> 
> Richard
> 
> 
> gcc/
>         * read-rtl.c (mapping): Remove index field.  Add current_value field.
>         Define heap vectors.
>         (iterator_group): Fix long line.  Remove num_builtins field and
>         uses_iterator fields.  Make apply_iterator take a void * parameter.
>         (iterator_use, atttribute_use): New structures.
>         (iterator_traverse_data, BELLWETHER_CODE, bellwether_codes): Delete.
>         (current_iterators, iterator_uses, attribute_uses): New variables.
>         (uses_mode_iterator_p, uses_code_iterator_p): Delete.
>         (apply_mode_iterator, apply_code_iterator): Take a void * parameter.
>         (map_attr_string, apply_iterator_to_string): Remove iterator
>         and value parameters.  Look through all current iterator values
>         for a matching attribute.
>         (mode_attr_index, apply_mode_maps): Delete.
>         (apply_iterator_to_rtx): Replace with...
>         (copy_rtx_for_iterators): ...this new function.
>         (uses_iterator_p, apply_iterator_traverse): Delete.
>         (apply_attribute_uses, add_current_iterators, apply_iterators): New
>         functions.
>         (add_mapping): Remove index field.  Set current_value field.
>         (initialize_iterators): Don't set num_builtins and uses_iterator_p
>         fields.
>         (find_iterator): Delete.
>         (record_iterator_use, record_attribute_use): New functions.
>         (record_potential_iterator_use): New function.
>         (check_code_iterator): Remove handling of bellwether codes.
>         (read_rtx): Remove mode maps.  Truncate iterator and attribute uses.
>         (read_rtx_code, read_nested_rtx, read_rtx_variadic): Remove mode_maps
>         parameter.  Use the first code iterator value instead of the
>         bellwether_codes array.  Use record_potential_iterator_use
>         for modes.
> 
> Index: gcc/read-rtl.c
> ===================================================================
> --- gcc/read-rtl.c      2012-06-03 08:58:32.251211521 +0100
> +++ gcc/read-rtl.c      2012-06-03 09:20:47.633208254 +0100
> @@ -41,7 +41,7 @@ struct map_value {
>  };
> 
>  /* Maps an iterator or attribute name to a list of (integer, string) pairs.
> -   The integers are mode or code values; the strings are either C conditions
> +   The integers are iterator values; the strings are either C conditions
>     or attribute values.  */
>  struct mapping {
>    /* The name of the iterator or attribute.  */
> @@ -50,82 +50,80 @@ struct mapping {
>    /* The group (modes or codes) to which the iterator or attribute belongs.  */
>    struct iterator_group *group;
> 
> -  /* Gives a unique number to the attribute or iterator.  Numbers are
> -     allocated consecutively, starting at 0.  */
> -  int index;
> -
>    /* The list of (integer, string) pairs.  */
>    struct map_value *values;
> +
> +  /* For iterators, records the current value of the iterator.  */
> +  struct map_value *current_value;
>  };
> 
> -/* A structure for abstracting the common parts of code and mode iterators.  */
> +/* Vector definitions for the above.  */
> +typedef struct mapping *mapping_ptr;
> +DEF_VEC_P (mapping_ptr);
> +DEF_VEC_ALLOC_P (mapping_ptr, heap);
> +
> +/* A structure for abstracting the common parts of iterators.  */
>  struct iterator_group {
> -  /* Tables of "mapping" structures, one for attributes and one for iterators.  */
> +  /* Tables of "mapping" structures, one for attributes and one for
> +     iterators.  */
>    htab_t attrs, iterators;
> 
> -  /* The number of "real" modes or codes (and by extension, the first
> -     number available for use as an iterator placeholder).  */
> -  int num_builtins;
> -
> -  /* Treat the given string as the name of a standard mode or code and
> +  /* Treat the given string as the name of a standard mode, etc., and
>       return its integer value.  */
>    int (*find_builtin) (const char *);
> 
> -  /* Return true if the given rtx uses the given mode or code.  */
> -  bool (*uses_iterator_p) (rtx, int);
> +  /* Make the given pointer use the given iterator value.  */
> +  void (*apply_iterator) (void *, int);
> +};
> +
> +/* Records one use of an iterator.  */
> +struct iterator_use {
> +  /* The iterator itself.  */
> +  struct mapping *iterator;
> 
> -  /* Make the given rtx use the given mode or code.  */
> -  void (*apply_iterator) (rtx, int);
> +  /* The location of the use, as passed to the apply_iterator callback.  */
> +  void *ptr;
>  };
> 
> -/* A structure used to pass data from read_rtx to apply_iterator_traverse
> -   via htab_traverse.  */
> -struct iterator_traverse_data {
> -  /* Instruction queue.  */
> -  rtx queue;
> -  /* Attributes seen for modes.  */
> -  struct map_value *mode_maps;
> -  /* The last unknown attribute used as a mode.  */
> -  const char *unknown_mode_attr;
> +/* Vector definitions for the above.  */
> +typedef struct iterator_use iterator_use;
> +DEF_VEC_O (iterator_use);
> +DEF_VEC_ALLOC_O (iterator_use, heap);
> +
> +/* Records one use of an attribute (the "<[iterator:]attribute>" syntax)
> +   in a non-string rtx field.  */
> +struct attribute_use {
> +  /* The group that describes the use site.  */
> +  struct iterator_group *group;
> +
> +  /* The name of the attribute, possibly with an "iterator:" prefix.  */
> +  const char *value;
> +
> +  /* The location of the use, as passed to GROUP's apply_iterator callback.  */
> +  void *ptr;
>  };
> 
> -/* If CODE is the number of a code iterator, return a real rtx code that
> -   has the same format.  Return CODE otherwise.  */
> -#define BELLWETHER_CODE(CODE) \
> -  ((CODE) < NUM_RTX_CODE ? CODE : bellwether_codes[CODE - NUM_RTX_CODE])
> -
> -static int find_mode (const char *);
> -static bool uses_mode_iterator_p (rtx, int);
> -static void apply_mode_iterator (rtx, int);
> -static int find_code (const char *);
> -static bool uses_code_iterator_p (rtx, int);
> -static void apply_code_iterator (rtx, int);
> -static const char *apply_iterator_to_string (const char *, struct mapping *, int);
> -static rtx apply_iterator_to_rtx (rtx, struct mapping *, int,
> -                                 struct map_value *, const char **);
> -static bool uses_iterator_p (rtx, struct mapping *);
> -static const char *add_condition_to_string (const char *, const char *);
> -static void add_condition_to_rtx (rtx, const char *);
> -static int apply_iterator_traverse (void **, void *);
> -static struct mapping *add_mapping (struct iterator_group *, htab_t t,
> -                                   const char *);
> -static struct map_value **add_map_value (struct map_value **,
> -                                        int, const char *);
> -static void initialize_iterators (void);
> -static void read_conditions (void);
> +/* Vector definitions for the above.  */
> +typedef struct attribute_use attribute_use;
> +DEF_VEC_O (attribute_use);
> +DEF_VEC_ALLOC_O (attribute_use, heap);
> +
>  static void validate_const_int (const char *);
> -static int find_iterator (struct iterator_group *, const char *);
> -static struct mapping *read_mapping (struct iterator_group *, htab_t);
> -static void check_code_iterator (struct mapping *);
> -static rtx read_rtx_code (const char *, struct map_value **);
> -static rtx read_nested_rtx (struct map_value **);
> -static rtx read_rtx_variadic (struct map_value **, rtx);
> +static rtx read_rtx_code (const char *);
> +static rtx read_nested_rtx (void);
> +static rtx read_rtx_variadic (rtx);
> 
>  /* The mode and code iterator structures.  */
>  static struct iterator_group modes, codes;
> 
> -/* Index I is the value of BELLWETHER_CODE (I + NUM_RTX_CODE).  */
> -static enum rtx_code *bellwether_codes;
> +/* All iterators used in the current rtx.  */
> +static VEC (mapping_ptr, heap) *current_iterators;
> +
> +/* The list of all iterator uses in the current rtx.  */
> +static VEC (iterator_use, heap) *iterator_uses;
> +
> +/* The list of all attribute uses in the current rtx.  */
> +static VEC (attribute_use, heap) *attribute_uses;
> 
>  /* Implementations of the iterator_group callbacks for modes.  */
> 
> @@ -141,16 +139,10 @@ find_mode (const char *name)
>    fatal_with_file_and_line ("unknown mode `%s'", name);
>  }
> 
> -static bool
> -uses_mode_iterator_p (rtx x, int mode)
> -{
> -  return (int) GET_MODE (x) == mode;
> -}
> -
>  static void
> -apply_mode_iterator (rtx x, int mode)
> +apply_mode_iterator (void *loc, int mode)
>  {
> -  PUT_MODE (x, (enum machine_mode) mode);
> +  PUT_MODE ((rtx) loc, (enum machine_mode) mode);
>  }
> 
>  /* Implementations of the iterator_group callbacks for codes.  */
> @@ -167,122 +159,64 @@ find_code (const char *name)
>    fatal_with_file_and_line ("unknown rtx code `%s'", name);
>  }
> 
> -static bool
> -uses_code_iterator_p (rtx x, int code)
> -{
> -  return (int) GET_CODE (x) == code;
> -}
> -
>  static void
> -apply_code_iterator (rtx x, int code)
> +apply_code_iterator (void *loc, int code)
>  {
> -  PUT_CODE (x, (enum rtx_code) code);
> +  PUT_CODE ((rtx) loc, (enum rtx_code) code);
>  }
> 
> -/* Map a code or mode attribute string P to the underlying string for
> -   ITERATOR and VALUE.  */
> +/* Map attribute string P to its current value.  Return null if the attribute
> +   isn't known.  */
> 
>  static struct map_value *
> -map_attr_string (const char *p, struct mapping *iterator, int value)
> +map_attr_string (const char *p)
>  {
>    const char *attr;
> +  struct mapping *iterator;
> +  unsigned int i;
>    struct mapping *m;
>    struct map_value *v;
> +  int iterator_name_len;
> 
> -  /* If there's a "iterator:" prefix, check whether the iterator name matches.
> -     Set ATTR to the start of the attribute name.  */
> +  /* Peel off any "iterator:" prefix.  Set ATTR to the start of the
> +     attribute name.  */
>    attr = strchr (p, ':');
>    if (attr == 0)
> -    attr = p;
> +    {
> +      iterator_name_len = -1;
> +      attr = p;
> +    }
>    else
>      {
> -      if (strncmp (p, iterator->name, attr - p) != 0
> -         || iterator->name[attr - p] != 0)
> -       return 0;
> +      iterator_name_len = attr - p;
>        attr++;
>      }
> 
> -  /* Find the attribute specification.  */
> -  m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
> -  if (m == 0)
> -    return 0;
> -
> -  /* Find the attribute value for VALUE.  */
> -  for (v = m->values; v != 0; v = v->next)
> -    if (v->number == value)
> -      break;
> -
> -  return v;
> -}
> -
> -/* Given an attribute string used as a machine mode, return an index
> -   to store in the machine mode to be translated by
> -   apply_iterator_to_rtx.  */
> -
> -static unsigned int
> -mode_attr_index (struct map_value **mode_maps, const char *string)
> -{
> -  char *p;
> -  struct map_value *mv;
> -
> -  /* Copy the attribute string into permanent storage, without the
> -     angle brackets around it.  */
> -  obstack_grow0 (&string_obstack, string + 1, strlen (string) - 2);
> -  p = XOBFINISH (&string_obstack, char *);
> -
> -  mv = XNEW (struct map_value);
> -  mv->number = *mode_maps == 0 ? 0 : (*mode_maps)->number + 1;
> -  mv->string = p;
> -  mv->next = *mode_maps;
> -  *mode_maps = mv;
> -
> -  /* We return a code which we can map back into this string: the
> -     number of machine modes + the number of mode iterators + the index
> -     we just used.  */
> -  return MAX_MACHINE_MODE + htab_elements (modes.iterators) + mv->number;
> -}
> -
> -/* Apply MODE_MAPS to the top level of X, expanding cases where an
> -   attribute is used for a mode.  ITERATOR is the current iterator we are
> -   expanding, and VALUE is the value to which we are expanding it.
> -   This sets *UNKNOWN to true if we find a mode attribute which has not
> -   yet been defined, and does not change it otherwise.  */
> -
> -static void
> -apply_mode_maps (rtx x, struct map_value *mode_maps, struct mapping *iterator,
> -                int value, const char **unknown)
> -{
> -  unsigned int offset;
> -  int indx;
> -  struct map_value *pm;
> -
> -  offset = MAX_MACHINE_MODE + htab_elements (modes.iterators);
> -  if (GET_MODE (x) < offset)
> -    return;
> -
> -  indx = GET_MODE (x) - offset;
> -  for (pm = mode_maps; pm; pm = pm->next)
> +  FOR_EACH_VEC_ELT (mapping_ptr, current_iterators, i, iterator)
>      {
> -      if (pm->number == indx)
> -       {
> -         struct map_value *v;
> +      /* If an iterator name was specified, check that it matches.  */
> +      if (iterator_name_len >= 0
> +         && (strncmp (p, iterator->name, iterator_name_len) != 0
> +             || iterator->name[iterator_name_len] != 0))
> +       continue;
> 
> -         v = map_attr_string (pm->string, iterator, value);
> -         if (v)
> -           PUT_MODE (x, (enum machine_mode) find_mode (v->string));
> -         else
> -           *unknown = pm->string;
> -         return;
> -       }
> +      /* Find the attribute specification.  */
> +      m = (struct mapping *) htab_find (iterator->group->attrs, &attr);
> +      if (m)
> +       /* Find the attribute value associated with the current
> +          iterator value.  */
> +       for (v = m->values; v; v = v->next)
> +         if (v->number == iterator->current_value->number)
> +           return v;
>      }
> +  return NULL;
>  }
> 
> -/* Given that ITERATOR is being expanded as VALUE, apply the appropriate
> -   string substitutions to STRING.  Return the new string if any changes
> -   were needed, otherwise return STRING itself.  */
> +/* Apply the current iterator values to STRING.  Return the new string
> +   if any changes were needed, otherwise return STRING itself.  */
> 
>  static const char *
> -apply_iterator_to_string (const char *string, struct mapping *iterator, int value)
> +apply_iterator_to_string (const char *string)
>  {
>    char *base, *copy, *p, *start, *end;
>    struct map_value *v;
> @@ -296,7 +230,7 @@ apply_iterator_to_string (const char *st
>        p = start + 1;
> 
>        *end = 0;
> -      v = map_attr_string (p, iterator, value);
> +      v = map_attr_string (p);
>        *end = '>';
>        if (v == 0)
>         continue;
> @@ -317,55 +251,39 @@ apply_iterator_to_string (const char *st
>    return string;
>  }
> 
> -/* Return a copy of ORIGINAL in which all uses of ITERATOR have been
> -   replaced by VALUE.  MODE_MAPS holds information about attribute
> -   strings used for modes.  This sets *UNKNOWN_MODE_ATTR to the value of
> -   an unknown mode attribute, and does not change it otherwise.  */
> +/* Return a deep copy of X, substituting the current iterator
> +   values into any strings.  */
> 
>  static rtx
> -apply_iterator_to_rtx (rtx original, struct mapping *iterator, int value,
> -                      struct map_value *mode_maps,
> -                      const char **unknown_mode_attr)
> +copy_rtx_for_iterators (rtx original)
>  {
> -  struct iterator_group *group;
>    const char *format_ptr;
>    int i, j;
>    rtx x;
> -  enum rtx_code bellwether_code;
> 
>    if (original == 0)
>      return original;
> 
>    /* Create a shallow copy of ORIGINAL.  */
> -  bellwether_code = BELLWETHER_CODE (GET_CODE (original));
> -  x = rtx_alloc (bellwether_code);
> -  memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
> -
> -  /* Change the mode or code itself.  */
> -  group = iterator->group;
> -  if (group->uses_iterator_p (x, iterator->index + group->num_builtins))
> -    group->apply_iterator (x, value);
> -
> -  if (mode_maps)
> -    apply_mode_maps (x, mode_maps, iterator, value, unknown_mode_attr);
> +  x = rtx_alloc (GET_CODE (original));
> +  memcpy (x, original, RTX_CODE_SIZE (GET_CODE (original)));
> 
>    /* Change each string and recursively change each rtx.  */
> -  format_ptr = GET_RTX_FORMAT (bellwether_code);
> +  format_ptr = GET_RTX_FORMAT (GET_CODE (original));
>    for (i = 0; format_ptr[i] != 0; i++)
>      switch (format_ptr[i])
>        {
>        case 'T':
> -       XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i), iterator, value);
> +       XTMPL (x, i) = apply_iterator_to_string (XTMPL (x, i));
>         break;
> 
>        case 'S':
>        case 's':
> -       XSTR (x, i) = apply_iterator_to_string (XSTR (x, i), iterator, value);
> +       XSTR (x, i) = apply_iterator_to_string (XSTR (x, i));
>         break;
> 
>        case 'e':
> -       XEXP (x, i) = apply_iterator_to_rtx (XEXP (x, i), iterator, value,
> -                                            mode_maps, unknown_mode_attr);
> +       XEXP (x, i) = copy_rtx_for_iterators (XEXP (x, i));
>         break;
> 
>        case 'V':
> @@ -374,9 +292,8 @@ apply_iterator_to_rtx (rtx original, str
>           {
>             XVEC (x, i) = rtvec_alloc (XVECLEN (original, i));
>             for (j = 0; j < XVECLEN (x, i); j++)
> -             XVECEXP (x, i, j) = apply_iterator_to_rtx (XVECEXP (original, i, j),
> -                                                        iterator, value, mode_maps,
> -                                                        unknown_mode_attr);
> +             XVECEXP (x, i, j)
> +               = copy_rtx_for_iterators (XVECEXP (original, i, j));
>           }
>         break;
> 
> @@ -386,45 +303,6 @@ apply_iterator_to_rtx (rtx original, str
>    return x;
>  }
> 
> -/* Return true if X (or some subexpression of X) uses iterator ITERATOR.  */
> -
> -static bool
> -uses_iterator_p (rtx x, struct mapping *iterator)
> -{
> -  struct iterator_group *group;
> -  const char *format_ptr;
> -  int i, j;
> -
> -  if (x == 0)
> -    return false;
> -
> -  group = iterator->group;
> -  if (group->uses_iterator_p (x, iterator->index + group->num_builtins))
> -    return true;
> -
> -  format_ptr = GET_RTX_FORMAT (BELLWETHER_CODE (GET_CODE (x)));
> -  for (i = 0; format_ptr[i] != 0; i++)
> -    switch (format_ptr[i])
> -      {
> -      case 'e':
> -       if (uses_iterator_p (XEXP (x, i), iterator))
> -         return true;
> -       break;
> -
> -      case 'V':
> -      case 'E':
> -       if (XVEC (x, i))
> -         for (j = 0; j < XVECLEN (x, i); j++)
> -           if (uses_iterator_p (XVECEXP (x, i, j), iterator))
> -             return true;
> -       break;
> -
> -      default:
> -       break;
> -      }
> -  return false;
> -}
> -
>  /* Return a condition that must satisfy both ORIGINAL and EXTRA.  If ORIGINAL
>     has the form "&& ..." (as used in define_insn_and_splits), assume that
>     EXTRA is already satisfied.  Empty strings are treated like "true".  */
> @@ -466,50 +344,115 @@ add_condition_to_rtx (rtx x, const char
>      }
>  }
> 
> -/* A htab_traverse callback.  Search the EXPR_LIST given by DATA
> -   for rtxes that use the iterator in *SLOT.  Replace each such rtx
> -   with a list of expansions.  */
> +/* Apply the current iterator values to all attribute_uses.  */
> +
> +static void
> +apply_attribute_uses (void)
> +{
> +  struct map_value *v;
> +  attribute_use *ause;
> +  unsigned int i;
> +
> +  FOR_EACH_VEC_ELT (attribute_use, attribute_uses, i, ause)
> +    {
> +      v = map_attr_string (ause->value);
> +      if (!v)
> +       fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
> +      ause->group->apply_iterator (ause->ptr,
> +                                  ause->group->find_builtin (v->string));
> +    }
> +}
> +
> +/* A htab_traverse callback for iterators.  Add all used iterators
> +   to current_iterators.  */
> 
>  static int
> -apply_iterator_traverse (void **slot, void *data)
> +add_current_iterators (void **slot, void *data ATTRIBUTE_UNUSED)
>  {
> -  struct iterator_traverse_data *mtd = (struct iterator_traverse_data *) data;
>    struct mapping *iterator;
> -  struct map_value *v;
> -  rtx elem, new_elem, original, x;
> 
>    iterator = (struct mapping *) *slot;
> -  for (elem = mtd->queue; elem != 0; elem = XEXP (elem, 1))
> -    if (uses_iterator_p (XEXP (elem, 0), iterator))
> -      {
> -       /* For each iterator we expand, we set UNKNOWN_MODE_ATTR to NULL.
> -          If apply_iterator_rtx finds an unknown attribute for a mode,
> -          it will set it to the attribute.  We want to know whether
> -          the attribute is unknown after we have expanded all
> -          possible iterators, so setting it to NULL here gives us the
> -          right result when the hash table traversal is complete.  */
> -       mtd->unknown_mode_attr = NULL;
> +  if (iterator->current_value)
> +    VEC_safe_push (mapping_ptr, heap, current_iterators, iterator);
> +  return 1;
> +}
> 
> -       original = XEXP (elem, 0);
> -       for (v = iterator->values; v != 0; v = v->next)
> -         {
> -           x = apply_iterator_to_rtx (original, iterator, v->number,
> -                                      mtd->mode_maps,
> -                                      &mtd->unknown_mode_attr);
> -           add_condition_to_rtx (x, v->string);
> -           if (v != iterator->values)
> -             {
> -               /* Insert a new EXPR_LIST node after ELEM and put the
> -                  new expansion there.  */
> -               new_elem = rtx_alloc (EXPR_LIST);
> -               XEXP (new_elem, 1) = XEXP (elem, 1);
> -               XEXP (elem, 1) = new_elem;
> -               elem = new_elem;
> -             }
> -           XEXP (elem, 0) = x;
> -         }
> +/* Expand all iterators in the current rtx, which is given as ORIGINAL.
> +   Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE.  */
> +
> +static void
> +apply_iterators (rtx original, rtx *queue)
> +{
> +  unsigned int i;
> +  const char *condition;
> +  iterator_use *iuse;
> +  struct mapping *iterator;
> +  struct map_value *v;
> +  rtx x;
> +
> +  if (VEC_empty (iterator_use, iterator_uses))
> +    {
> +      /* Raise an error if any attributes were used.  */
> +      apply_attribute_uses ();
> +      XEXP (*queue, 0) = original;
> +      XEXP (*queue, 1) = NULL_RTX;
> +      return;
> +    }
> +
> +  /* Clear out the iterators from the previous run.  */
> +  FOR_EACH_VEC_ELT (mapping_ptr, current_iterators, i, iterator)
> +    iterator->current_value = NULL;
> +  VEC_truncate (mapping_ptr, current_iterators, 0);
> +
> +  /* Mark the iterators that we need this time.  */
> +  FOR_EACH_VEC_ELT (iterator_use, iterator_uses, i, iuse)
> +    iuse->iterator->current_value = iuse->iterator->values;
> +
> +  /* Get the list of iterators that are in use, preserving the
> +     definition order within each group.  */
> +  htab_traverse (modes.iterators, add_current_iterators, NULL);
> +  htab_traverse (codes.iterators, add_current_iterators, NULL);
> +  gcc_assert (!VEC_empty (mapping_ptr, current_iterators));
> +
> +  for (;;)
> +    {
> +      /* Apply the current iterator values.  Accumulate a condition to
> +        say when the resulting rtx can be used.  */
> +      condition = NULL;
> +      FOR_EACH_VEC_ELT (iterator_use, iterator_uses, i, iuse)
> +       {
> +         v = iuse->iterator->current_value;
> +         iuse->iterator->group->apply_iterator (iuse->ptr, v->number);
> +         condition = join_c_conditions (condition, v->string);
> +       }
> +      apply_attribute_uses ();
> +      x = copy_rtx_for_iterators (original);
> +      add_condition_to_rtx (x, condition);
> +
> +      /* Add the new rtx to the end of the queue.  */
> +      XEXP (*queue, 0) = x;
> +      XEXP (*queue, 1) = NULL_RTX;
> +
> +      /* Lexicographically increment the iterator value sequence.
> +        That is, cycle through iterator values, starting from the right,
> +        and stopping when one of them doesn't wrap around.  */
> +      i = VEC_length (mapping_ptr, current_iterators);
> +      for (;;)
> +       {
> +         if (i == 0)
> +           return;
> +         i--;
> +         iterator = VEC_index (mapping_ptr, current_iterators, i);
> +         iterator->current_value = iterator->current_value->next;
> +         if (iterator->current_value)
> +           break;
> +         iterator->current_value = iterator->values;
> +       }
> +
> +      /* At least one more rtx to go.  Allocate room for it.  */
> +      XEXP (*queue, 1) = rtx_alloc (EXPR_LIST);
> +      queue = &XEXP (*queue, 1);
>      }
> -  return 1;
>  }
> 
>  /* Add a new "mapping" structure to hashtable TABLE.  NAME is the name
> @@ -524,8 +467,8 @@ add_mapping (struct iterator_group *grou
>    m = XNEW (struct mapping);
>    m->name = xstrdup (name);
>    m->group = group;
> -  m->index = htab_elements (table);
>    m->values = 0;
> +  m->current_value = NULL;
> 
>    slot = htab_find_slot (table, m, INSERT);
>    if (*slot != 0)
> @@ -566,17 +509,13 @@ initialize_iterators (void)
>    modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    modes.iterators = htab_create (13, leading_string_hash,
>                                  leading_string_eq_p, 0);
> -  modes.num_builtins = MAX_MACHINE_MODE;
>    modes.find_builtin = find_mode;
> -  modes.uses_iterator_p = uses_mode_iterator_p;
>    modes.apply_iterator = apply_mode_iterator;
> 
>    codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    codes.iterators = htab_create (13, leading_string_hash,
>                                  leading_string_eq_p, 0);
> -  codes.num_builtins = NUM_RTX_CODE;
>    codes.find_builtin = find_code;
> -  codes.uses_iterator_p = uses_code_iterator_p;
>    codes.apply_iterator = apply_code_iterator;
> 
>    lower = add_mapping (&modes, modes.attrs, "mode");
> @@ -714,18 +653,60 @@ validate_const_int (const char *string)
>      fatal_with_file_and_line ("invalid decimal constant \"%s\"\n", string);
>  }
> 
> -/* Search GROUP for a mode or code called NAME and return its numerical
> -   identifier.  */
> +/* Record that PTR uses iterator ITERATOR.  */
> 
> -static int
> -find_iterator (struct iterator_group *group, const char *name)
> +static void
> +record_iterator_use (struct mapping *iterator, void *ptr)
> +{
> +  struct iterator_use *iuse;
> +
> +  iuse = VEC_safe_push (iterator_use, heap, iterator_uses, NULL);
> +  iuse->iterator = iterator;
> +  iuse->ptr = ptr;
> +}
> +
> +/* Record that PTR uses attribute VALUE, which must match a built-in
> +   value from group GROUP.  */
> +
> +static void
> +record_attribute_use (struct iterator_group *group, void *ptr,
> +                     const char *value)
> +{
> +  struct attribute_use *ause;
> +
> +  ause = VEC_safe_push (attribute_use, heap, attribute_uses, NULL);
> +  ause->group = group;
> +  ause->value = value;
> +  ause->ptr = ptr;
> +}
> +
> +/* Interpret NAME as either a built-in value, iterator or attribute
> +   for group GROUP.  PTR is the value to pass to GROUP's apply_iterator
> +   callback.  */
> +
> +static void
> +record_potential_iterator_use (struct iterator_group *group, void *ptr,
> +                              const char *name)
>  {
>    struct mapping *m;
> +  size_t len;
> 
> -  m = (struct mapping *) htab_find (group->iterators, &name);
> -  if (m != 0)
> -    return m->index + group->num_builtins;
> -  return group->find_builtin (name);
> +  len = strlen (name);
> +  if (name[0] == '<' && name[len - 1] == '>')
> +    {
> +      /* Copy the attribute string into permanent storage, without the
> +        angle brackets around it.  */
> +      obstack_grow0 (&string_obstack, name + 1, len - 2);
> +      record_attribute_use (group, ptr, XOBFINISH (&string_obstack, char *));
> +    }
> +  else
> +    {
> +      m = (struct mapping *) htab_find (group->iterators, &name);
> +      if (m != 0)
> +       record_iterator_use (m, ptr);
> +      else
> +       group->apply_iterator (ptr, group->find_builtin (name));
> +    }
>  }
> 
>  /* Finish reading a declaration of the form:
> @@ -787,7 +768,7 @@ read_mapping (struct iterator_group *gro
>  }
> 
>  /* Check newly-created code iterator ITERATOR to see whether every code has the
> -   same format.  Initialize the iterator's entry in bellwether_codes.  */
> +   same format.  */
> 
>  static void
>  check_code_iterator (struct mapping *iterator)
> @@ -800,10 +781,6 @@ check_code_iterator (struct mapping *ite
>      if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
>        fatal_with_file_and_line ("code iterator `%s' combines "
>                                 "different rtx formats", iterator->name);
> -
> -  bellwether_codes = XRESIZEVEC (enum rtx_code, bellwether_codes,
> -                                iterator->index + 1);
> -  bellwether_codes[iterator->index] = bellwether;
>  }
> 
>  /* Read an rtx-related declaration from the MD file, given that it
> @@ -815,8 +792,6 @@ check_code_iterator (struct mapping *ite
>  read_rtx (const char *rtx_name, rtx *x)
>  {
>    static rtx queue_head;
> -  struct map_value *mode_maps;
> -  struct iterator_traverse_data mtd;
> 
>    /* Do one-time initialization.  */
>    if (queue_head == 0)
> @@ -853,18 +828,9 @@ read_rtx (const char *rtx_name, rtx *x)
>        return false;
>      }
> 
> -  mode_maps = 0;
> -  XEXP (queue_head, 0) = read_rtx_code (rtx_name, &mode_maps);
> -  XEXP (queue_head, 1) = 0;
> -
> -  mtd.queue = queue_head;
> -  mtd.mode_maps = mode_maps;
> -  mtd.unknown_mode_attr = mode_maps ? mode_maps->string : NULL;
> -  htab_traverse (modes.iterators, apply_iterator_traverse, &mtd);
> -  htab_traverse (codes.iterators, apply_iterator_traverse, &mtd);
> -  if (mtd.unknown_mode_attr)
> -    fatal_with_file_and_line ("undefined attribute '%s' used for mode",
> -                             mtd.unknown_mode_attr);
> +  apply_iterators (read_rtx_code (rtx_name), &queue_head);
> +  VEC_truncate (iterator_use, iterator_uses, 0);
> +  VEC_truncate (attribute_use, attribute_uses, 0);
> 
>    *x = queue_head;
>    return true;
> @@ -872,13 +838,14 @@ read_rtx (const char *rtx_name, rtx *x)
> 
>  /* Subroutine of read_rtx and read_nested_rtx.  CODE_NAME is the name of
>     either an rtx code or a code iterator.  Parse the rest of the rtx and
> -   return it.  MODE_MAPS is as for iterator_traverse_data.  */
> +   return it.  */
> 
>  static rtx
> -read_rtx_code (const char *code_name, struct map_value **mode_maps)
> +read_rtx_code (const char *code_name)
>  {
>    int i;
> -  RTX_CODE real_code, bellwether_code;
> +  RTX_CODE code;
> +  struct mapping *iterator;
>    const char *format_ptr;
>    struct md_name name;
>    rtx return_rtx;
> @@ -893,13 +860,21 @@ read_rtx_code (const char *code_name, st
>        rtx value;               /* Value of this node.  */
>      };
> 
> -  real_code = (enum rtx_code) find_iterator (&codes, code_name);
> -  bellwether_code = BELLWETHER_CODE (real_code);
> +  /* If this code is an iterator, build the rtx using the iterator's
> +     first value.  */
> +  iterator = (struct mapping *) htab_find (codes.iterators, &code_name);
> +  if (iterator != 0)
> +    code = (enum rtx_code) iterator->values->number;
> +  else
> +    code = (enum rtx_code) codes.find_builtin (code_name);
> 
>    /* If we end up with an insn expression then we free this space below.  */
> -  return_rtx = rtx_alloc (bellwether_code);
> -  format_ptr = GET_RTX_FORMAT (bellwether_code);
> -  PUT_CODE (return_rtx, real_code);
> +  return_rtx = rtx_alloc (code);
> +  format_ptr = GET_RTX_FORMAT (code);
> +  PUT_CODE (return_rtx, code);
> +
> +  if (iterator)
> +    record_iterator_use (iterator, return_rtx);
> 
>    /* If what follows is `: mode ', read it and
>       store the mode in the rtx.  */
> @@ -907,16 +882,8 @@ read_rtx_code (const char *code_name, st
>    i = read_skip_spaces ();
>    if (i == ':')
>      {
> -      unsigned int mode;
> -
>        read_name (&name);
> -      if (name.string[0] != '<' || name.string[strlen (name.string) - 1] != '>')
> -       mode = find_iterator (&modes, name.string);
> -      else
> -       mode = mode_attr_index (mode_maps, name.string);
> -      PUT_MODE (return_rtx, (enum machine_mode) mode);
> -      if (GET_MODE (return_rtx) != mode)
> -       fatal_with_file_and_line ("mode too large");
> +      record_potential_iterator_use (&modes, return_rtx, name.string);
>      }
>    else
>      unread_char (i);
> @@ -931,7 +898,7 @@ read_rtx_code (const char *code_name, st
> 
>        case 'e':
>        case 'u':
> -       XEXP (return_rtx, i) = read_nested_rtx (mode_maps);
> +       XEXP (return_rtx, i) = read_nested_rtx ();
>         break;
> 
>        case 'V':
> @@ -965,7 +932,7 @@ read_rtx_code (const char *code_name, st
>                 fatal_expected_char (']', c);
>               unread_char (c);
>               list_counter++;
> -             obstack_ptr_grow (&vector_stack, read_nested_rtx (mode_maps));
> +             obstack_ptr_grow (&vector_stack, read_nested_rtx ());
>             }
>           if (list_counter > 0)
>             {
> @@ -1075,17 +1042,16 @@ read_rtx_code (const char *code_name, st
>    if (c == '('
>        && (GET_CODE (return_rtx) == AND
>           || GET_CODE (return_rtx) == IOR))
> -    return read_rtx_variadic (mode_maps, return_rtx);
> +    return read_rtx_variadic (return_rtx);
> 
>    unread_char (c);
>    return return_rtx;
>  }
> 
> -/* Read a nested rtx construct from the MD file and return it.
> -   MODE_MAPS is as for iterator_traverse_data.  */
> +/* Read a nested rtx construct from the MD file and return it.  */
> 
>  static rtx
> -read_nested_rtx (struct map_value **mode_maps)
> +read_nested_rtx (void)
>  {
>    struct md_name name;
>    int c;
> @@ -1099,7 +1065,7 @@ read_nested_rtx (struct map_value **mode
>    if (strcmp (name.string, "nil") == 0)
>      return_rtx = NULL;
>    else
> -    return_rtx = read_rtx_code (name.string, mode_maps);
> +    return_rtx = read_rtx_code (name.string);
> 
>    c = read_skip_spaces ();
>    if (c != ')')
> @@ -1115,7 +1081,7 @@ read_nested_rtx (struct map_value **mode
>     is just past the leading parenthesis of x3.  Only works
>     for THINGs which are dyadic expressions, e.g. AND, IOR.  */
>  static rtx
> -read_rtx_variadic (struct map_value **mode_maps, rtx form)
> +read_rtx_variadic (rtx form)
>  {
>    char c = '(';
>    rtx p = form, q;
> @@ -1128,7 +1094,7 @@ read_rtx_variadic (struct map_value **mo
>        PUT_MODE (q, GET_MODE (p));
> 
>        XEXP (q, 0) = XEXP (p, 1);
> -      XEXP (q, 1) = read_nested_rtx (mode_maps);
> +      XEXP (q, 1) = read_nested_rtx ();
> 
>        XEXP (p, 1) = q;
>        p = q;
> 

Hi Richard,

Thanks for this patch. I've attached the int iterators patch based on this. It 
has been bootstrapped on x86_64-linux-gnu and regression tested on 
arm-none-eabi. Also the generated .c and .h files have no diffs on 
arm-none-eabi. OK?

Thanks,
Tejas Belagod
ARM.

PS: The doc claims an example from the ARM port but that change will be in a 
subsequent patch.

Changelog:

2012-06-11  Tejas Belagod  <tejas.belagod@arm.com>

gcc/
	* doc/md.texi: Document int iterators.
	* read-rtl.c (ints): New.
	(find_int): New.
	(apply_int_iterator): New.
	(apply_iterators): Traverse int iterator table and add all the used
	iterators to list.
	(initialize_iterators): Initialize data structures and callbacks for int
	iterators.
	(read_rtx): Parse and read mappings for int iterators.
	(read_rtx_code): Record int iterator usage.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: int-iterators.txt
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20120611/9b37056b/attachment.txt>


More information about the Gcc-patches mailing list