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?
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?
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)); \
--
Alexandre Oliva, happy hacker https://blog.lx.oliva.nom.br/
Free Software Activist FSFLA co-founder GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity.
Excluding neuro-others for not behaving ""normal"" is *not* inclusive!