[libc-commits] [libc] [libc][stdbit] implement stdc_first_trailing_zero (C23) (PR #81526)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Mon Feb 12 13:31:42 PST 2024


================
@@ -268,6 +268,65 @@ SPECIALIZE_FLZ(first_leading_zero, unsigned long long, __builtin_clzll)
 
 #undef SPECIALIZE_FLZ
 
+#define SPECIALIZE_FLO(NAME, TYPE, BUILTIN)                                    \
+  template <> [[nodiscard]] LIBC_INLINE constexpr int NAME<TYPE>(TYPE value) { \
+    static_assert(cpp::is_unsigned_v<TYPE>);                                   \
+    return value == static_cast<TYPE>(0)                                       \
+               ? 0                                                             \
+               : BUILTIN(static_cast<TYPE>(value)) + 1;                        \
+  }
+
+template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>>
+[[nodiscard]] LIBC_INLINE constexpr int first_leading_one(T value) {
+  return value == static_cast<T>(0) ? 0
+                                    : countl_zero<T>(static_cast<T>(value)) + 1;
+}
+
+#if LIBC_HAS_BUILTIN(__builtin_clzs)
+SPECIALIZE_FLO(first_leading_one, unsigned short, __builtin_clzs)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clz)
+SPECIALIZE_FLO(first_leading_one, unsigned int, __builtin_clz)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clzl)
+SPECIALIZE_FLO(first_leading_one, unsigned long, __builtin_clzl)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clzll)
+SPECIALIZE_FLO(first_leading_one, unsigned long long, __builtin_clzll)
+#endif
+
+#undef SPECIALIZE_FLO
+
+#define SPECIALIZE_FTZ(NAME, TYPE, BUILTIN)                                    \
+  template <> [[nodiscard]] LIBC_INLINE constexpr int NAME<TYPE>(TYPE value) { \
+    static_assert(cpp::is_unsigned_v<TYPE>);                                   \
+    return value == cpp::numeric_limits<TYPE>::max()                           \
+               ? 0                                                             \
+               : BUILTIN(static_cast<TYPE>(~value)) + 1;                       \
+  }
+
+template <typename T, typename = cpp::enable_if_t<cpp::is_unsigned_v<T>>>
+[[nodiscard]] LIBC_INLINE constexpr int first_trailing_zero(T value) {
+  return value == cpp::numeric_limits<T>::max()
+             ? 0
+             : countr_zero(static_cast<T>(~value)) + 1;
+}
+
+#if LIBC_HAS_BUILTIN(__builtin_clzs)
+SPECIALIZE_FTZ(first_trailing_zero, unsigned short, __builtin_ctzs)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clz)
+SPECIALIZE_FTZ(first_trailing_zero, unsigned int, __builtin_ctz)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clzl)
+SPECIALIZE_FTZ(first_trailing_zero, unsigned long, __builtin_ctzl)
+#endif
+#if LIBC_HAS_BUILTIN(__builtin_clzll)
----------------
nickdesaulniers wrote:

These has builtin checks should be checking against `clz` not `ctz`.

https://github.com/llvm/llvm-project/pull/81526


More information about the libc-commits mailing list