Marcus Shawcroft <marcus.shawcr...@arm.com> writes:
> This patch adds an implementation of integer iterators.

Nice.  A few comments from an onlooker (on top of what Stephen said).

> +/* Since GCC does not construct a table of valid constants,
> +   we have to accept any int as valid.  No cross-checking can
> +   be done.  */
> +static int
> +find_int (const char *name)
> +{
> +  char *endptr;
> +  int ret;
> +
> +  if (ISDIGIT (*name))
> +    {
> +      ret = strtol (name, &endptr, 0);
> +      gcc_assert (*endptr == '\0');

I think this should be an error rather than an assert.

> +/* Stand-alone int iterator usage-checking function.  */
> +static bool
> +uses_int_iterator_p (rtx x, struct mapping *iterator, int opno)
> +{
> +  int i;
> +  for (i=0; i < num_int_iterator_data; i++)
> +    if (int_iterator_data[i].iterator->group == iterator->group &&
> +     int_iterator_data[i].iterator->index == iterator->index)

Formatting: && should be at the beginning of the second line.

> +      {
> +     /* Found an existing entry. Check if X is in its list.  */
> +     struct int_iterator_mapping it = int_iterator_data[i];
> +     int j;
> +
> +     for (j=0; j < it.num_rtx; j++)
> +     {
> +       if (it.rtxs[j].x == x && it.rtxs[j].opno == opno)
> +         return true;
> +     }

Formatting: redundant { ... }.

It might be easier to store a pointer to XEXP (x, opno) than storing
x and opno separately.

> +      }
> +  return false;
> +}
> +
>  /* Map a code or mode attribute string P to the underlying string for
>     ITERATOR and VALUE.  */
>  
> @@ -341,7 +414,9 @@
>    x = rtx_alloc (bellwether_code);
>    memcpy (x, original, RTX_CODE_SIZE (bellwether_code));
>  
> -  /* Change the mode or code itself.  */
> +  /* Change the mode or code itself.
> +     For int iterators, apply_iterator () does nothing. This is
> +     because we want to apply int iterators to operands below.  */

The way I imagined this working is that we'd just walk a list of
rtx * pointers for the current iterator and substitute the current
iterator value.  Then we'd take a deep copy of the rtx once all
iterators had been applied.  Checking every operand against the
substitution table seems a bit round-about.

It'd be good to do the same for codes and modes, but I'll volunteer
to do that as a follow-up.

> +/* Add to triplet-database for int iterators.  */
> +static void
> +add_int_iterator (struct mapping *iterator, rtx x, int opno)
> +{
> +
> +  /* Find iterator in int_iterator_data. If already present,
> +     add this R to its list of rtxs. If not present, create
> +     a new entry for INT_ITERATOR_DATA and add the R to its
> +     rtx list.  */
> +  int i;
> +  for (i=0; i < num_int_iterator_data; i++)
> +    if (int_iterator_data[i].iterator->index == iterator->index)
> +      {
> +     /* Found an existing entry. Add rtx to this iterator's list.  */
> +     int_iterator_data[i].rtxs =
> +                     XRESIZEVEC (struct rtx_list,
> +                                 int_iterator_data[i].rtxs,
> +                                 int_iterator_data[i].num_rtx + 1);
> +     int_iterator_data[i].rtxs[int_iterator_data[i].num_rtx].x = x;
> +     int_iterator_data[i].rtxs[int_iterator_data[i].num_rtx].opno = opno;
> +     int_iterator_data[i].num_rtx++;
> +     return;
> +      }
> +
> +  /* New INT_ITERATOR_DATA entry.  */
> +  if (num_int_iterator_data == 0)
> +    int_iterator_data = XNEWVEC (struct int_iterator_mapping, 1);
> +  else
> +    int_iterator_data = XRESIZEVEC (struct int_iterator_mapping,
> +                                 int_iterator_data,
> +                                 num_int_iterator_data + 1);
> +  int_iterator_data[num_int_iterator_data].iterator = iterator;
> +  int_iterator_data[num_int_iterator_data].rtxs = XNEWVEC (struct rtx_list, 
> 1);
> +  int_iterator_data[num_int_iterator_data].rtxs[0].x = x;
> +  int_iterator_data[num_int_iterator_data].rtxs[0].opno = opno;
> +  int_iterator_data[num_int_iterator_data].num_rtx = 1;
> +  num_int_iterator_data++;
> +}

VECs might be better here.

> @@ -1057,14 +1227,30 @@
>       XWINT (return_rtx, i) = tmp_wide;
>       break;
>  
> -      case 'i':
>        case 'n':
> -     read_name (&name);
>       validate_const_int (name.string);
>       tmp_int = atoi (name.string);
>       XINT (return_rtx, i) = tmp_int;
>       break;
> -
> +      case 'i':
> +     /* Can be an iterator or an integer constant.  */
> +     read_name (&name);
> +     if (!ISDIGIT (name.string[0]))
> +       {
> +         struct mapping *iterator;
> +         /* An iterator.  */
> +         iterator = find_int_iterator (&ints, name.string);
> +         /* Build (iterator, rtx, op) triplet-database.  */
> +         add_int_iterator (iterator, return_rtx, i);
> +       }
> +     else
> +       {
> +         /* A numeric constant.  */
> +         validate_const_int (name.string);
> +         tmp_int = atoi (name.string);
> +         XINT (return_rtx, i) = tmp_int;
> +       }
> +     break;
>        default:
>       gcc_unreachable ();
>        }

I don't see any need to split "i" and "n".  In fact we probably
shouldn't handle "n" at all, since it's only used in NOTE_INSNs.
So I think we should either remove the "n" case or continue to
treat it in the same way as "i".

Richard

Reply via email to