This makes several functions in <bit> faster to compile, with fewer
expressions to parse and fewer instantiations of __numeric_traits
required.

libstdc++-v3/ChangeLog:

        PR libstdc++/118855
        * include/std/bit (__count_lzero, __count_rzero, __popcount):
        Use type-generic built-ins when available.
---

Tested x86_64-linux.

This depends on [PATCH 1/2] because the built-ins reject signed
arguments, so we need to fix all (mis)uses of these functions within the
library. That shouldn't affect user code, because users should be using
the public APIs like std::bit_ceil etc. and those already have static
assertions to reject signed types.

Does this seem OK for stage 3 or should it wait for stage 1?

 libstdc++-v3/include/std/bit | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit
index 483801ee85bf..b53c1baccbb3 100644
--- a/libstdc++-v3/include/std/bit
+++ b/libstdc++-v3/include/std/bit
@@ -205,6 +205,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __gnu_cxx::__int_traits;
       constexpr auto _Nd = __int_traits<_Tp>::__digits;
 
+#if __has_builtin(__builtin_clzg)
+      return __builtin_clzg(__x, _Nd);
+#else
       if (__x == 0)
         return _Nd;
 
@@ -242,6 +245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          unsigned long long __low = __x & __max_ull;
          return (_Nd - _Nd_ull) + __builtin_clzll(__low);
        }
+#endif
     }
 
   template<typename _Tp>
@@ -258,6 +262,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __gnu_cxx::__int_traits;
       constexpr auto _Nd = __int_traits<_Tp>::__digits;
 
+#if __has_builtin(__builtin_ctzg)
+      return __builtin_ctzg(__x, _Nd);
+#else
       if (__x == 0)
         return _Nd;
 
@@ -283,6 +290,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          unsigned long long __high = __x >> _Nd_ull;
          return __builtin_ctzll(__high) + _Nd_ull;
        }
+#endif
     }
 
   template<typename _Tp>
@@ -296,6 +304,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     constexpr int
     __popcount(_Tp __x) noexcept
     {
+#if __has_builtin(__builtin_popcountg)
+      return __builtin_popcountg(__x);
+#else
       using __gnu_cxx::__int_traits;
       constexpr auto _Nd = __int_traits<_Tp>::__digits;
 
@@ -319,6 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          unsigned long long __high = __x >> _Nd_ull;
          return __builtin_popcountll(__low) + __builtin_popcountll(__high);
        }
+#endif
     }
 
   template<typename _Tp>
-- 
2.48.1

Reply via email to