On Fri, 28 Nov 2025, Alexandre Oliva wrote:
> On Nov 28, 2025, Alexandre Oliva <[email protected]> wrote:
>
> > Now, if we want to stick to those assumptions, the current iterator
> > implementation can be modified to use ffs or ctz instead. Would you
> > prefer that?
>
> Like this, maybe?
Yes, this looks more obviously like an improvement.
> Now, there are disappointingly few uses of
> EXECITE_IF_SET_IN_HARD_REG_SET. On the upside, there are a number of
> loops with TEST_HARD_REG_BIT remaining that could be converted to it to
> benefit from this speedup, but I'm not tackling that.
>
>
> Simplify the HARD_REG_SET iteration, using ctz and avoiding some
> unnecessary operations.
>
> Regstrapping on x86_64-linux-gnu. Ok to install?
OK by me.
Richard.
>
> for gcc/ChangeLog
>
> * hard-reg-set.h (hard_reg_set_iter_init): Drop unnecessary
> increment of min.
> (hard_reg_set_iter_set): Use ctz_hwi, and compute
> word-advanced regno from word_no.
> (hard_reg_set_iter_next): Only clear the cached LSB.
> ---
> gcc/hard-reg-set.h | 36 +++++++++++++++---------------------
> 1 file changed, 15 insertions(+), 21 deletions(-)
>
> diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h
> index e33c8e334d396..4e986a99c67db 100644
> --- a/gcc/hard-reg-set.h
> +++ b/gcc/hard-reg-set.h
> @@ -342,8 +342,8 @@ struct hard_reg_set_iterator
>
> #define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT
>
> -/* The implementation of the iterator functions is fully analogous to
> - the bitmap iterators. */
> +/* The implementation of the iterator functions is a simplified version of
> + those of bitmap iterators. */
> inline void
> hard_reg_set_iter_init (hard_reg_set_iterator *iter, const_hard_reg_set set,
> unsigned min, unsigned *regno)
> @@ -360,11 +360,8 @@ hard_reg_set_iter_init (hard_reg_set_iterator *iter,
> const_hard_reg_set set,
> {
> 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;
> + *regno = min;
> }
> - *regno = min;
> }
>
> inline bool
> @@ -378,37 +375,34 @@ hard_reg_set_iter_set (hard_reg_set_iterator *iter,
> unsigned *regno)
>
> if (iter->bits)
> {
> - /* Find the correct bit and return it. */
> - while (!(iter->bits & 1))
> - {
> - iter->bits >>= 1;
> - *regno += 1;
> - }
> + unsigned skip = ctz_hwi (iter->bits);
> + iter->bits >>= skip;
> + *regno += skip;
> 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;
> + {
> + *regno = iter->word_no * HARD_REG_ELT_BITS;
> + break;
> + }
> }
> }
> }
>
> inline void
> -hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
> +hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *)
> {
> - iter->bits >>= 1;
> - *regno += 1;
> + /* Only clear the bit, so that we skip it in iter_set. */
> + iter->bits &= ~ HARD_CONST (1);
> }
>
> +/* SET must not change throughout the iteration.
> + REGNUM (and ITER) may only be changed by the iteration functions. */
> #define EXECUTE_IF_SET_IN_HARD_REG_SET(SET, MIN, REGNUM, ITER) \
> for (hard_reg_set_iter_init (&(ITER), (SET), (MIN), &(REGNUM)); \
> hard_reg_set_iter_set (&(ITER), &(REGNUM)); \
>
>
>
--
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)