[llvm] MathExtras: rewrite two methods to never overflow (PR #95556)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 14 08:48:11 PDT 2024


================
@@ -424,33 +426,37 @@ template <uint64_t Align> constexpr inline uint64_t alignTo(uint64_t Value) {
   return (Value + Align - 1) / Align * Align;
 }
 
-/// Returns the integer ceil(Numerator / Denominator). Unsigned integer version.
+/// Returns the integer ceil(Numerator / Denominator). Unsigned version.
+/// Guaranteed to never overflow.
 inline uint64_t divideCeil(uint64_t Numerator, uint64_t Denominator) {
-  return alignTo(Numerator, Denominator) / Denominator;
+  uint64_t Bias = (Numerator != 0);
+  return (Numerator - Bias) / Denominator + Bias;
 }
 
-/// Returns the integer ceil(Numerator / Denominator). Signed integer version.
+/// Returns the integer ceil(Numerator / Denominator). Signed version.
+/// Guaranteed to never overflow.
 inline int64_t divideCeilSigned(int64_t Numerator, int64_t Denominator) {
   assert(Denominator && "Division by zero");
   if (!Numerator)
     return 0;
   // C's integer division rounds towards 0.
-  int64_t X = (Denominator > 0) ? -1 : 1;
+  int64_t Bias = (Denominator > 0 ? 1 : -1);
----------------
jayfoad wrote:

Nit: writing this as `>= 0` makes it slightly more likely that the compiler can implement it in terms of `ashr(Dominator, 63)`. Same for some or all of the `> 0` checks below.

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


More information about the llvm-commits mailing list