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!

Reply via email to