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;
+  /* 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;
 }
 


-- 
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