Skip to content

Commit 9a0d4ad

Browse files
Update MathExtras.h
1 parent 35efe17 commit 9a0d4ad

File tree

1 file changed

+30
-17
lines changed

1 file changed

+30
-17
lines changed

llvm/include/llvm/Support/MathExtras.h

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -764,27 +764,40 @@ std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y, T &Result) {
764764
#if __has_builtin(__builtin_mul_overflow)
765765
return __builtin_mul_overflow(X, Y, &Result);
766766
#else
767-
// Perform the unsigned multiplication on absolute values.
768767
using U = std::make_unsigned_t<T>;
769-
const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
770-
const U UY = Y < 0 ? (0 - static_cast<U>(Y)) : static_cast<U>(Y);
771-
const U UResult = UX * UY;
772768

773-
// Convert to signed.
774-
const bool IsNegative = (X < 0) ^ (Y < 0);
775-
Result = IsNegative ? (0 - UResult) : UResult;
776-
777-
// If any of the args was 0, result is 0 and no overflow occurs.
778-
if (UX == 0 || UY == 0)
769+
// Handle zero case
770+
if (X == 0 || Y == 0) {
771+
Result = 0;
779772
return false;
773+
}
780774

781-
// UX and UY are in [1, 2^n], where n is the number of digits.
782-
// Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
783-
// positive) divided by an argument compares to the other.
784-
if (IsNegative)
785-
return UX > (static_cast<U>(std::numeric_limits<T>::max()) + U(1)) / UY;
786-
else
787-
return UX > (static_cast<U>(std::numeric_limits<T>::max())) / UY;
775+
bool IsNegative = (X < 0) ^ (Y < 0);
776+
777+
// Safely compute absolute values
778+
const U AbsX = X < 0 ? (0 - static_cast<U>(X+1))+1 : static_cast<U>(X);
779+
const U AbsY = Y < 0 ? (0 - static_cast<U>(Y+1))+1 : static_cast<U>(Y);
780+
781+
// Overflow check before actual multiplication
782+
constexpr U MaxPositive = static_cast<U>(std::numeric_limits<T>::max());
783+
constexpr U MaxNegative = static_cast<U>(std::numeric_limits<T>::max()) + 1;
784+
785+
// Safe to multiply
786+
U AbsResult = AbsX * AbsY;
787+
Result = IsNegative ? static_cast<T>(0-AbsResult) : static_cast<T>(AbsResult);
788+
789+
// Handle INT_MIN * -1 overflow case explicitly
790+
if ((X == std::numeric_limits<T>::min() && Y == -1) ||
791+
(Y == std::numeric_limits<T>::min() && X == -1)) {
792+
return true; // overflow
793+
}
794+
795+
U Limit = IsNegative ? MaxNegative : MaxPositive;
796+
797+
if (AbsX > Limit / AbsY)
798+
return true;
799+
800+
return false;
788801
#endif
789802
}
790803

0 commit comments

Comments
 (0)