[llvm] Make more math&bit functions constexpr, NFC (PR #145856)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 26 05:13:57 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-adt

Author: Haojian Wu (hokein)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/145856.diff


2 Files Affected:

- (modified) llvm/include/llvm/ADT/bit.h (+8-8) 
- (modified) llvm/include/llvm/Support/MathExtras.h (+25-22) 


``````````diff
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
index d6e33c3e6133a..207653f2f8478 100644
--- a/llvm/include/llvm/ADT/bit.h
+++ b/llvm/include/llvm/ADT/bit.h
@@ -154,7 +154,7 @@ template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
 /// Only unsigned integral types are allowed.
 ///
 /// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countr_zero(T Val) {
+template <typename T> [[nodiscard]] constexpr int countr_zero(T Val) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   if (!Val)
@@ -200,7 +200,7 @@ template <typename T> [[nodiscard]] int countr_zero(T Val) {
 /// Only unsigned integral types are allowed.
 ///
 /// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countl_zero(T Val) {
+template <typename T> [[nodiscard]] constexpr int countl_zero(T Val) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   if (!Val)
@@ -244,7 +244,7 @@ template <typename T> [[nodiscard]] int countl_zero(T Val) {
 /// Only unsigned integral types are allowed.
 ///
 /// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countl_one(T Value) {
+template <typename T> [[nodiscard]] constexpr int countl_one(T Value) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   return llvm::countl_zero<T>(~Value);
@@ -257,7 +257,7 @@ template <typename T> [[nodiscard]] int countl_one(T Value) {
 /// Only unsigned integral types are allowed.
 ///
 /// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countr_one(T Value) {
+template <typename T> [[nodiscard]] constexpr int countr_one(T Value) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   return llvm::countr_zero<T>(~Value);
@@ -267,7 +267,7 @@ template <typename T> [[nodiscard]] int countr_one(T Value) {
 /// Returns 0 otherwise.
 ///
 /// Ex. bit_width(5) == 3.
-template <typename T> [[nodiscard]] int bit_width(T Value) {
+template <typename T> [[nodiscard]] constexpr int bit_width(T Value) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
@@ -277,7 +277,7 @@ template <typename T> [[nodiscard]] int bit_width(T Value) {
 /// nonzero.  Returns 0 otherwise.
 ///
 /// Ex. bit_floor(5) == 4.
-template <typename T> [[nodiscard]] T bit_floor(T Value) {
+template <typename T> [[nodiscard]] constexpr T bit_floor(T Value) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   if (!Value)
@@ -292,7 +292,7 @@ template <typename T> [[nodiscard]] T bit_floor(T Value) {
 ///
 /// The return value is undefined if the input is larger than the largest power
 /// of two representable in T.
-template <typename T> [[nodiscard]] T bit_ceil(T Value) {
+template <typename T> [[nodiscard]] constexpr T bit_ceil(T Value) {
   static_assert(std::is_unsigned_v<T>,
                 "Only unsigned integral types are allowed.");
   if (Value < 2)
@@ -304,7 +304,7 @@ template <typename T> [[nodiscard]] T bit_ceil(T Value) {
 /// Ex. popcount(0xF000F000) = 8
 /// Returns 0 if the word is zero.
 template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] inline int popcount(T Value) noexcept {
+[[nodiscard]] inline constexpr int popcount(T Value) noexcept {
   if constexpr (sizeof(T) <= 4) {
 #if defined(__GNUC__)
     return (int)__builtin_popcount(Value);
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 7bbf1b3aab761..2cf0511231976 100644
--- a/llvm/include/llvm/Support/MathExtras.h
+++ b/llvm/include/llvm/Support/MathExtras.h
@@ -303,8 +303,8 @@ constexpr bool isPowerOf2_64(uint64_t Value) {
 /// If true, \p MaskIdx will specify the index of the lowest set bit and \p
 /// MaskLen is updated to specify the length of the mask, else neither are
 /// updated.
-inline bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx,
-                             unsigned &MaskLen) {
+inline constexpr bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx,
+                                       unsigned &MaskLen) {
   if (!isShiftedMask_32(Value))
     return false;
   MaskIdx = llvm::countr_zero(Value);
@@ -316,8 +316,8 @@ inline bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx,
 /// remainder zero (64 bit version.) If true, \p MaskIdx will specify the index
 /// of the lowest set bit and \p MaskLen is updated to specify the length of the
 /// mask, else neither are updated.
-inline bool isShiftedMask_64(uint64_t Value, unsigned &MaskIdx,
-                             unsigned &MaskLen) {
+inline constexpr bool isShiftedMask_64(uint64_t Value, unsigned &MaskIdx,
+                                       unsigned &MaskLen) {
   if (!isShiftedMask_64(Value))
     return false;
   MaskIdx = llvm::countr_zero(Value);
@@ -337,26 +337,26 @@ template <> constexpr size_t CTLog2<1>() { return 0; }
 /// Return the floor log base 2 of the specified value, -1 if the value is zero.
 /// (32 bit edition.)
 /// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
-inline unsigned Log2_32(uint32_t Value) {
+inline constexpr unsigned Log2_32(uint32_t Value) {
   return 31 - llvm::countl_zero(Value);
 }
 
 /// Return the floor log base 2 of the specified value, -1 if the value is zero.
 /// (64 bit edition.)
-inline unsigned Log2_64(uint64_t Value) {
+inline constexpr unsigned Log2_64(uint64_t Value) {
   return 63 - llvm::countl_zero(Value);
 }
 
 /// Return the ceil log base 2 of the specified value, 32 if the value is zero.
 /// (32 bit edition).
 /// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
-inline unsigned Log2_32_Ceil(uint32_t Value) {
+inline constexpr unsigned Log2_32_Ceil(uint32_t Value) {
   return 32 - llvm::countl_zero(Value - 1);
 }
 
 /// Return the ceil log base 2 of the specified value, 64 if the value is zero.
 /// (64 bit edition.)
-inline unsigned Log2_64_Ceil(uint64_t Value) {
+inline constexpr unsigned Log2_64_Ceil(uint64_t Value) {
   return 64 - llvm::countl_zero(Value - 1);
 }
 
@@ -391,7 +391,7 @@ constexpr uint64_t NextPowerOf2(uint64_t A) {
 
 /// Returns the power of two which is greater than or equal to the given value.
 /// Essentially, it is a ceil operation across the domain of powers of two.
-inline uint64_t PowerOf2Ceil(uint64_t A) {
+inline constexpr uint64_t PowerOf2Ceil(uint64_t A) {
   if (!A || A > UINT64_MAX / 2)
     return 0;
   return UINT64_C(1) << Log2_64_Ceil(A);
@@ -569,7 +569,7 @@ template <unsigned B> constexpr int32_t SignExtend32(uint32_t X) {
 
 /// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
 /// Requires B <= 32.
-inline int32_t SignExtend32(uint32_t X, unsigned B) {
+inline constexpr int32_t SignExtend32(uint32_t X, unsigned B) {
   assert(B <= 32 && "Bit width out of range.");
   if (B == 0)
     return 0;
@@ -587,7 +587,7 @@ template <unsigned B> constexpr int64_t SignExtend64(uint64_t x) {
 
 /// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
 /// Requires B <= 64.
-inline int64_t SignExtend64(uint64_t X, unsigned B) {
+inline constexpr int64_t SignExtend64(uint64_t X, unsigned B) {
   assert(B <= 64 && "Bit width out of range.");
   if (B == 0)
     return 0;
@@ -614,9 +614,9 @@ constexpr T AbsoluteDifference(U X, V Y) {
 /// maximum representable value of T on overflow.  ResultOverflowed indicates if
 /// the result is larger than the maximum representable value of type T.
 template <typename T>
-std::enable_if_t<std::is_unsigned_v<T>, T>
+constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
 SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
-  bool Dummy;
+  bool Dummy = 0;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
   // Hacker's Delight, p. 29
   T Z = X + Y;
@@ -630,8 +630,8 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
 /// Add multiple unsigned integers of type T.  Clamp the result to the
 /// maximum representable value of T on overflow.
 template <class T, class... Ts>
-std::enable_if_t<std::is_unsigned_v<T>, T> SaturatingAdd(T X, T Y, T Z,
-                                                         Ts... Args) {
+constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
+SaturatingAdd(T X, T Y, T Z, Ts... Args) {
   bool Overflowed = false;
   T XY = SaturatingAdd(X, Y, &Overflowed);
   if (Overflowed)
@@ -643,9 +643,9 @@ std::enable_if_t<std::is_unsigned_v<T>, T> SaturatingAdd(T X, T Y, T Z,
 /// maximum representable value of T on overflow.  ResultOverflowed indicates if
 /// the result is larger than the maximum representable value of type T.
 template <typename T>
-std::enable_if_t<std::is_unsigned_v<T>, T>
+constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
 SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
-  bool Dummy;
+  bool Dummy = 0;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
 
   // Hacker's Delight, p. 30 has a different algorithm, but we don't use that
@@ -689,9 +689,9 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
 /// overflow. ResultOverflowed indicates if the result is larger than the
 /// maximum representable value of type T.
 template <typename T>
-std::enable_if_t<std::is_unsigned_v<T>, T>
+constexpr std::enable_if_t<std::is_unsigned_v<T>, T>
 SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
-  bool Dummy;
+  bool Dummy = 0;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
 
   T Product = SaturatingMultiply(X, Y, &Overflowed);
@@ -707,7 +707,8 @@ LLVM_ABI extern const float huge_valf;
 /// Add two signed integers, computing the two's complement truncated result,
 /// returning true if overflow occurred.
 template <typename T>
-std::enable_if_t<std::is_signed_v<T>, T> AddOverflow(T X, T Y, T &Result) {
+constexpr std::enable_if_t<std::is_signed_v<T>, T> AddOverflow(T X, T Y,
+                                                               T &Result) {
 #if __has_builtin(__builtin_add_overflow)
   return __builtin_add_overflow(X, Y, &Result);
 #else
@@ -733,7 +734,8 @@ std::enable_if_t<std::is_signed_v<T>, T> AddOverflow(T X, T Y, T &Result) {
 /// Subtract two signed integers, computing the two's complement truncated
 /// result, returning true if an overflow occurred.
 template <typename T>
-std::enable_if_t<std::is_signed_v<T>, T> SubOverflow(T X, T Y, T &Result) {
+constexpr std::enable_if_t<std::is_signed_v<T>, T> SubOverflow(T X, T Y,
+                                                               T &Result) {
 #if __has_builtin(__builtin_sub_overflow)
   return __builtin_sub_overflow(X, Y, &Result);
 #else
@@ -759,7 +761,8 @@ std::enable_if_t<std::is_signed_v<T>, T> SubOverflow(T X, T Y, T &Result) {
 /// Multiply two signed integers, computing the two's complement truncated
 /// result, returning true if an overflow occurred.
 template <typename T>
-std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y, T &Result) {
+constexpr std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y,
+                                                               T &Result) {
 #if __has_builtin(__builtin_mul_overflow)
   return __builtin_mul_overflow(X, Y, &Result);
 #else

``````````

</details>


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


More information about the llvm-commits mailing list