[llvm] [ADT] implement countl_zero_constexpr and reuse it for countl_zero & bit_width_constexpr (PR #189111)

Max Graey via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 07:34:57 PDT 2026


================
@@ -227,6 +227,38 @@ template <typename T> [[nodiscard]] int countr_zero(T Val) {
   return countr_zero_constexpr(Val);
 }
 
+/// Count number of 0's from the most significant bit to the least
+///   stopping at the first 1.
+///
+/// A constexpr version of countl_zero.
+///
+/// Only unsigned integral types are allowed.
+///
+/// Returns std::numeric_limits<T>::digits on an input of 0.
+template <typename T> [[nodiscard]] constexpr int countl_zero_constexpr(T Val) {
+  static_assert(std::is_unsigned_v<T>,
+                "Only unsigned integral types are allowed.");
+
+  constexpr int BitWidth = std::numeric_limits<T>::digits;
+
+  if (!Val)
+    return BitWidth;
+
+  Val |= (Val >> 1);
+  Val |= (Val >> 2);
+  Val |= (Val >> 4);
+  if constexpr (BitWidth > 8) {
+    Val |= (Val >> 8);
+  }
+  if constexpr (BitWidth > 16) {
+    Val |= (Val >> 16);
+  }
+  if constexpr (BitWidth > 32) {
+    Val |= (Val >> 32);
+  }
+  return BitWidth - llvm::popcount(Val);
----------------
MaxGraey wrote:

The main idea here is to reuse `llvm::popcount`, which can be executed in a `constexpr` context. Similar to [countr_zero_constexpr](https://github.com/llvm/llvm-project/blob/2cff8d52b7c5425d16674519b664b41116dc9af2/llvm/include/llvm/ADT/bit.h#L193). In theory, this should slightly improve performance, especially for 64-bit Vals.

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


More information about the llvm-commits mailing list