On Thu, 27 Nov 2025, Alexandre Oliva wrote:

> On Nov 26, 2025, Vladimir Makarov <[email protected]> wrote:
> 
> > I any case any saving is welcome.  Taking also into account that the
> > iterator is simpler, I'd go for this change.
> 
> > So, Alex, if you want you can commit the patch (of course after usual
> > testing).
> 
> I'd already tested it, but I've added some comments, so I gave it
> another round of testing, and a ChangeLog entry.
> 
> Here's what I'm going to put in, barring objections.  Regstrapped on
> x86_64-linux-gnu.
> 
> 
> Use the newly-added first_diff API for iteration.  This hugely
> simplifies the iterator type, that no longer saves internal state, and
> largely simplifies and likely speeds up iteration, thanks to the use
> of ctz.
> 
> 
> for  gcc/ChangeLog
> 
>       PR rtl-optimization/122767
>       * hard-reg-set.h (hard_reg_set_iterator): Simplify.
>       (hard_reg_set_iter_init): Likewise.
>       (hard_reg_set_iter_set): Likewise.  Use first_diff.
>       (hard_reg_set_iter_next): Likewise.
> ---
>  gcc/hard-reg-set.h |   77 
> ++++++++++------------------------------------------
>  1 file changed, 15 insertions(+), 62 deletions(-)
> 
> diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h
> index e33c8e334d396..92f5531cb2016 100644
> --- a/gcc/hard-reg-set.h
> +++ b/gcc/hard-reg-set.h
> @@ -321,23 +321,13 @@ hard_reg_set_first_diff (const_hard_reg_set x, 
> const_hard_reg_set y,
>  }
>  #endif
>  
> -/* Iterator for hard register sets.  */
> +/* Iterator for hard register sets.  This is not an iterator proper, the bulk
> +   of the iterator state is held in the REGNO passed to the iterator
> +   functions.  */
>  
>  struct hard_reg_set_iterator
>  {
> -  /* Pointer to the current element.  */
> -  const HARD_REG_ELT_TYPE *pelt;
> -
> -  /* The length of the set.  */
> -  unsigned short length;
> -
> -  /* Word within the current element.  */
> -  unsigned short word_no;
> -
> -  /* Contents of the actually processed word.  When finding next bit
> -     it is shifted right, so that the actual bit is always the least
> -     significant bit of ACTUAL.  */
> -  HARD_REG_ELT_TYPE bits;
> +  const HARD_REG_SET *set;
>  };
>  
>  #define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT
> @@ -348,64 +338,27 @@ inline void
>  hard_reg_set_iter_init (hard_reg_set_iterator *iter, const_hard_reg_set set,
>                          unsigned min, unsigned *regno)
>  {
> -#ifdef HARD_REG_SET_LONGS
> -  iter->pelt = set.elts;
> -  iter->length = HARD_REG_SET_LONGS;
> -#else
> -  iter->pelt = &set;
> -  iter->length = 1;
> -#endif
> -  iter->word_no = min / HARD_REG_ELT_BITS;
> -  if (iter->word_no < iter->length)
> -    {
> -      iter->bits = iter->pelt[iter->word_no];
> -      iter->bits >>= min % HARD_REG_ELT_BITS;
> -
> -      /* This is required for correct search of the next bit.  */
> -      min += !iter->bits;
> -    }
> +  iter->set = &set;
>    *regno = min;
>  }
>  
>  inline bool
>  hard_reg_set_iter_set (hard_reg_set_iterator *iter, unsigned *regno)
>  {
> -  while (1)
> -    {
> -      /* Return false when we're advanced past the end of the set.  */
> -      if (iter->word_no >= iter->length)
> -        return false;
> -
> -      if (iter->bits)
> -        {
> -          /* Find the correct bit and return it.  */
> -          while (!(iter->bits & 1))
> -            {
> -              iter->bits >>= 1;
> -              *regno += 1;
> -            }
> -          return (*regno < FIRST_PSEUDO_REGISTER);
> -        }
> -
> -      /* Round to the beginning of the next word.  */
> -      *regno = (*regno + HARD_REG_ELT_BITS - 1);
> -      *regno -= *regno % HARD_REG_ELT_BITS;
> -
> -      /* Find the next non-zero word.  */
> -      while (++iter->word_no < iter->length)
> -        {
> -          iter->bits = iter->pelt[iter->word_no];
> -          if (iter->bits)
> -            break;
> -          *regno += HARD_REG_ELT_BITS;
> -        }
> -    }
> +  static const HARD_REG_SET hard_reg_set_empty = {};
> +  *regno = std::abs (hard_reg_set_first_diff (*iter->set,
> +                                           hard_reg_set_empty,
> +                                           *regno)) - 1;

I'm not sure I like using hard_reg_set_first_diff, esp. when
that ends up using the array version this looks like a step
backwards?

Richard.

> +  /* If hard_reg_set_first_diff returns zero, we'll have set *regno to
> +     (unsigned)-1 above, so the test below will yield FALSE, and iteration 
> will
> +     stop.  Also stop iteration if it finds a nonzero bit at
> +     FIRST_PSEUDO_REGISTER or greater.  */
> +  return *regno < FIRST_PSEUDO_REGISTER;
>  }
>  
>  inline void
> -hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
> +hard_reg_set_iter_next (hard_reg_set_iterator *, unsigned *regno)
>  {
> -  iter->bits >>= 1;
>    *regno += 1;
>  }
>  
> 
> 
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to