Rather than using global variables and then copying them into a bb
structure, would it be possible to write directly into the bb structure?
The answer's probably "no", just asking. :-)

Bernd Schmidt <ber...@codesourcery.com> writes:
>       * regrename.c (struct du_head): Make nregs signed.
>       (scan_rtx_reg, scan_rtx_address, dump_def_use_chain): Remove
>       declarations.

This bit was split out.

>       (mark_conflict, create_new_chain): Move upwards in the file.

Same here.  Should mention the change to create_new_chain's interface
though.

> -     2. For each chain, the set of possible renaming registers is computed.
> +     2. We try combine the local chains across basic block boundaries by
> +        comparing chains that were open at the start or end of a block to
> +     those in successor/predecessor blocks.

"try to combine"

> +/* Dump all def/use chains, starting at id FROM.  */
>  
>  static void
> -dump_def_use_chain (struct du_head *head)
> +dump_def_use_chain (int from)
>  {
> -  while (head)
> +  du_head_p head;
> +  int i;
> +  FOR_EACH_VEC_ELT (du_head_p, id_to_chain, i, head)
>      {
>        struct du_chain *this_du = head->first;
> +      if (i < from)
> +     continue;
>        fprintf (dump_file, "Register %s (%d):",
>              reg_names[head->regno], head->nregs);
>        while (this_du)

I know it's only a dumping function, but maybe this'd be a good excuse
to add:

#define FOR_EACH_VEC_ELT_FROM(T, V, I, P, FROM)         \
  for (I = (FROM); VEC_iterate (T, (V), (I), (P)); ++(I))

> +/* A structure recording information about each basic block.  It is saved
> +   and restored around basic block boundaries.  */
> +struct bb_rename_info

Probably worth saying here or elsewhere that the bb->aux field points
to this information and that (more importantly) the bb->aux is null
for blocks that could not be optimised, including the exit block.

> +/* Record in RI that the block corresponding to it has an incoming
> +   live value, described by CHAIN.  */
> +static void
> +set_incoming_from_chain (struct bb_rename_info *ri, du_head_p chain)
> +{
> +  int min_reg, max_reg, i;
> +  int incoming_nregs = ri->incoming[chain->regno].nregs;
> +  int nregs;
> +
> +  /* If we've recorded the same information before, everything is fine.  */
> +  if (incoming_nregs == chain->nregs)
> +    {
> +      if (dump_file)
> +     fprintf (dump_file, "reg %d/%d already recorded\n",
> +              chain->regno, chain->nregs);
> +      return;
> +    }
> +
> +  /* If we have no information for any of the involved registers, update
> +     the incoming array.  */
> +  nregs = chain->nregs;
> +  while (nregs-- > 0)
> +    if (ri->incoming[chain->regno + nregs].nregs != 0
> +     || ri->incoming[chain->regno + nregs].unusable)
> +      break;
> +  if (nregs < 0)
> +    {
> +      nregs = chain->nregs;
> +      ri->incoming[chain->regno].nregs = nregs;
> +      while (nregs-- > 1)
> +     ri->incoming[chain->regno + nregs].nregs = -nregs;
> +      if (dump_file)
> +     fprintf (dump_file, "recorded reg %d/%d\n",
> +              chain->regno, chain->nregs);
> +      return;
> +    }
> +
> +  /* There must be some kind of conflict.  Set the unusable for all
> +     overlapping registers.  */
> +  min_reg = chain->regno;
> +  if (incoming_nregs < 0)
> +    min_reg += incoming_nregs;
> +  max_reg = chain->regno + chain->nregs;
> +  for (i = min_reg; i < max_reg; i++)
> +    ri->incoming[i].unusable = true;

In the incoming_nregs < 0 case, we only need to set
ri->incoming[chain->regno + incoming_nregs] itself, right,
not the other registers between that and ri->incoming[chain->regno]?
If so, I think it'd be clearer to have:

  /* There must be some kind of conflict.  Prevent both the old and
     new ranges from being used.  */
  if (incoming_nregs < 0)
    ri->incoming[chain->regno + incoming_nregs].unusable = true;
  for (i = 0; i < chain->nregs; i++)
    ri->incoming[chain->regno + i].unusable = true;

When I first looked at the code, I was wondering why we changed every
register in (chain->regno + incoming_nregs, chain_regno), but none in
[chain->regno + chain->nregs, OLD_END).  Seems like we should do neither
(as in the above suggestion) or both.

> +  /* Process all basic blocks by using a worklist, adding unvisited successor
> +     blocks whenever we reach the end of one basic blocks.  This ensures that
> +     whenever possible, we only process a block after at least one of its
> +     predecessors, which provides a "seeding" effect to make the logic in
> +     set_incoming_from_chain and init_rename_info useful.  */

Wouldn't a reverse post-order (inverted_post_order_compute) allow even
more pre-opening (as well as being less code)?

Looked good to me otherwise.

Richard

Reply via email to