[llvm] MathExtras: template'ize alignToPowerOf2 (PR #97814)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 31 05:07:16 PDT 2024


================
@@ -488,13 +488,21 @@ constexpr uint64_t alignTo(uint64_t Value, uint64_t Align) {
   return CeilDiv * Align;
 }
 
+/// Will overflow only if result is not representable in T.
+template <typename U, typename V, typename T = common_uint<U, V>>
+constexpr T alignToPowerOf2(U Value, V Align) {
+  assert(Align != 0 && (Align & (Align - 1)) == 0 &&
+         "Align must be a power of 2");
+  T CeilDiv = divideCeil(Value, Align);
+  return CeilDiv * Align;
+}
+
+/// Fallback when arguments aren't integral.
 constexpr uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
   assert(Align != 0 && (Align & (Align - 1)) == 0 &&
          "Align must be a power of 2");
-  // Replace unary minus to avoid compilation error on Windows:
-  // "unary minus operator applied to unsigned type, result still unsigned"
-  uint64_t NegAlign = (~Align) + 1;
-  return (Value + Align - 1) & NegAlign;
----------------
artagnon wrote:

Sorry about taking so long to debug this, but I finally have definitive proof:

Consider Value=8589934592, Align=1, U = unsigned int, V = unsigned long. Then,

T is computed as unsigned long.
NegAlign is computed as 4294967295 (unsigned long).
Value + (Align - 1) is computed as 8589934592 (unsigned long).
(Value + (Align - 1)) & NegAlign is computed as 0 (unsigned long).

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


More information about the llvm-commits mailing list