vppinfra: bitops cleanup
[vpp.git] / src / vppinfra / bitops.h
index 0436569..15454ca 100644 (file)
 #ifndef included_clib_bitops_h
 #define included_clib_bitops_h
 
-#include <vppinfra/clib.h>
+static_always_inline uword
+clear_lowest_set_bit (uword x)
+{
+#ifdef __BMI__
+  return uword_bits > 32 ? _blsr_u64 (x) : _blsr_u32 (x);
+#else
+  return x & (x - 1);
+#endif
+}
+
+static_always_inline uword
+get_lowest_set_bit (uword x)
+{
+#ifdef __BMI__
+  return uword_bits > 32 ? _blsi_u64 (x) : _blsi_u32 (x);
+#else
+  return x & -x;
+#endif
+}
+
+static_always_inline u8
+get_lowest_set_bit_index (uword x)
+{
+  return uword_bits > 32 ? __builtin_ctzll (x) : __builtin_ctz (x);
+}
 
 /* Population count from Hacker's Delight. */
 always_inline uword
 count_set_bits (uword x)
 {
 #ifdef __POPCNT__
-#if uword_bits == 64
-  return __builtin_popcountll (x);
-#else
-  return __builtin_popcount (x);
-#endif
+  return uword_bits > 32 ? __builtin_popcountll (x) : __builtin_popcount (x);
 #else
 #if uword_bits == 64
   const uword c1 = 0x5555555555555555;
@@ -81,6 +101,15 @@ count_set_bits (uword x)
 #endif
 }
 
+#if uword_bits == 64
+#define count_leading_zeros(x) __builtin_clzll (x)
+#else
+#define count_leading_zeros(x) __builtin_clzll (x)
+#endif
+
+#define count_trailing_zeros(x) get_lowest_set_bit_index (x)
+#define log2_first_set(x)      get_lowest_set_bit_index (x)
+
 /* Based on "Hacker's Delight" code from GLS. */
 typedef struct
 {
@@ -163,45 +192,13 @@ next_with_same_number_of_set_bits (uword x)
   return ripple | ones;
 }
 
-#define foreach_set_bit(var,mask,body)                                 \
-do {                                                                   \
-  uword _foreach_set_bit_m_##var = (mask);                             \
-  uword _foreach_set_bit_f_##var;                                      \
-  while (_foreach_set_bit_m_##var != 0)                                        \
-    {                                                                  \
-      _foreach_set_bit_f_##var = first_set (_foreach_set_bit_m_##var); \
-      _foreach_set_bit_m_##var ^= _foreach_set_bit_f_##var;            \
-      (var) = min_log2 (_foreach_set_bit_f_##var);                     \
-      do { body; } while (0);                                          \
-    }                                                                  \
-} while (0)
-
-static_always_inline u64
-reset_lowest_set_bit (u64 x)
-{
-#ifdef __BMI__
-  return _blsr_u64 (x);
-#else
-  return x & (x - 1);
-#endif
-}
+#define foreach_set_bit_index(i, v)                                           \
+  for (uword _tmp = (v) + 0 * (uword) (i = get_lowest_set_bit_index (v));     \
+       _tmp;                                                                  \
+       i = get_lowest_set_bit_index (_tmp = clear_lowest_set_bit (_tmp)))
 
-static_always_inline u64
-get_lowest_set_bit (u64 x)
-{
-#ifdef __BMI__
-  return _blsi_u64 (x);
 #else
-  return x & -x;
-#endif
-}
-
-static_always_inline u64
-get_lowest_set_bit_index (u64 x)
-{
-  return __builtin_ctzll (x);
-}
-
+#warning "already included"
 #endif /* included_clib_bitops_h */
 
 /*