[Mlir-commits] [llvm] [mlir] mlir/Presburger/MPInt: move into LLVM/ADT (PR #94953)

Ramkumar Ramachandra llvmlistbot at llvm.org
Mon Jun 10 04:04:44 PDT 2024


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/94953

>From 8bc9f8d095b65b1cd3e5ace1e8fdf11c50f6aa8c Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Wed, 5 Jun 2024 14:53:16 +0100
Subject: [PATCH 1/2] mlir/Presburger/MPInt: move into LLVM/ADT

MPInt is an arbitrary-precision integer library that builds on top of
APInt, and has a fast-path when the number fits within 64 bits. It was
originally written for the Presburger library in MLIR, but seems useful
to the LLVM project in general, independently of the Presburger library
or MLIR. Hence, move it into LLVM/ADT.

This patch is part of a project to move the Presburger library into
LLVM.
---
 llvm/include/llvm/ADT/MPInt.h                 | 644 ++++++++++++++++++
 llvm/include/llvm/ADT/SlowMPInt.h             | 138 ++++
 llvm/lib/Support/CMakeLists.txt               |   2 +
 llvm/lib/Support/MPInt.cpp                    |  25 +
 llvm/lib/Support/SlowMPInt.cpp                | 276 ++++++++
 llvm/unittests/ADT/CMakeLists.txt             |   1 +
 llvm/unittests/ADT/MPIntTest.cpp              | 200 ++++++
 .../mlir/Analysis/Presburger/Fraction.h       |   4 +-
 .../Analysis/Presburger/IntegerRelation.h     |   3 +
 mlir/include/mlir/Analysis/Presburger/MPInt.h | 617 -----------------
 .../mlir/Analysis/Presburger/SlowMPInt.h      | 136 ----
 mlir/include/mlir/Analysis/Presburger/Utils.h |   3 +-
 mlir/include/mlir/Support/LLVM.h              |   2 +
 mlir/lib/Analysis/Presburger/CMakeLists.txt   |   2 -
 .../Analysis/Presburger/IntegerRelation.cpp   |   8 +-
 .../Analysis/Presburger/LinearTransform.cpp   |   2 +-
 mlir/lib/Analysis/Presburger/MPInt.cpp        |  38 --
 mlir/lib/Analysis/Presburger/Matrix.cpp       |   2 +-
 mlir/lib/Analysis/Presburger/PWMAFunction.cpp |   2 +-
 .../Presburger/PresburgerRelation.cpp         |   1 -
 mlir/lib/Analysis/Presburger/Simplex.cpp      |   4 +-
 mlir/lib/Analysis/Presburger/SlowMPInt.cpp    | 290 --------
 mlir/lib/Analysis/Presburger/Utils.cpp        |  11 +-
 .../Analysis/Presburger/CMakeLists.txt        |   1 -
 .../Analysis/Presburger/MPIntTest.cpp         | 200 ------
 mlir/unittests/Analysis/Presburger/Utils.h    |   2 +
 26 files changed, 1311 insertions(+), 1303 deletions(-)
 create mode 100644 llvm/include/llvm/ADT/MPInt.h
 create mode 100644 llvm/include/llvm/ADT/SlowMPInt.h
 create mode 100644 llvm/lib/Support/MPInt.cpp
 create mode 100644 llvm/lib/Support/SlowMPInt.cpp
 create mode 100644 llvm/unittests/ADT/MPIntTest.cpp
 delete mode 100644 mlir/include/mlir/Analysis/Presburger/MPInt.h
 delete mode 100644 mlir/include/mlir/Analysis/Presburger/SlowMPInt.h
 delete mode 100644 mlir/lib/Analysis/Presburger/MPInt.cpp
 delete mode 100644 mlir/lib/Analysis/Presburger/SlowMPInt.cpp
 delete mode 100644 mlir/unittests/Analysis/Presburger/MPIntTest.cpp

diff --git a/llvm/include/llvm/ADT/MPInt.h b/llvm/include/llvm/ADT/MPInt.h
new file mode 100644
index 0000000000000..dc387d7d0e5db
--- /dev/null
+++ b/llvm/include/llvm/ADT/MPInt.h
@@ -0,0 +1,644 @@
+//===- MPInt.h - MPInt Class ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a simple class to represent arbitrary precision signed integers.
+// Unlike APInt, one does not have to specify a fixed maximum size, and the
+// integer can take on any arbitrary values. This is optimized for small-values
+// by providing fast-paths for the cases when the value stored fits in 64-bits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_MPINT_H
+#define LLVM_ADT_MPINT_H
+
+#include "llvm/ADT/SlowMPInt.h"
+#include "llvm/Support/raw_ostream.h"
+#include <numeric>
+
+namespace llvm {
+namespace detail {
+/// ---------------------------------------------------------------------------
+/// Some helpers from MLIR/MathExtras.
+/// ---------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t ceilDiv(int64_t Numerator,
+                                             int64_t Denominator) {
+  assert(Denominator);
+  if (!Numerator)
+    return 0;
+  // C's integer division rounds towards 0.
+  int64_t X = (Denominator > 0) ? -1 : 1;
+  bool SameSign = (Numerator > 0) == (Denominator > 0);
+  return SameSign ? ((Numerator + X) / Denominator) + 1
+                  : -(-Numerator / Denominator);
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t floorDiv(int64_t Numerator,
+                                              int64_t Denominator) {
+  assert(Denominator);
+  if (!Numerator)
+    return 0;
+  // C's integer division rounds towards 0.
+  int64_t X = (Denominator > 0) ? -1 : 1;
+  bool SameSign = (Numerator > 0) == (Denominator > 0);
+  return SameSign ? Numerator / Denominator
+                  : -((-Numerator + X) / Denominator) - 1;
+}
+
+/// Returns the remainder of the Euclidean division of LHS by RHS. Result is
+/// always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t mod(int64_t Numerator,
+                                         int64_t Denominator) {
+  assert(Denominator >= 1);
+  return Numerator % Denominator < 0 ? Numerator % Denominator + Denominator
+                                     : Numerator % Denominator;
+}
+
+/// If builtin intrinsics for overflow-checked arithmetic are available,
+/// use them. Otherwise, call through to LLVM's overflow-checked arithmetic
+/// functionality. Those functions also have such macro-gated uses of intrinsics
+/// but they are not always_inlined, which is important for us to achieve
+/// high-performance; calling the functions directly would result in a slowdown
+/// of 1.15x.
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool addOverflow(int64_t X, int64_t Y,
+                                              int64_t &Result) {
+#if __has_builtin(__builtin_add_overflow)
+  return __builtin_add_overflow(X, Y, &Result);
+#else
+  return AddOverflow(x, y, result);
+#endif
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool subOverflow(int64_t X, int64_t Y,
+                                              int64_t &Result) {
+#if __has_builtin(__builtin_sub_overflow)
+  return __builtin_sub_overflow(X, Y, &Result);
+#else
+  return SubOverflow(x, y, result);
+#endif
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool mulOverflow(int64_t X, int64_t Y,
+                                              int64_t &Result) {
+#if __has_builtin(__builtin_mul_overflow)
+  return __builtin_mul_overflow(X, Y, &Result);
+#else
+  return MulOverflow(x, y, result);
+#endif
+}
+} // namespace detail
+
+/// This class provides support for multi-precision arithmetic.
+///
+/// Unlike APInt, this extends the precision as necessary to prevent overflows
+/// and supports operations between objects with differing internal precisions.
+///
+/// This is optimized for small-values by providing fast-paths for the cases
+/// when the value stored fits in 64-bits. We annotate all fastpaths by using
+/// the LLVM_LIKELY/LLVM_UNLIKELY annotations. Removing these would result in
+/// a 1.2x performance slowdown.
+///
+/// We always_inline all operations; removing these results in a 1.5x
+/// performance slowdown.
+///
+/// When holdsLarge is true, a SlowMPInt is held in the union. If it is false,
+/// the int64_t is held. Using std::variant instead would lead to significantly
+/// worse performance.
+class MPInt {
+private:
+  union {
+    int64_t ValSmall;
+    detail::SlowMPInt ValLarge;
+  };
+  unsigned HoldsLarge;
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE void initSmall(int64_t O) {
+    if (LLVM_UNLIKELY(isLarge()))
+      ValLarge.detail::SlowMPInt::~SlowMPInt();
+    ValSmall = O;
+    HoldsLarge = false;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE void initLarge(const detail::SlowMPInt &O) {
+    if (LLVM_LIKELY(isSmall())) {
+      // The data in memory could be in an arbitrary state, not necessarily
+      // corresponding to any valid state of ValLarge; we cannot call any member
+      // functions, e.g. the assignment operator on it, as they may access the
+      // invalid internal state. We instead construct a new object using
+      // placement new.
+      new (&ValLarge) detail::SlowMPInt(O);
+    } else {
+      // In this case, we need to use the assignment operator, because if we use
+      // placement-new as above we would lose track of allocated memory
+      // and leak it.
+      ValLarge = O;
+    }
+    HoldsLarge = true;
+  }
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit MPInt(const detail::SlowMPInt &Val)
+      : ValLarge(Val), HoldsLarge(true) {}
+  LLVM_ATTRIBUTE_ALWAYS_INLINE bool isSmall() const { return !HoldsLarge; }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE bool isLarge() const { return HoldsLarge; }
+  /// Get the stored value. For getSmall/Large,
+  /// the stored value should be small/large.
+  LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t getSmall() const {
+    assert(isSmall() &&
+           "getSmall should only be called when the value stored is small!");
+    return ValSmall;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t &getSmall() {
+    assert(isSmall() &&
+           "getSmall should only be called when the value stored is small!");
+    return ValSmall;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE const detail::SlowMPInt &getLarge() const {
+    assert(isLarge() &&
+           "getLarge should only be called when the value stored is large!");
+    return ValLarge;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE detail::SlowMPInt &getLarge() {
+    assert(isLarge() &&
+           "getLarge should only be called when the value stored is large!");
+    return ValLarge;
+  }
+  explicit operator detail::SlowMPInt() const {
+    if (isSmall())
+      return detail::SlowMPInt(getSmall());
+    return getLarge();
+  }
+
+public:
+  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit MPInt(int64_t Val)
+      : ValSmall(Val), HoldsLarge(false) {}
+  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt() : MPInt(0) {}
+  LLVM_ATTRIBUTE_ALWAYS_INLINE ~MPInt() {
+    if (LLVM_UNLIKELY(isLarge()))
+      ValLarge.detail::SlowMPInt::~SlowMPInt();
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt(const MPInt &O)
+      : ValSmall(O.ValSmall), HoldsLarge(false) {
+    if (LLVM_UNLIKELY(O.isLarge()))
+      initLarge(O.ValLarge);
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator=(const MPInt &O) {
+    if (LLVM_LIKELY(O.isSmall())) {
+      initSmall(O.ValSmall);
+      return *this;
+    }
+    initLarge(O.ValLarge);
+    return *this;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator=(int X) {
+    initSmall(X);
+    return *this;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit operator int64_t() const {
+    if (isSmall())
+      return getSmall();
+    return static_cast<int64_t>(getLarge());
+  }
+
+  bool operator==(const MPInt &O) const;
+  bool operator!=(const MPInt &O) const;
+  bool operator>(const MPInt &O) const;
+  bool operator<(const MPInt &O) const;
+  bool operator<=(const MPInt &O) const;
+  bool operator>=(const MPInt &O) const;
+  MPInt operator+(const MPInt &O) const;
+  MPInt operator-(const MPInt &O) const;
+  MPInt operator*(const MPInt &O) const;
+  MPInt operator/(const MPInt &O) const;
+  MPInt operator%(const MPInt &O) const;
+  MPInt &operator+=(const MPInt &O);
+  MPInt &operator-=(const MPInt &O);
+  MPInt &operator*=(const MPInt &O);
+  MPInt &operator/=(const MPInt &O);
+  MPInt &operator%=(const MPInt &O);
+  MPInt operator-() const;
+  MPInt &operator++();
+  MPInt &operator--();
+
+  // Divide by a number that is known to be positive.
+  // This is slightly more efficient because it saves an overflow check.
+  MPInt divByPositive(const MPInt &O) const;
+  MPInt &divByPositiveInPlace(const MPInt &O);
+
+  friend MPInt abs(const MPInt &X);
+  friend MPInt ceilDiv(const MPInt &LHS, const MPInt &RHS);
+  friend MPInt floorDiv(const MPInt &LHS, const MPInt &RHS);
+  // The operands must be non-negative for gcd.
+  friend MPInt gcd(const MPInt &A, const MPInt &B);
+  friend MPInt lcm(const MPInt &A, const MPInt &B);
+  friend MPInt mod(const MPInt &LHS, const MPInt &RHS);
+
+  /// ---------------------------------------------------------------------------
+  /// Convenience operator overloads for int64_t.
+  /// ---------------------------------------------------------------------------
+  friend MPInt &operator+=(MPInt &A, int64_t B);
+  friend MPInt &operator-=(MPInt &A, int64_t B);
+  friend MPInt &operator*=(MPInt &A, int64_t B);
+  friend MPInt &operator/=(MPInt &A, int64_t B);
+  friend MPInt &operator%=(MPInt &A, int64_t B);
+
+  friend bool operator==(const MPInt &A, int64_t B);
+  friend bool operator!=(const MPInt &A, int64_t B);
+  friend bool operator>(const MPInt &A, int64_t B);
+  friend bool operator<(const MPInt &A, int64_t B);
+  friend bool operator<=(const MPInt &A, int64_t B);
+  friend bool operator>=(const MPInt &A, int64_t B);
+  friend MPInt operator+(const MPInt &A, int64_t B);
+  friend MPInt operator-(const MPInt &A, int64_t B);
+  friend MPInt operator*(const MPInt &A, int64_t B);
+  friend MPInt operator/(const MPInt &A, int64_t B);
+  friend MPInt operator%(const MPInt &A, int64_t B);
+
+  friend bool operator==(int64_t A, const MPInt &B);
+  friend bool operator!=(int64_t A, const MPInt &B);
+  friend bool operator>(int64_t A, const MPInt &B);
+  friend bool operator<(int64_t A, const MPInt &B);
+  friend bool operator<=(int64_t A, const MPInt &B);
+  friend bool operator>=(int64_t A, const MPInt &B);
+  friend MPInt operator+(int64_t A, const MPInt &B);
+  friend MPInt operator-(int64_t A, const MPInt &B);
+  friend MPInt operator*(int64_t A, const MPInt &B);
+  friend MPInt operator/(int64_t A, const MPInt &B);
+  friend MPInt operator%(int64_t A, const MPInt &B);
+
+  friend hash_code hash_value(const MPInt &x); // NOLINT
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  raw_ostream &print(raw_ostream &OS) const;
+  LLVM_DUMP_METHOD void dump() const;
+#endif
+};
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+inline raw_ostream &operator<<(raw_ostream &OS, const MPInt &X) {
+  X.print(OS);
+  return OS;
+}
+#endif
+
+/// Redeclarations of friend declaration above to
+/// make it discoverable by lookups.
+hash_code hash_value(const MPInt &X); // NOLINT
+
+/// This just calls through to the operator int64_t, but it's useful when a
+/// function pointer is required. (Although this is marked inline, it is still
+/// possible to obtain and use a function pointer to this.)
+static inline int64_t int64FromMPInt(const MPInt &X) { return int64_t(X); }
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mpintFromInt64(int64_t X) {
+  return MPInt(X);
+}
+
+// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mod(const MPInt &LHS, const MPInt &RHS);
+
+namespace detail {
+// Division overflows only when trying to negate the minimal signed value.
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool divWouldOverflow(int64_t X, int64_t Y) {
+  return X == std::numeric_limits<int64_t>::min() && Y == -1;
+}
+} // namespace detail
+
+/// We define the operations here in the header to facilitate inlining.
+
+/// ---------------------------------------------------------------------------
+/// Comparison operators.
+/// ---------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator==(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() == O.getSmall();
+  return detail::SlowMPInt(*this) == detail::SlowMPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator!=(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() != O.getSmall();
+  return detail::SlowMPInt(*this) != detail::SlowMPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator>(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() > O.getSmall();
+  return detail::SlowMPInt(*this) > detail::SlowMPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator<(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() < O.getSmall();
+  return detail::SlowMPInt(*this) < detail::SlowMPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator<=(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() <= O.getSmall();
+  return detail::SlowMPInt(*this) <= detail::SlowMPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator>=(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() >= O.getSmall();
+  return detail::SlowMPInt(*this) >= detail::SlowMPInt(O);
+}
+
+/// ---------------------------------------------------------------------------
+/// Arithmetic operators.
+/// ---------------------------------------------------------------------------
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator+(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    MPInt Result;
+    bool Overflow =
+        detail::addOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(O));
+  }
+  return MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator-(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    MPInt Result;
+    bool Overflow =
+        detail::subOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(O));
+  }
+  return MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator*(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    MPInt Result;
+    bool Overflow =
+        detail::mulOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(O));
+  }
+  return MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(O));
+}
+
+// Division overflows only occur when negating the minimal possible value.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::divByPositive(const MPInt &O) const {
+  assert(O > 0);
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return MPInt(getSmall() / O.getSmall());
+  return MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator/(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    // Division overflows only occur when negating the minimal possible value.
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(getSmall(), O.getSmall())))
+      return -*this;
+    return MPInt(getSmall() / O.getSmall());
+  }
+  return MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt abs(const MPInt &X) {
+  return MPInt(X >= 0 ? X : -X);
+}
+// Division overflows only occur when negating the minimal possible value.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt ceilDiv(const MPInt &LHS, const MPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall())) {
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(LHS.getSmall(), RHS.getSmall())))
+      return -LHS;
+    return MPInt(detail::ceilDiv(LHS.getSmall(), RHS.getSmall()));
+  }
+  return MPInt(ceilDiv(detail::SlowMPInt(LHS), detail::SlowMPInt(RHS)));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt floorDiv(const MPInt &LHS,
+                                            const MPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall())) {
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(LHS.getSmall(), RHS.getSmall())))
+      return -LHS;
+    return MPInt(detail::floorDiv(LHS.getSmall(), RHS.getSmall()));
+  }
+  return MPInt(floorDiv(detail::SlowMPInt(LHS), detail::SlowMPInt(RHS)));
+}
+// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mod(const MPInt &LHS, const MPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall()))
+    return MPInt(detail::mod(LHS.getSmall(), RHS.getSmall()));
+  return MPInt(mod(detail::SlowMPInt(LHS), detail::SlowMPInt(RHS)));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt gcd(const MPInt &A, const MPInt &B) {
+  assert(A >= 0 && B >= 0 && "operands must be non-negative!");
+  if (LLVM_LIKELY(A.isSmall() && B.isSmall()))
+    return MPInt(std::gcd(A.getSmall(), B.getSmall()));
+  return MPInt(gcd(detail::SlowMPInt(A), detail::SlowMPInt(B)));
+}
+
+/// Returns the least common multiple of A and B.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt lcm(const MPInt &A, const MPInt &B) {
+  MPInt X = abs(A);
+  MPInt Y = abs(B);
+  return (X * Y) / gcd(X, Y);
+}
+
+/// This operation cannot overflow.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator%(const MPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return MPInt(getSmall() % O.getSmall());
+  return MPInt(detail::SlowMPInt(*this) % detail::SlowMPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator-() const {
+  if (LLVM_LIKELY(isSmall())) {
+    if (LLVM_LIKELY(getSmall() != std::numeric_limits<int64_t>::min()))
+      return MPInt(-getSmall());
+    return MPInt(-detail::SlowMPInt(*this));
+  }
+  return MPInt(-detail::SlowMPInt(*this));
+}
+
+/// ---------------------------------------------------------------------------
+/// Assignment operators, preincrement, predecrement.
+/// ---------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator+=(const MPInt &O) {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    int64_t Result = getSmall();
+    bool Overflow = detail::addOverflow(getSmall(), O.getSmall(), Result);
+    if (LLVM_LIKELY(!Overflow)) {
+      getSmall() = Result;
+      return *this;
+    }
+    // Note: this return is not strictly required but
+    // removing it leads to a performance regression.
+    return *this = MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(O));
+  }
+  return *this = MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator-=(const MPInt &O) {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    int64_t Result = getSmall();
+    bool Overflow = detail::subOverflow(getSmall(), O.getSmall(), Result);
+    if (LLVM_LIKELY(!Overflow)) {
+      getSmall() = Result;
+      return *this;
+    }
+    // Note: this return is not strictly required but
+    // removing it leads to a performance regression.
+    return *this = MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(O));
+  }
+  return *this = MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator*=(const MPInt &O) {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    int64_t Result = getSmall();
+    bool Overflow = detail::mulOverflow(getSmall(), O.getSmall(), Result);
+    if (LLVM_LIKELY(!Overflow)) {
+      getSmall() = Result;
+      return *this;
+    }
+    // Note: this return is not strictly required but
+    // removing it leads to a performance regression.
+    return *this = MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(O));
+  }
+  return *this = MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator/=(const MPInt &O) {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    // Division overflows only occur when negating the minimal possible value.
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(getSmall(), O.getSmall())))
+      return *this = -*this;
+    getSmall() /= O.getSmall();
+    return *this;
+  }
+  return *this = MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(O));
+}
+
+// Division overflows only occur when the divisor is -1.
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &
+MPInt::divByPositiveInPlace(const MPInt &O) {
+  assert(O > 0);
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    getSmall() /= O.getSmall();
+    return *this;
+  }
+  return *this = MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator%=(const MPInt &O) {
+  return *this = *this % O;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator++() { return *this += 1; }
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator--() { return *this -= 1; }
+
+/// ----------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ----------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator+=(MPInt &A, int64_t B) {
+  return A = A + B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator-=(MPInt &A, int64_t B) {
+  return A = A - B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator*=(MPInt &A, int64_t B) {
+  return A = A * B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator/=(MPInt &A, int64_t B) {
+  return A = A / B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator%=(MPInt &A, int64_t B) {
+  return A = A % B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator+(const MPInt &A, int64_t B) {
+  return A + MPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator-(const MPInt &A, int64_t B) {
+  return A - MPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator*(const MPInt &A, int64_t B) {
+  return A * MPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator/(const MPInt &A, int64_t B) {
+  return A / MPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator%(const MPInt &A, int64_t B) {
+  return A % MPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator+(int64_t A, const MPInt &B) {
+  return MPInt(A) + B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator-(int64_t A, const MPInt &B) {
+  return MPInt(A) - B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator*(int64_t A, const MPInt &B) {
+  return MPInt(A) * B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator/(int64_t A, const MPInt &B) {
+  return MPInt(A) / B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator%(int64_t A, const MPInt &B) {
+  return MPInt(A) % B;
+}
+
+/// We provide special implementations of the comparison operators rather than
+/// calling through as above, as this would result in a 1.2x slowdown.
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator==(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() == B;
+  return A.getLarge() == B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() != B;
+  return A.getLarge() != B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() > B;
+  return A.getLarge() > B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() < B;
+  return A.getLarge() < B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() <= B;
+  return A.getLarge() <= B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(const MPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() >= B;
+  return A.getLarge() >= B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator==(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A == B.getSmall();
+  return A == B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A != B.getSmall();
+  return A != B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A > B.getSmall();
+  return A > B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A < B.getSmall();
+  return A < B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A <= B.getSmall();
+  return A <= B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(int64_t A, const MPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A >= B.getSmall();
+  return A >= B.getLarge();
+}
+} // namespace llvm
+
+#endif // LLVM_ADT_MPINT_H
diff --git a/llvm/include/llvm/ADT/SlowMPInt.h b/llvm/include/llvm/ADT/SlowMPInt.h
new file mode 100644
index 0000000000000..b2e593853ce44
--- /dev/null
+++ b/llvm/include/llvm/ADT/SlowMPInt.h
@@ -0,0 +1,138 @@
+//===- SlowMPInt.h - SlowMPInt Class ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a simple class to represent arbitrary precision signed integers.
+// Unlike APInt, one does not have to specify a fixed maximum size, and the
+// integer can take on any arbitrary values.
+//
+// This class is to be used as a fallback slow path for the MPInt class, and
+// is not intended to be used directly.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SLOWMPINT_H
+#define LLVM_ADT_SLOWMPINT_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace detail {
+/// A simple class providing multi-precision arithmetic. Internally, it stores
+/// an APInt, whose width is doubled whenever an overflow occurs at a certain
+/// width. The default constructor sets the initial width to 64. SlowMPInt is
+/// primarily intended to be used as a slow fallback path for the upcoming MPInt
+/// class.
+class SlowMPInt {
+private:
+  APInt Val;
+
+public:
+  explicit SlowMPInt(int64_t Val);
+  SlowMPInt();
+  explicit SlowMPInt(const APInt &Val);
+  SlowMPInt &operator=(int64_t Val);
+  explicit operator int64_t() const;
+  SlowMPInt operator-() const;
+  bool operator==(const SlowMPInt &O) const;
+  bool operator!=(const SlowMPInt &O) const;
+  bool operator>(const SlowMPInt &O) const;
+  bool operator<(const SlowMPInt &O) const;
+  bool operator<=(const SlowMPInt &O) const;
+  bool operator>=(const SlowMPInt &O) const;
+  SlowMPInt operator+(const SlowMPInt &O) const;
+  SlowMPInt operator-(const SlowMPInt &O) const;
+  SlowMPInt operator*(const SlowMPInt &O) const;
+  SlowMPInt operator/(const SlowMPInt &O) const;
+  SlowMPInt operator%(const SlowMPInt &O) const;
+  SlowMPInt &operator+=(const SlowMPInt &O);
+  SlowMPInt &operator-=(const SlowMPInt &O);
+  SlowMPInt &operator*=(const SlowMPInt &O);
+  SlowMPInt &operator/=(const SlowMPInt &O);
+  SlowMPInt &operator%=(const SlowMPInt &O);
+
+  SlowMPInt &operator++();
+  SlowMPInt &operator--();
+
+  friend SlowMPInt abs(const SlowMPInt &X);
+  friend SlowMPInt ceilDiv(const SlowMPInt &LHS, const SlowMPInt &RHS);
+  friend SlowMPInt floorDiv(const SlowMPInt &LHS, const SlowMPInt &RHS);
+  /// The operands must be non-negative for gcd.
+  friend SlowMPInt gcd(const SlowMPInt &A, const SlowMPInt &B);
+
+  /// Overload to compute a hash_code for a SlowMPInt value.
+  friend hash_code hash_value(const SlowMPInt &X); // NOLINT
+
+  unsigned getBitWidth() const { return Val.getBitWidth(); }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  void print(raw_ostream &OS) const;
+  LLVM_DUMP_METHOD void dump() const;
+#endif
+};
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+inline raw_ostream &operator<<(raw_ostream &OS, const SlowMPInt &X) {
+  X.print(OS);
+  return OS;
+}
+#endif
+
+/// Returns the remainder of dividing LHS by RHS.
+///
+/// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+SlowMPInt mod(const SlowMPInt &LHS, const SlowMPInt &RHS);
+
+/// Returns the least common multiple of A and B.
+SlowMPInt lcm(const SlowMPInt &A, const SlowMPInt &B);
+
+/// Redeclarations of friend declarations above to
+/// make it discoverable by lookups.
+SlowMPInt abs(const SlowMPInt &X);
+SlowMPInt ceilDiv(const SlowMPInt &LHS, const SlowMPInt &RHS);
+SlowMPInt floorDiv(const SlowMPInt &LHS, const SlowMPInt &RHS);
+SlowMPInt gcd(const SlowMPInt &A, const SlowMPInt &B);
+hash_code hash_value(const SlowMPInt &X); // NOLINT
+
+/// ---------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ---------------------------------------------------------------------------
+SlowMPInt &operator+=(SlowMPInt &A, int64_t B);
+SlowMPInt &operator-=(SlowMPInt &A, int64_t B);
+SlowMPInt &operator*=(SlowMPInt &A, int64_t B);
+SlowMPInt &operator/=(SlowMPInt &A, int64_t B);
+SlowMPInt &operator%=(SlowMPInt &A, int64_t B);
+
+bool operator==(const SlowMPInt &A, int64_t B);
+bool operator!=(const SlowMPInt &A, int64_t B);
+bool operator>(const SlowMPInt &A, int64_t B);
+bool operator<(const SlowMPInt &A, int64_t B);
+bool operator<=(const SlowMPInt &A, int64_t B);
+bool operator>=(const SlowMPInt &A, int64_t B);
+SlowMPInt operator+(const SlowMPInt &A, int64_t B);
+SlowMPInt operator-(const SlowMPInt &A, int64_t B);
+SlowMPInt operator*(const SlowMPInt &A, int64_t B);
+SlowMPInt operator/(const SlowMPInt &A, int64_t B);
+SlowMPInt operator%(const SlowMPInt &A, int64_t B);
+
+bool operator==(int64_t A, const SlowMPInt &B);
+bool operator!=(int64_t A, const SlowMPInt &B);
+bool operator>(int64_t A, const SlowMPInt &B);
+bool operator<(int64_t A, const SlowMPInt &B);
+bool operator<=(int64_t A, const SlowMPInt &B);
+bool operator>=(int64_t A, const SlowMPInt &B);
+SlowMPInt operator+(int64_t A, const SlowMPInt &B);
+SlowMPInt operator-(int64_t A, const SlowMPInt &B);
+SlowMPInt operator*(int64_t A, const SlowMPInt &B);
+SlowMPInt operator/(int64_t A, const SlowMPInt &B);
+SlowMPInt operator%(int64_t A, const SlowMPInt &B);
+} // namespace detail
+} // namespace llvm
+
+#endif // LLVM_ADT_SLOWMPINT_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 5df36f811efe9..2c854cc7ffed2 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -204,6 +204,7 @@ add_llvm_component_library(LLVMSupport
   MemoryBuffer.cpp
   MemoryBufferRef.cpp
   MD5.cpp
+  MPInt.cpp
   MSP430Attributes.cpp
   MSP430AttributeParser.cpp
   NativeFormatting.cpp
@@ -223,6 +224,7 @@ add_llvm_component_library(LLVMSupport
   SHA1.cpp
   SHA256.cpp
   Signposts.cpp
+  SlowMPInt.cpp
   SmallPtrSet.cpp
   SmallVector.cpp
   SourceMgr.cpp
diff --git a/llvm/lib/Support/MPInt.cpp b/llvm/lib/Support/MPInt.cpp
new file mode 100644
index 0000000000000..0695cc392708c
--- /dev/null
+++ b/llvm/lib/Support/MPInt.cpp
@@ -0,0 +1,25 @@
+#include "llvm/ADT/MPInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+hash_code llvm::hash_value(const MPInt &X) {
+  if (X.isSmall())
+    return llvm::hash_value(X.getSmall());
+  return detail::hash_value(X.getLarge());
+}
+
+/// ---------------------------------------------------------------------------
+/// Printing.
+/// ---------------------------------------------------------------------------
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+raw_ostream &MPInt::print(raw_ostream &OS) const {
+  if (isSmall())
+    return OS << ValSmall;
+  return OS << ValLarge;
+}
+
+void MPInt::dump() const { print(dbgs()); }
+#endif
diff --git a/llvm/lib/Support/SlowMPInt.cpp b/llvm/lib/Support/SlowMPInt.cpp
new file mode 100644
index 0000000000000..e88eb6b596f63
--- /dev/null
+++ b/llvm/lib/Support/SlowMPInt.cpp
@@ -0,0 +1,276 @@
+//===- SlowMPInt.cpp - SlowMPInt Class ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SlowMPInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace detail;
+
+SlowMPInt::SlowMPInt(int64_t Val) : Val(64, Val, /*isSigned=*/true) {}
+SlowMPInt::SlowMPInt() : SlowMPInt(0) {}
+SlowMPInt::SlowMPInt(const APInt &Val) : Val(Val) {}
+SlowMPInt &SlowMPInt::operator=(int64_t Val) { return *this = SlowMPInt(Val); }
+SlowMPInt::operator int64_t() const { return Val.getSExtValue(); }
+
+hash_code detail::hash_value(const SlowMPInt &X) { return hash_value(X.Val); }
+
+/// ---------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ---------------------------------------------------------------------------
+SlowMPInt &detail::operator+=(SlowMPInt &A, int64_t B) {
+  return A += SlowMPInt(B);
+}
+SlowMPInt &detail::operator-=(SlowMPInt &A, int64_t B) {
+  return A -= SlowMPInt(B);
+}
+SlowMPInt &detail::operator*=(SlowMPInt &A, int64_t B) {
+  return A *= SlowMPInt(B);
+}
+SlowMPInt &detail::operator/=(SlowMPInt &A, int64_t B) {
+  return A /= SlowMPInt(B);
+}
+SlowMPInt &detail::operator%=(SlowMPInt &A, int64_t B) {
+  return A %= SlowMPInt(B);
+}
+
+bool detail::operator==(const SlowMPInt &A, int64_t B) {
+  return A == SlowMPInt(B);
+}
+bool detail::operator!=(const SlowMPInt &A, int64_t B) {
+  return A != SlowMPInt(B);
+}
+bool detail::operator>(const SlowMPInt &A, int64_t B) {
+  return A > SlowMPInt(B);
+}
+bool detail::operator<(const SlowMPInt &A, int64_t B) {
+  return A < SlowMPInt(B);
+}
+bool detail::operator<=(const SlowMPInt &A, int64_t B) {
+  return A <= SlowMPInt(B);
+}
+bool detail::operator>=(const SlowMPInt &A, int64_t B) {
+  return A >= SlowMPInt(B);
+}
+SlowMPInt detail::operator+(const SlowMPInt &A, int64_t B) {
+  return A + SlowMPInt(B);
+}
+SlowMPInt detail::operator-(const SlowMPInt &A, int64_t B) {
+  return A - SlowMPInt(B);
+}
+SlowMPInt detail::operator*(const SlowMPInt &A, int64_t B) {
+  return A * SlowMPInt(B);
+}
+SlowMPInt detail::operator/(const SlowMPInt &A, int64_t B) {
+  return A / SlowMPInt(B);
+}
+SlowMPInt detail::operator%(const SlowMPInt &A, int64_t B) {
+  return A % SlowMPInt(B);
+}
+
+bool detail::operator==(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) == B;
+}
+bool detail::operator!=(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) != B;
+}
+bool detail::operator>(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) > B;
+}
+bool detail::operator<(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) < B;
+}
+bool detail::operator<=(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) <= B;
+}
+bool detail::operator>=(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) >= B;
+}
+SlowMPInt detail::operator+(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) + B;
+}
+SlowMPInt detail::operator-(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) - B;
+}
+SlowMPInt detail::operator*(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) * B;
+}
+SlowMPInt detail::operator/(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) / B;
+}
+SlowMPInt detail::operator%(int64_t A, const SlowMPInt &B) {
+  return SlowMPInt(A) % B;
+}
+
+static unsigned getMaxWidth(const APInt &A, const APInt &B) {
+  return std::max(A.getBitWidth(), B.getBitWidth());
+}
+
+/// ---------------------------------------------------------------------------
+/// Comparison operators.
+/// ---------------------------------------------------------------------------
+
+// TODO: consider instead making APInt::compare available and using that.
+bool SlowMPInt::operator==(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width) == O.Val.sext(Width);
+}
+bool SlowMPInt::operator!=(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width) != O.Val.sext(Width);
+}
+bool SlowMPInt::operator>(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).sgt(O.Val.sext(Width));
+}
+bool SlowMPInt::operator<(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).slt(O.Val.sext(Width));
+}
+bool SlowMPInt::operator<=(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).sle(O.Val.sext(Width));
+}
+bool SlowMPInt::operator>=(const SlowMPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).sge(O.Val.sext(Width));
+}
+
+/// ---------------------------------------------------------------------------
+/// Arithmetic operators.
+/// ---------------------------------------------------------------------------
+
+/// Bring a and b to have the same width and then call op(a, b, overflow).
+/// If the overflow bit becomes set, resize a and b to double the width and
+/// call op(a, b, overflow), returning its result. The operation with double
+/// widths should not also overflow.
+APInt runOpWithExpandOnOverflow(
+    const APInt &A, const APInt &B,
+    function_ref<APInt(const APInt &, const APInt &, bool &Overflow)> Op) {
+  bool Overflow;
+  unsigned Width = getMaxWidth(A, B);
+  APInt Ret = Op(A.sext(Width), B.sext(Width), Overflow);
+  if (!Overflow)
+    return Ret;
+
+  Width *= 2;
+  Ret = Op(A.sext(Width), B.sext(Width), Overflow);
+  assert(!Overflow && "double width should be sufficient to avoid overflow!");
+  return Ret;
+}
+
+SlowMPInt SlowMPInt::operator+(const SlowMPInt &O) const {
+  return SlowMPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sadd_ov)));
+}
+SlowMPInt SlowMPInt::operator-(const SlowMPInt &O) const {
+  return SlowMPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::ssub_ov)));
+}
+SlowMPInt SlowMPInt::operator*(const SlowMPInt &O) const {
+  return SlowMPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::smul_ov)));
+}
+SlowMPInt SlowMPInt::operator/(const SlowMPInt &O) const {
+  return SlowMPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sdiv_ov)));
+}
+SlowMPInt detail::abs(const SlowMPInt &X) { return X >= 0 ? X : -X; }
+SlowMPInt detail::ceilDiv(const SlowMPInt &LHS, const SlowMPInt &RHS) {
+  if (RHS == -1)
+    return -LHS;
+  unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
+  return SlowMPInt(APIntOps::RoundingSDiv(
+      LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::UP));
+}
+SlowMPInt detail::floorDiv(const SlowMPInt &LHS, const SlowMPInt &RHS) {
+  if (RHS == -1)
+    return -LHS;
+  unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
+  return SlowMPInt(APIntOps::RoundingSDiv(
+      LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::DOWN));
+}
+// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+SlowMPInt detail::mod(const SlowMPInt &LHS, const SlowMPInt &RHS) {
+  assert(RHS >= 1 && "mod is only supported for positive divisors!");
+  return LHS % RHS < 0 ? LHS % RHS + RHS : LHS % RHS;
+}
+
+SlowMPInt detail::gcd(const SlowMPInt &A, const SlowMPInt &B) {
+  assert(A >= 0 && B >= 0 && "operands must be non-negative!");
+  unsigned Width = getMaxWidth(A.Val, B.Val);
+  return SlowMPInt(
+      APIntOps::GreatestCommonDivisor(A.Val.sext(Width), B.Val.sext(Width)));
+}
+
+/// Returns the least common multiple of A and B.
+SlowMPInt detail::lcm(const SlowMPInt &A, const SlowMPInt &B) {
+  SlowMPInt X = abs(A);
+  SlowMPInt Y = abs(B);
+  return (X * Y) / gcd(X, Y);
+}
+
+/// This operation cannot overflow.
+SlowMPInt SlowMPInt::operator%(const SlowMPInt &O) const {
+  unsigned Width = std::max(Val.getBitWidth(), O.Val.getBitWidth());
+  return SlowMPInt(Val.sext(Width).srem(O.Val.sext(Width)));
+}
+
+SlowMPInt SlowMPInt::operator-() const {
+  if (Val.isMinSignedValue()) {
+    /// Overflow only occurs when the value is the minimum possible value.
+    APInt Ret = Val.sext(2 * Val.getBitWidth());
+    return SlowMPInt(-Ret);
+  }
+  return SlowMPInt(-Val);
+}
+
+/// ---------------------------------------------------------------------------
+/// Assignment operators, preincrement, predecrement.
+/// ---------------------------------------------------------------------------
+SlowMPInt &SlowMPInt::operator+=(const SlowMPInt &O) {
+  *this = *this + O;
+  return *this;
+}
+SlowMPInt &SlowMPInt::operator-=(const SlowMPInt &O) {
+  *this = *this - O;
+  return *this;
+}
+SlowMPInt &SlowMPInt::operator*=(const SlowMPInt &O) {
+  *this = *this * O;
+  return *this;
+}
+SlowMPInt &SlowMPInt::operator/=(const SlowMPInt &O) {
+  *this = *this / O;
+  return *this;
+}
+SlowMPInt &SlowMPInt::operator%=(const SlowMPInt &O) {
+  *this = *this % O;
+  return *this;
+}
+SlowMPInt &SlowMPInt::operator++() {
+  *this += 1;
+  return *this;
+}
+
+SlowMPInt &SlowMPInt::operator--() {
+  *this -= 1;
+  return *this;
+}
+
+/// ---------------------------------------------------------------------------
+/// Printing.
+/// ---------------------------------------------------------------------------
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+void SlowMPInt::print(raw_ostream &OS) const { OS << Val; }
+
+void SlowMPInt::dump() const { print(dbgs()); }
+#endif
diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index 17c5c9d1c59ce..786ec7a206677 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -53,6 +53,7 @@ add_llvm_unittest(ADTTests
   MappedIteratorTest.cpp
   MapVectorTest.cpp
   MoveOnly.cpp
+  MPIntTest.cpp
   PackedVectorTest.cpp
   PagedVectorTest.cpp
   PointerEmbeddedIntTest.cpp
diff --git a/llvm/unittests/ADT/MPIntTest.cpp b/llvm/unittests/ADT/MPIntTest.cpp
new file mode 100644
index 0000000000000..a70e3c2a1b41c
--- /dev/null
+++ b/llvm/unittests/ADT/MPIntTest.cpp
@@ -0,0 +1,200 @@
+//===- MPIntTest.cpp - Tests for MPInt ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/MPInt.h"
+#include "llvm/ADT/SlowMPInt.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+// googletest boilerplate to run the same tests with both MPInt and SlowMPInt.
+template <typename> class IntTest : public testing::Test {};
+using TypeList = testing::Types<MPInt, detail::SlowMPInt>;
+
+// This is for pretty-printing the test name with the name of the class in use.
+class TypeNames {
+public:
+  template <typename T>
+  static std::string GetName(int) { // NOLINT; gtest mandates this name.
+    if (std::is_same<T, MPInt>())
+      return "MPInt";
+    if (std::is_same<T, detail::SlowMPInt>())
+      return "SlowMPInt";
+    llvm_unreachable("Unknown class!");
+  }
+};
+TYPED_TEST_SUITE(IntTest, TypeList, TypeNames);
+
+TYPED_TEST(IntTest, ops) {
+  TypeParam Two(2), Five(5), Seven(7), Ten(10);
+  EXPECT_EQ(Five + Five, Ten);
+  EXPECT_EQ(Five * Five, 2 * Ten + Five);
+  EXPECT_EQ(Five * Five, 3 * Ten - Five);
+  EXPECT_EQ(Five * Two, Ten);
+  EXPECT_EQ(Five / Two, Two);
+  EXPECT_EQ(Five % Two, Two / Two);
+
+  EXPECT_EQ(-Ten % Seven, -10 % 7);
+  EXPECT_EQ(Ten % -Seven, 10 % -7);
+  EXPECT_EQ(-Ten % -Seven, -10 % -7);
+  EXPECT_EQ(Ten % Seven, 10 % 7);
+
+  EXPECT_EQ(-Ten / Seven, -10 / 7);
+  EXPECT_EQ(Ten / -Seven, 10 / -7);
+  EXPECT_EQ(-Ten / -Seven, -10 / -7);
+  EXPECT_EQ(Ten / Seven, 10 / 7);
+
+  TypeParam X = Ten;
+  X += Five;
+  EXPECT_EQ(X, 15);
+  X *= Two;
+  EXPECT_EQ(X, 30);
+  X /= Seven;
+  EXPECT_EQ(X, 4);
+  X -= Two * 10;
+  EXPECT_EQ(X, -16);
+  X *= 2 * Two;
+  EXPECT_EQ(X, -64);
+  X /= Two / -2;
+  EXPECT_EQ(X, 64);
+
+  EXPECT_LE(Ten, Ten);
+  EXPECT_GE(Ten, Ten);
+  EXPECT_EQ(Ten, Ten);
+  EXPECT_FALSE(Ten != Ten);
+  EXPECT_FALSE(Ten < Ten);
+  EXPECT_FALSE(Ten > Ten);
+  EXPECT_LT(Five, Ten);
+  EXPECT_GT(Ten, Five);
+}
+
+TYPED_TEST(IntTest, ops64Overloads) {
+  TypeParam Two(2), Five(5), Seven(7), Ten(10);
+  EXPECT_EQ(Five + 5, Ten);
+  EXPECT_EQ(Five + 5, 5 + Five);
+  EXPECT_EQ(Five * 5, 2 * Ten + 5);
+  EXPECT_EQ(Five * 5, 3 * Ten - 5);
+  EXPECT_EQ(Five * Two, Ten);
+  EXPECT_EQ(5 / Two, 2);
+  EXPECT_EQ(Five / 2, 2);
+  EXPECT_EQ(2 % Two, 0);
+  EXPECT_EQ(2 - Two, 0);
+  EXPECT_EQ(2 % Two, Two % 2);
+
+  TypeParam X = Ten;
+  X += 5;
+  EXPECT_EQ(X, 15);
+  X *= 2;
+  EXPECT_EQ(X, 30);
+  X /= 7;
+  EXPECT_EQ(X, 4);
+  X -= 20;
+  EXPECT_EQ(X, -16);
+  X *= 4;
+  EXPECT_EQ(X, -64);
+  X /= -1;
+  EXPECT_EQ(X, 64);
+
+  EXPECT_LE(Ten, 10);
+  EXPECT_GE(Ten, 10);
+  EXPECT_EQ(Ten, 10);
+  EXPECT_FALSE(Ten != 10);
+  EXPECT_FALSE(Ten < 10);
+  EXPECT_FALSE(Ten > 10);
+  EXPECT_LT(Five, 10);
+  EXPECT_GT(Ten, 5);
+
+  EXPECT_LE(10, Ten);
+  EXPECT_GE(10, Ten);
+  EXPECT_EQ(10, Ten);
+  EXPECT_FALSE(10 != Ten);
+  EXPECT_FALSE(10 < Ten);
+  EXPECT_FALSE(10 > Ten);
+  EXPECT_LT(5, Ten);
+  EXPECT_GT(10, Five);
+}
+
+TYPED_TEST(IntTest, overflows) {
+  TypeParam X(1ll << 60);
+  EXPECT_EQ((X * X - X * X * X * X) / (X * X * X), 1 - (1ll << 60));
+  TypeParam Y(1ll << 62);
+  EXPECT_EQ((Y + Y + Y + Y + Y + Y) / Y, 6);
+  EXPECT_EQ(-(2 * (-Y)), 2 * Y); // -(-2^63) overflow.
+  X *= X;
+  EXPECT_EQ(X, (Y * Y) / 16);
+  Y += Y;
+  Y += Y;
+  Y += Y;
+  Y /= 8;
+  EXPECT_EQ(Y, 1ll << 62);
+
+  TypeParam Min(std::numeric_limits<int64_t>::min());
+  TypeParam One(1);
+  EXPECT_EQ(floorDiv(Min, -One), -Min);
+  EXPECT_EQ(ceilDiv(Min, -One), -Min);
+  EXPECT_EQ(abs(Min), -Min);
+
+  TypeParam Z = Min;
+  Z /= -1;
+  EXPECT_EQ(Z, -Min);
+  TypeParam W(Min);
+  --W;
+  EXPECT_EQ(W, TypeParam(Min) - 1);
+  TypeParam U(Min);
+  U -= 1;
+  EXPECT_EQ(U, W);
+
+  TypeParam Max(std::numeric_limits<int64_t>::max());
+  TypeParam V = Max;
+  ++V;
+  EXPECT_EQ(V, Max + 1);
+  TypeParam T = Max;
+  T += 1;
+  EXPECT_EQ(T, V);
+}
+
+TYPED_TEST(IntTest, floorCeilModAbsLcmGcd) {
+  TypeParam X(1ll << 50), One(1), Two(2), Three(3);
+
+  // Run on small values and large values.
+  for (const TypeParam &Y : {X, X * X}) {
+    EXPECT_EQ(floorDiv(3 * Y, Three), Y);
+    EXPECT_EQ(ceilDiv(3 * Y, Three), Y);
+    EXPECT_EQ(floorDiv(3 * Y - 1, Three), Y - 1);
+    EXPECT_EQ(ceilDiv(3 * Y - 1, Three), Y);
+    EXPECT_EQ(floorDiv(3 * Y - 2, Three), Y - 1);
+    EXPECT_EQ(ceilDiv(3 * Y - 2, Three), Y);
+
+    EXPECT_EQ(mod(3 * Y, Three), 0);
+    EXPECT_EQ(mod(3 * Y + 1, Three), One);
+    EXPECT_EQ(mod(3 * Y + 2, Three), Two);
+
+    EXPECT_EQ(floorDiv(3 * Y, Y), 3);
+    EXPECT_EQ(ceilDiv(3 * Y, Y), 3);
+    EXPECT_EQ(floorDiv(3 * Y - 1, Y), 2);
+    EXPECT_EQ(ceilDiv(3 * Y - 1, Y), 3);
+    EXPECT_EQ(floorDiv(3 * Y - 2, Y), 2);
+    EXPECT_EQ(ceilDiv(3 * Y - 2, Y), 3);
+
+    EXPECT_EQ(mod(3 * Y, Y), 0);
+    EXPECT_EQ(mod(3 * Y + 1, Y), 1);
+    EXPECT_EQ(mod(3 * Y + 2, Y), 2);
+
+    EXPECT_EQ(abs(Y), Y);
+    EXPECT_EQ(abs(-Y), Y);
+
+    EXPECT_EQ(gcd(3 * Y, Three), Three);
+    EXPECT_EQ(lcm(Y, Three), 3 * Y);
+    EXPECT_EQ(gcd(2 * Y, 3 * Y), Y);
+    EXPECT_EQ(lcm(2 * Y, 3 * Y), 6 * Y);
+    EXPECT_EQ(gcd(15 * Y, 6 * Y), 3 * Y);
+    EXPECT_EQ(lcm(15 * Y, 6 * Y), 30 * Y);
+  }
+}
+} // namespace
diff --git a/mlir/include/mlir/Analysis/Presburger/Fraction.h b/mlir/include/mlir/Analysis/Presburger/Fraction.h
index c07bb767f50bf..24dea4fc3756e 100644
--- a/mlir/include/mlir/Analysis/Presburger/Fraction.h
+++ b/mlir/include/mlir/Analysis/Presburger/Fraction.h
@@ -14,11 +14,11 @@
 #ifndef MLIR_ANALYSIS_PRESBURGER_FRACTION_H
 #define MLIR_ANALYSIS_PRESBURGER_FRACTION_H
 
-#include "mlir/Analysis/Presburger/MPInt.h"
-#include "mlir/Support/MathExtras.h"
+#include "llvm/ADT/MPInt.h"
 
 namespace mlir {
 namespace presburger {
+using llvm::MPInt;
 
 /// A class to represent fractions. The sign of the fraction is represented
 /// in the sign of the numerator; the denominator is always positive.
diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
index 163f365c623d7..cf2e7692041a8 100644
--- a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
@@ -20,10 +20,13 @@
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "mlir/Support/LogicalResult.h"
+#include "llvm/ADT/MPInt.h"
 #include <optional>
 
 namespace mlir {
 namespace presburger {
+using llvm::int64FromMPInt;
+using llvm::MPInt;
 
 class IntegerRelation;
 class IntegerPolyhedron;
diff --git a/mlir/include/mlir/Analysis/Presburger/MPInt.h b/mlir/include/mlir/Analysis/Presburger/MPInt.h
deleted file mode 100644
index 12ab0598d10d9..0000000000000
--- a/mlir/include/mlir/Analysis/Presburger/MPInt.h
+++ /dev/null
@@ -1,617 +0,0 @@
-//===- MPInt.h - MLIR MPInt Class -------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a simple class to represent arbitrary precision signed integers.
-// Unlike APInt, one does not have to specify a fixed maximum size, and the
-// integer can take on any arbitrary values. This is optimized for small-values
-// by providing fast-paths for the cases when the value stored fits in 64-bits.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_ANALYSIS_PRESBURGER_MPINT_H
-#define MLIR_ANALYSIS_PRESBURGER_MPINT_H
-
-#include "mlir/Analysis/Presburger/SlowMPInt.h"
-#include "mlir/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <numeric>
-
-namespace mlir {
-namespace presburger {
-
-/// Redefine these functions, which operate on 64-bit ints, to also be part of
-/// the mlir::presburger namespace. This is useful because this file defines
-/// identically-named functions that operate on MPInts, which would otherwie
-/// become the only candidates of overload resolution when calling e.g. ceilDiv
-/// from the mlir::presburger namespace. So to access the 64-bit overloads, an
-/// explict call to mlir::ceilDiv would be required. These using declarations
-/// allow overload resolution to transparently call the right function.
-using ::mlir::ceilDiv;
-using ::mlir::floorDiv;
-using ::mlir::mod;
-
-namespace detail {
-/// If builtin intrinsics for overflow-checked arithmetic are available,
-/// use them. Otherwise, call through to LLVM's overflow-checked arithmetic
-/// functionality. Those functions also have such macro-gated uses of intrinsics
-/// but they are not always_inlined, which is important for us to achieve
-/// high-performance; calling the functions directly would result in a slowdown
-/// of 1.15x.
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool addOverflow(int64_t x, int64_t y,
-                                              int64_t &result) {
-#if __has_builtin(__builtin_add_overflow)
-  return __builtin_add_overflow(x, y, &result);
-#else
-  return llvm::AddOverflow(x, y, result);
-#endif
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool subOverflow(int64_t x, int64_t y,
-                                              int64_t &result) {
-#if __has_builtin(__builtin_sub_overflow)
-  return __builtin_sub_overflow(x, y, &result);
-#else
-  return llvm::SubOverflow(x, y, result);
-#endif
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool mulOverflow(int64_t x, int64_t y,
-                                              int64_t &result) {
-#if __has_builtin(__builtin_mul_overflow)
-  return __builtin_mul_overflow(x, y, &result);
-#else
-  return llvm::MulOverflow(x, y, result);
-#endif
-}
-} // namespace detail
-
-/// This class provides support for multi-precision arithmetic.
-///
-/// Unlike APInt, this extends the precision as necessary to prevent overflows
-/// and supports operations between objects with differing internal precisions.
-///
-/// This is optimized for small-values by providing fast-paths for the cases
-/// when the value stored fits in 64-bits. We annotate all fastpaths by using
-/// the LLVM_LIKELY/LLVM_UNLIKELY annotations. Removing these would result in
-/// a 1.2x performance slowdown.
-///
-/// We always_inline all operations; removing these results in a 1.5x
-/// performance slowdown.
-///
-/// When holdsLarge is true, a SlowMPInt is held in the union. If it is false,
-/// the int64_t is held. Using std::variant instead would lead to significantly
-/// worse performance.
-class MPInt {
-private:
-  union {
-    int64_t valSmall;
-    detail::SlowMPInt valLarge;
-  };
-  unsigned holdsLarge;
-
-  LLVM_ATTRIBUTE_ALWAYS_INLINE void initSmall(int64_t o) {
-    if (LLVM_UNLIKELY(isLarge()))
-      valLarge.detail::SlowMPInt::~SlowMPInt();
-    valSmall = o;
-    holdsLarge = false;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE void initLarge(const detail::SlowMPInt &o) {
-    if (LLVM_LIKELY(isSmall())) {
-      // The data in memory could be in an arbitrary state, not necessarily
-      // corresponding to any valid state of valLarge; we cannot call any member
-      // functions, e.g. the assignment operator on it, as they may access the
-      // invalid internal state. We instead construct a new object using
-      // placement new.
-      new (&valLarge) detail::SlowMPInt(o);
-    } else {
-      // In this case, we need to use the assignment operator, because if we use
-      // placement-new as above we would lose track of allocated memory
-      // and leak it.
-      valLarge = o;
-    }
-    holdsLarge = true;
-  }
-
-  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit MPInt(const detail::SlowMPInt &val)
-      : valLarge(val), holdsLarge(true) {}
-  LLVM_ATTRIBUTE_ALWAYS_INLINE bool isSmall() const { return !holdsLarge; }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE bool isLarge() const { return holdsLarge; }
-  /// Get the stored value. For getSmall/Large,
-  /// the stored value should be small/large.
-  LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t getSmall() const {
-    assert(isSmall() &&
-           "getSmall should only be called when the value stored is small!");
-    return valSmall;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t &getSmall() {
-    assert(isSmall() &&
-           "getSmall should only be called when the value stored is small!");
-    return valSmall;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE const detail::SlowMPInt &getLarge() const {
-    assert(isLarge() &&
-           "getLarge should only be called when the value stored is large!");
-    return valLarge;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE detail::SlowMPInt &getLarge() {
-    assert(isLarge() &&
-           "getLarge should only be called when the value stored is large!");
-    return valLarge;
-  }
-  explicit operator detail::SlowMPInt() const {
-    if (isSmall())
-      return detail::SlowMPInt(getSmall());
-    return getLarge();
-  }
-
-public:
-  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit MPInt(int64_t val)
-      : valSmall(val), holdsLarge(false) {}
-  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt() : MPInt(0) {}
-  LLVM_ATTRIBUTE_ALWAYS_INLINE ~MPInt() {
-    if (LLVM_UNLIKELY(isLarge()))
-      valLarge.detail::SlowMPInt::~SlowMPInt();
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt(const MPInt &o)
-      : valSmall(o.valSmall), holdsLarge(false) {
-    if (LLVM_UNLIKELY(o.isLarge()))
-      initLarge(o.valLarge);
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator=(const MPInt &o) {
-    if (LLVM_LIKELY(o.isSmall())) {
-      initSmall(o.valSmall);
-      return *this;
-    }
-    initLarge(o.valLarge);
-    return *this;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator=(int x) {
-    initSmall(x);
-    return *this;
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit operator int64_t() const {
-    if (isSmall())
-      return getSmall();
-    return static_cast<int64_t>(getLarge());
-  }
-
-  bool operator==(const MPInt &o) const;
-  bool operator!=(const MPInt &o) const;
-  bool operator>(const MPInt &o) const;
-  bool operator<(const MPInt &o) const;
-  bool operator<=(const MPInt &o) const;
-  bool operator>=(const MPInt &o) const;
-  MPInt operator+(const MPInt &o) const;
-  MPInt operator-(const MPInt &o) const;
-  MPInt operator*(const MPInt &o) const;
-  MPInt operator/(const MPInt &o) const;
-  MPInt operator%(const MPInt &o) const;
-  MPInt &operator+=(const MPInt &o);
-  MPInt &operator-=(const MPInt &o);
-  MPInt &operator*=(const MPInt &o);
-  MPInt &operator/=(const MPInt &o);
-  MPInt &operator%=(const MPInt &o);
-  MPInt operator-() const;
-  MPInt &operator++();
-  MPInt &operator--();
-
-  // Divide by a number that is known to be positive.
-  // This is slightly more efficient because it saves an overflow check.
-  MPInt divByPositive(const MPInt &o) const;
-  MPInt &divByPositiveInPlace(const MPInt &o);
-
-  friend MPInt abs(const MPInt &x);
-  friend MPInt gcdRange(ArrayRef<MPInt> range);
-  friend MPInt ceilDiv(const MPInt &lhs, const MPInt &rhs);
-  friend MPInt floorDiv(const MPInt &lhs, const MPInt &rhs);
-  // The operands must be non-negative for gcd.
-  friend MPInt gcd(const MPInt &a, const MPInt &b);
-  friend MPInt lcm(const MPInt &a, const MPInt &b);
-  friend MPInt mod(const MPInt &lhs, const MPInt &rhs);
-
-  llvm::raw_ostream &print(llvm::raw_ostream &os) const;
-  void dump() const;
-
-  /// ---------------------------------------------------------------------------
-  /// Convenience operator overloads for int64_t.
-  /// ---------------------------------------------------------------------------
-  friend MPInt &operator+=(MPInt &a, int64_t b);
-  friend MPInt &operator-=(MPInt &a, int64_t b);
-  friend MPInt &operator*=(MPInt &a, int64_t b);
-  friend MPInt &operator/=(MPInt &a, int64_t b);
-  friend MPInt &operator%=(MPInt &a, int64_t b);
-
-  friend bool operator==(const MPInt &a, int64_t b);
-  friend bool operator!=(const MPInt &a, int64_t b);
-  friend bool operator>(const MPInt &a, int64_t b);
-  friend bool operator<(const MPInt &a, int64_t b);
-  friend bool operator<=(const MPInt &a, int64_t b);
-  friend bool operator>=(const MPInt &a, int64_t b);
-  friend MPInt operator+(const MPInt &a, int64_t b);
-  friend MPInt operator-(const MPInt &a, int64_t b);
-  friend MPInt operator*(const MPInt &a, int64_t b);
-  friend MPInt operator/(const MPInt &a, int64_t b);
-  friend MPInt operator%(const MPInt &a, int64_t b);
-
-  friend bool operator==(int64_t a, const MPInt &b);
-  friend bool operator!=(int64_t a, const MPInt &b);
-  friend bool operator>(int64_t a, const MPInt &b);
-  friend bool operator<(int64_t a, const MPInt &b);
-  friend bool operator<=(int64_t a, const MPInt &b);
-  friend bool operator>=(int64_t a, const MPInt &b);
-  friend MPInt operator+(int64_t a, const MPInt &b);
-  friend MPInt operator-(int64_t a, const MPInt &b);
-  friend MPInt operator*(int64_t a, const MPInt &b);
-  friend MPInt operator/(int64_t a, const MPInt &b);
-  friend MPInt operator%(int64_t a, const MPInt &b);
-
-  friend llvm::hash_code hash_value(const MPInt &x); // NOLINT
-};
-
-/// Redeclarations of friend declaration above to
-/// make it discoverable by lookups.
-llvm::hash_code hash_value(const MPInt &x); // NOLINT
-
-/// This just calls through to the operator int64_t, but it's useful when a
-/// function pointer is required. (Although this is marked inline, it is still
-/// possible to obtain and use a function pointer to this.)
-static inline int64_t int64FromMPInt(const MPInt &x) { return int64_t(x); }
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mpintFromInt64(int64_t x) {
-  return MPInt(x);
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const MPInt &x);
-
-// The RHS is always expected to be positive, and the result
-/// is always non-negative.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mod(const MPInt &lhs, const MPInt &rhs);
-
-namespace detail {
-// Division overflows only when trying to negate the minimal signed value.
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool divWouldOverflow(int64_t x, int64_t y) {
-  return x == std::numeric_limits<int64_t>::min() && y == -1;
-}
-} // namespace detail
-
-/// We define the operations here in the header to facilitate inlining.
-
-/// ---------------------------------------------------------------------------
-/// Comparison operators.
-/// ---------------------------------------------------------------------------
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator==(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() == o.getSmall();
-  return detail::SlowMPInt(*this) == detail::SlowMPInt(o);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator!=(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() != o.getSmall();
-  return detail::SlowMPInt(*this) != detail::SlowMPInt(o);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator>(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() > o.getSmall();
-  return detail::SlowMPInt(*this) > detail::SlowMPInt(o);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator<(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() < o.getSmall();
-  return detail::SlowMPInt(*this) < detail::SlowMPInt(o);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator<=(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() <= o.getSmall();
-  return detail::SlowMPInt(*this) <= detail::SlowMPInt(o);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool MPInt::operator>=(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return getSmall() >= o.getSmall();
-  return detail::SlowMPInt(*this) >= detail::SlowMPInt(o);
-}
-
-/// ---------------------------------------------------------------------------
-/// Arithmetic operators.
-/// ---------------------------------------------------------------------------
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator+(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    MPInt result;
-    bool overflow =
-        detail::addOverflow(getSmall(), o.getSmall(), result.getSmall());
-    if (LLVM_LIKELY(!overflow))
-      return result;
-    return MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(o));
-  }
-  return MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(o));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator-(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    MPInt result;
-    bool overflow =
-        detail::subOverflow(getSmall(), o.getSmall(), result.getSmall());
-    if (LLVM_LIKELY(!overflow))
-      return result;
-    return MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(o));
-  }
-  return MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(o));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator*(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    MPInt result;
-    bool overflow =
-        detail::mulOverflow(getSmall(), o.getSmall(), result.getSmall());
-    if (LLVM_LIKELY(!overflow))
-      return result;
-    return MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(o));
-  }
-  return MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(o));
-}
-
-// Division overflows only occur when negating the minimal possible value.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::divByPositive(const MPInt &o) const {
-  assert(o > 0);
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return MPInt(getSmall() / o.getSmall());
-  return MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(o));
-}
-
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator/(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    // Division overflows only occur when negating the minimal possible value.
-    if (LLVM_UNLIKELY(detail::divWouldOverflow(getSmall(), o.getSmall())))
-      return -*this;
-    return MPInt(getSmall() / o.getSmall());
-  }
-  return MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(o));
-}
-
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt abs(const MPInt &x) {
-  return MPInt(x >= 0 ? x : -x);
-}
-// Division overflows only occur when negating the minimal possible value.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt ceilDiv(const MPInt &lhs, const MPInt &rhs) {
-  if (LLVM_LIKELY(lhs.isSmall() && rhs.isSmall())) {
-    if (LLVM_UNLIKELY(detail::divWouldOverflow(lhs.getSmall(), rhs.getSmall())))
-      return -lhs;
-    return MPInt(ceilDiv(lhs.getSmall(), rhs.getSmall()));
-  }
-  return MPInt(ceilDiv(detail::SlowMPInt(lhs), detail::SlowMPInt(rhs)));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt floorDiv(const MPInt &lhs,
-                                            const MPInt &rhs) {
-  if (LLVM_LIKELY(lhs.isSmall() && rhs.isSmall())) {
-    if (LLVM_UNLIKELY(detail::divWouldOverflow(lhs.getSmall(), rhs.getSmall())))
-      return -lhs;
-    return MPInt(floorDiv(lhs.getSmall(), rhs.getSmall()));
-  }
-  return MPInt(floorDiv(detail::SlowMPInt(lhs), detail::SlowMPInt(rhs)));
-}
-// The RHS is always expected to be positive, and the result
-/// is always non-negative.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt mod(const MPInt &lhs, const MPInt &rhs) {
-  if (LLVM_LIKELY(lhs.isSmall() && rhs.isSmall()))
-    return MPInt(mod(lhs.getSmall(), rhs.getSmall()));
-  return MPInt(mod(detail::SlowMPInt(lhs), detail::SlowMPInt(rhs)));
-}
-
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt gcd(const MPInt &a, const MPInt &b) {
-  assert(a >= 0 && b >= 0 && "operands must be non-negative!");
-  if (LLVM_LIKELY(a.isSmall() && b.isSmall()))
-    return MPInt(std::gcd(a.getSmall(), b.getSmall()));
-  return MPInt(gcd(detail::SlowMPInt(a), detail::SlowMPInt(b)));
-}
-
-/// Returns the least common multiple of 'a' and 'b'.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt lcm(const MPInt &a, const MPInt &b) {
-  MPInt x = abs(a);
-  MPInt y = abs(b);
-  return (x * y) / gcd(x, y);
-}
-
-/// This operation cannot overflow.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator%(const MPInt &o) const {
-  if (LLVM_LIKELY(isSmall() && o.isSmall()))
-    return MPInt(getSmall() % o.getSmall());
-  return MPInt(detail::SlowMPInt(*this) % detail::SlowMPInt(o));
-}
-
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt MPInt::operator-() const {
-  if (LLVM_LIKELY(isSmall())) {
-    if (LLVM_LIKELY(getSmall() != std::numeric_limits<int64_t>::min()))
-      return MPInt(-getSmall());
-    return MPInt(-detail::SlowMPInt(*this));
-  }
-  return MPInt(-detail::SlowMPInt(*this));
-}
-
-/// ---------------------------------------------------------------------------
-/// Assignment operators, preincrement, predecrement.
-/// ---------------------------------------------------------------------------
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator+=(const MPInt &o) {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    int64_t result = getSmall();
-    bool overflow = detail::addOverflow(getSmall(), o.getSmall(), result);
-    if (LLVM_LIKELY(!overflow)) {
-      getSmall() = result;
-      return *this;
-    }
-    // Note: this return is not strictly required but
-    // removing it leads to a performance regression.
-    return *this = MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(o));
-  }
-  return *this = MPInt(detail::SlowMPInt(*this) + detail::SlowMPInt(o));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator-=(const MPInt &o) {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    int64_t result = getSmall();
-    bool overflow = detail::subOverflow(getSmall(), o.getSmall(), result);
-    if (LLVM_LIKELY(!overflow)) {
-      getSmall() = result;
-      return *this;
-    }
-    // Note: this return is not strictly required but
-    // removing it leads to a performance regression.
-    return *this = MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(o));
-  }
-  return *this = MPInt(detail::SlowMPInt(*this) - detail::SlowMPInt(o));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator*=(const MPInt &o) {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    int64_t result = getSmall();
-    bool overflow = detail::mulOverflow(getSmall(), o.getSmall(), result);
-    if (LLVM_LIKELY(!overflow)) {
-      getSmall() = result;
-      return *this;
-    }
-    // Note: this return is not strictly required but
-    // removing it leads to a performance regression.
-    return *this = MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(o));
-  }
-  return *this = MPInt(detail::SlowMPInt(*this) * detail::SlowMPInt(o));
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator/=(const MPInt &o) {
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    // Division overflows only occur when negating the minimal possible value.
-    if (LLVM_UNLIKELY(detail::divWouldOverflow(getSmall(), o.getSmall())))
-      return *this = -*this;
-    getSmall() /= o.getSmall();
-    return *this;
-  }
-  return *this = MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(o));
-}
-
-// Division overflows only occur when the divisor is -1.
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &
-MPInt::divByPositiveInPlace(const MPInt &o) {
-  assert(o > 0);
-  if (LLVM_LIKELY(isSmall() && o.isSmall())) {
-    getSmall() /= o.getSmall();
-    return *this;
-  }
-  return *this = MPInt(detail::SlowMPInt(*this) / detail::SlowMPInt(o));
-}
-
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator%=(const MPInt &o) {
-  return *this = *this % o;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator++() { return *this += 1; }
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &MPInt::operator--() { return *this -= 1; }
-
-/// ----------------------------------------------------------------------------
-/// Convenience operator overloads for int64_t.
-/// ----------------------------------------------------------------------------
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator+=(MPInt &a, int64_t b) {
-  return a = a + b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator-=(MPInt &a, int64_t b) {
-  return a = a - b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator*=(MPInt &a, int64_t b) {
-  return a = a * b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator/=(MPInt &a, int64_t b) {
-  return a = a / b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt &operator%=(MPInt &a, int64_t b) {
-  return a = a % b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator+(const MPInt &a, int64_t b) {
-  return a + MPInt(b);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator-(const MPInt &a, int64_t b) {
-  return a - MPInt(b);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator*(const MPInt &a, int64_t b) {
-  return a * MPInt(b);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator/(const MPInt &a, int64_t b) {
-  return a / MPInt(b);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator%(const MPInt &a, int64_t b) {
-  return a % MPInt(b);
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator+(int64_t a, const MPInt &b) {
-  return MPInt(a) + b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator-(int64_t a, const MPInt &b) {
-  return MPInt(a) - b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator*(int64_t a, const MPInt &b) {
-  return MPInt(a) * b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator/(int64_t a, const MPInt &b) {
-  return MPInt(a) / b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE MPInt operator%(int64_t a, const MPInt &b) {
-  return MPInt(a) % b;
-}
-
-/// We provide special implementations of the comparison operators rather than
-/// calling through as above, as this would result in a 1.2x slowdown.
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator==(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() == b;
-  return a.getLarge() == b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() != b;
-  return a.getLarge() != b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() > b;
-  return a.getLarge() > b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() < b;
-  return a.getLarge() < b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() <= b;
-  return a.getLarge() <= b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(const MPInt &a, int64_t b) {
-  if (LLVM_LIKELY(a.isSmall()))
-    return a.getSmall() >= b;
-  return a.getLarge() >= b;
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator==(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a == b.getSmall();
-  return a == b.getLarge();
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a != b.getSmall();
-  return a != b.getLarge();
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a > b.getSmall();
-  return a > b.getLarge();
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a < b.getSmall();
-  return a < b.getLarge();
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a <= b.getSmall();
-  return a <= b.getLarge();
-}
-LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(int64_t a, const MPInt &b) {
-  if (LLVM_LIKELY(b.isSmall()))
-    return a >= b.getSmall();
-  return a >= b.getLarge();
-}
-
-} // namespace presburger
-} // namespace mlir
-
-#endif // MLIR_ANALYSIS_PRESBURGER_MPINT_H
diff --git a/mlir/include/mlir/Analysis/Presburger/SlowMPInt.h b/mlir/include/mlir/Analysis/Presburger/SlowMPInt.h
deleted file mode 100644
index c70306761c549..0000000000000
--- a/mlir/include/mlir/Analysis/Presburger/SlowMPInt.h
+++ /dev/null
@@ -1,136 +0,0 @@
-//===- SlowMPInt.h - MLIR SlowMPInt Class -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a simple class to represent arbitrary precision signed integers.
-// Unlike APInt, one does not have to specify a fixed maximum size, and the
-// integer can take on any arbitrary values.
-//
-// This class is to be used as a fallback slow path for the MPInt class, and
-// is not intended to be used directly.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_ANALYSIS_PRESBURGER_SLOWMPINT_H
-#define MLIR_ANALYSIS_PRESBURGER_SLOWMPINT_H
-
-#include "mlir/Support/MathExtras.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace mlir {
-namespace presburger {
-namespace detail {
-
-/// A simple class providing multi-precision arithmetic. Internally, it stores
-/// an APInt, whose width is doubled whenever an overflow occurs at a certain
-/// width. The default constructor sets the initial width to 64. SlowMPInt is
-/// primarily intended to be used as a slow fallback path for the upcoming MPInt
-/// class.
-class SlowMPInt {
-private:
-  llvm::APInt val;
-
-public:
-  explicit SlowMPInt(int64_t val);
-  SlowMPInt();
-  explicit SlowMPInt(const llvm::APInt &val);
-  SlowMPInt &operator=(int64_t val);
-  explicit operator int64_t() const;
-  SlowMPInt operator-() const;
-  bool operator==(const SlowMPInt &o) const;
-  bool operator!=(const SlowMPInt &o) const;
-  bool operator>(const SlowMPInt &o) const;
-  bool operator<(const SlowMPInt &o) const;
-  bool operator<=(const SlowMPInt &o) const;
-  bool operator>=(const SlowMPInt &o) const;
-  SlowMPInt operator+(const SlowMPInt &o) const;
-  SlowMPInt operator-(const SlowMPInt &o) const;
-  SlowMPInt operator*(const SlowMPInt &o) const;
-  SlowMPInt operator/(const SlowMPInt &o) const;
-  SlowMPInt operator%(const SlowMPInt &o) const;
-  SlowMPInt &operator+=(const SlowMPInt &o);
-  SlowMPInt &operator-=(const SlowMPInt &o);
-  SlowMPInt &operator*=(const SlowMPInt &o);
-  SlowMPInt &operator/=(const SlowMPInt &o);
-  SlowMPInt &operator%=(const SlowMPInt &o);
-
-  SlowMPInt &operator++();
-  SlowMPInt &operator--();
-
-  friend SlowMPInt abs(const SlowMPInt &x);
-  friend SlowMPInt ceilDiv(const SlowMPInt &lhs, const SlowMPInt &rhs);
-  friend SlowMPInt floorDiv(const SlowMPInt &lhs, const SlowMPInt &rhs);
-  /// The operands must be non-negative for gcd.
-  friend SlowMPInt gcd(const SlowMPInt &a, const SlowMPInt &b);
-
-  /// Overload to compute a hash_code for a SlowMPInt value.
-  friend llvm::hash_code hash_value(const SlowMPInt &x); // NOLINT
-
-  void print(llvm::raw_ostream &os) const;
-  void dump() const;
-
-  unsigned getBitWidth() const { return val.getBitWidth(); }
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const SlowMPInt &x);
-
-/// Returns the remainder of dividing LHS by RHS.
-///
-/// The RHS is always expected to be positive, and the result
-/// is always non-negative.
-SlowMPInt mod(const SlowMPInt &lhs, const SlowMPInt &rhs);
-
-/// Returns the least common multiple of 'a' and 'b'.
-SlowMPInt lcm(const SlowMPInt &a, const SlowMPInt &b);
-
-/// Redeclarations of friend declarations above to
-/// make it discoverable by lookups.
-SlowMPInt abs(const SlowMPInt &x);
-SlowMPInt ceilDiv(const SlowMPInt &lhs, const SlowMPInt &rhs);
-SlowMPInt floorDiv(const SlowMPInt &lhs, const SlowMPInt &rhs);
-SlowMPInt gcd(const SlowMPInt &a, const SlowMPInt &b);
-llvm::hash_code hash_value(const SlowMPInt &x); // NOLINT
-
-/// ---------------------------------------------------------------------------
-/// Convenience operator overloads for int64_t.
-/// ---------------------------------------------------------------------------
-SlowMPInt &operator+=(SlowMPInt &a, int64_t b);
-SlowMPInt &operator-=(SlowMPInt &a, int64_t b);
-SlowMPInt &operator*=(SlowMPInt &a, int64_t b);
-SlowMPInt &operator/=(SlowMPInt &a, int64_t b);
-SlowMPInt &operator%=(SlowMPInt &a, int64_t b);
-
-bool operator==(const SlowMPInt &a, int64_t b);
-bool operator!=(const SlowMPInt &a, int64_t b);
-bool operator>(const SlowMPInt &a, int64_t b);
-bool operator<(const SlowMPInt &a, int64_t b);
-bool operator<=(const SlowMPInt &a, int64_t b);
-bool operator>=(const SlowMPInt &a, int64_t b);
-SlowMPInt operator+(const SlowMPInt &a, int64_t b);
-SlowMPInt operator-(const SlowMPInt &a, int64_t b);
-SlowMPInt operator*(const SlowMPInt &a, int64_t b);
-SlowMPInt operator/(const SlowMPInt &a, int64_t b);
-SlowMPInt operator%(const SlowMPInt &a, int64_t b);
-
-bool operator==(int64_t a, const SlowMPInt &b);
-bool operator!=(int64_t a, const SlowMPInt &b);
-bool operator>(int64_t a, const SlowMPInt &b);
-bool operator<(int64_t a, const SlowMPInt &b);
-bool operator<=(int64_t a, const SlowMPInt &b);
-bool operator>=(int64_t a, const SlowMPInt &b);
-SlowMPInt operator+(int64_t a, const SlowMPInt &b);
-SlowMPInt operator-(int64_t a, const SlowMPInt &b);
-SlowMPInt operator*(int64_t a, const SlowMPInt &b);
-SlowMPInt operator/(int64_t a, const SlowMPInt &b);
-SlowMPInt operator%(int64_t a, const SlowMPInt &b);
-} // namespace detail
-} // namespace presburger
-} // namespace mlir
-
-#endif // MLIR_ANALYSIS_PRESBURGER_SLOWMPINT_H
diff --git a/mlir/include/mlir/Analysis/Presburger/Utils.h b/mlir/include/mlir/Analysis/Presburger/Utils.h
index 38262a65f9754..9a26099dc3d75 100644
--- a/mlir/include/mlir/Analysis/Presburger/Utils.h
+++ b/mlir/include/mlir/Analysis/Presburger/Utils.h
@@ -13,8 +13,8 @@
 #ifndef MLIR_ANALYSIS_PRESBURGER_UTILS_H
 #define MLIR_ANALYSIS_PRESBURGER_UTILS_H
 
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 
@@ -23,7 +23,6 @@
 
 namespace mlir {
 namespace presburger {
-
 class IntegerRelation;
 
 /// This class represents the result of operations optimizing something subject
diff --git a/mlir/include/mlir/Support/LLVM.h b/mlir/include/mlir/Support/LLVM.h
index 235d84c5beff1..d1ab250af5043 100644
--- a/mlir/include/mlir/Support/LLVM.h
+++ b/mlir/include/mlir/Support/LLVM.h
@@ -80,6 +80,7 @@ class TypeSwitch;
 
 // Other common classes.
 class APInt;
+class MPInt;
 class APSInt;
 class APFloat;
 template <typename Fn>
@@ -143,6 +144,7 @@ using TypeSwitch = llvm::TypeSwitch<T, ResultT>;
 using llvm::APFloat;
 using llvm::APInt;
 using llvm::APSInt;
+using llvm::MPInt;
 template <typename Fn>
 using function_ref = llvm::function_ref<Fn>;
 using llvm::iterator_range;
diff --git a/mlir/lib/Analysis/Presburger/CMakeLists.txt b/mlir/lib/Analysis/Presburger/CMakeLists.txt
index 83d0514c9e7d1..1d30dd38ccd1b 100644
--- a/mlir/lib/Analysis/Presburger/CMakeLists.txt
+++ b/mlir/lib/Analysis/Presburger/CMakeLists.txt
@@ -3,13 +3,11 @@ add_mlir_library(MLIRPresburger
   IntegerRelation.cpp
   LinearTransform.cpp
   Matrix.cpp
-  MPInt.cpp
   PresburgerRelation.cpp
   PresburgerSpace.cpp
   PWMAFunction.cpp
   QuasiPolynomial.cpp
   Simplex.cpp
-  SlowMPInt.cpp
   Utils.cpp
 
   LINK_LIBS PUBLIC
diff --git a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
index b5a2ed6ccc369..7163e7584282d 100644
--- a/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
+++ b/mlir/lib/Analysis/Presburger/IntegerRelation.cpp
@@ -15,7 +15,6 @@
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
 #include "mlir/Analysis/Presburger/Fraction.h"
 #include "mlir/Analysis/Presburger/LinearTransform.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/PWMAFunction.h"
 #include "mlir/Analysis/Presburger/PresburgerRelation.h"
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
@@ -25,6 +24,7 @@
 #include "mlir/Support/LogicalResult.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallBitVector.h"
@@ -635,7 +635,7 @@ static void eliminateFromConstraint(IntegerRelation *constraints,
     return;
   MPInt pivotCoeff = constraints->atEq(pivotRow, pivotCol);
   int sign = (leadCoeff * pivotCoeff > 0) ? -1 : 1;
-  MPInt lcm = presburger::lcm(pivotCoeff, leadCoeff);
+  MPInt lcm = llvm::lcm(pivotCoeff, leadCoeff);
   MPInt pivotMultiplier = sign * (lcm / abs(pivotCoeff));
   MPInt rowMultiplier = lcm / abs(leadCoeff);
 
@@ -759,7 +759,7 @@ bool IntegerRelation::isEmptyByGCDTest() const {
   for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
     MPInt gcd = abs(atEq(i, 0));
     for (unsigned j = 1; j < numCols - 1; ++j) {
-      gcd = presburger::gcd(gcd, abs(atEq(i, j)));
+      gcd = llvm::gcd(gcd, abs(atEq(i, j)));
     }
     MPInt v = abs(atEq(i, numCols - 1));
     if (gcd > 0 && (v % gcd != 0)) {
@@ -2022,7 +2022,7 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow,
         if (l == pos)
           continue;
         assert(lbCoeff >= 1 && ubCoeff >= 1 && "bounds wrongly identified");
-        MPInt lcm = presburger::lcm(lbCoeff, ubCoeff);
+        MPInt lcm = llvm::lcm(lbCoeff, ubCoeff);
         ineq.push_back(atIneq(ubPos, l) * (lcm / ubCoeff) +
                        atIneq(lbPos, l) * (lcm / lbCoeff));
         assert(lcm > 0 && "lcm should be positive!");
diff --git a/mlir/lib/Analysis/Presburger/LinearTransform.cpp b/mlir/lib/Analysis/Presburger/LinearTransform.cpp
index 3e080e698b199..8491b85f709e9 100644
--- a/mlir/lib/Analysis/Presburger/LinearTransform.cpp
+++ b/mlir/lib/Analysis/Presburger/LinearTransform.cpp
@@ -8,9 +8,9 @@
 
 #include "mlir/Analysis/Presburger/LinearTransform.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/Matrix.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/MPInt.h"
 #include <utility>
 
 using namespace mlir;
diff --git a/mlir/lib/Analysis/Presburger/MPInt.cpp b/mlir/lib/Analysis/Presburger/MPInt.cpp
deleted file mode 100644
index 587e2b572facf..0000000000000
--- a/mlir/lib/Analysis/Presburger/MPInt.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- MPInt.cpp - MLIR MPInt Class ---------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Presburger/MPInt.h"
-#include "mlir/Analysis/Presburger/SlowMPInt.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace mlir;
-using namespace presburger;
-
-llvm::hash_code mlir::presburger::hash_value(const MPInt &x) {
-  if (x.isSmall())
-    return llvm::hash_value(x.getSmall());
-  return detail::hash_value(x.getLarge());
-}
-
-/// ---------------------------------------------------------------------------
-/// Printing.
-/// ---------------------------------------------------------------------------
-llvm::raw_ostream &MPInt::print(llvm::raw_ostream &os) const {
-  if (isSmall())
-    return os << valSmall;
-  return os << valLarge;
-}
-
-void MPInt::dump() const { print(llvm::errs()); }
-
-llvm::raw_ostream &mlir::presburger::operator<<(llvm::raw_ostream &os,
-                                                const MPInt &x) {
-  x.print(os);
-  return os;
-}
diff --git a/mlir/lib/Analysis/Presburger/Matrix.cpp b/mlir/lib/Analysis/Presburger/Matrix.cpp
index 4cb6e6b16bc87..8ea375e701af7 100644
--- a/mlir/lib/Analysis/Presburger/Matrix.cpp
+++ b/mlir/lib/Analysis/Presburger/Matrix.cpp
@@ -8,9 +8,9 @@
 
 #include "mlir/Analysis/Presburger/Matrix.h"
 #include "mlir/Analysis/Presburger/Fraction.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
diff --git a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
index d55962616de17..06306594d2a9e 100644
--- a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
+++ b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
@@ -8,11 +8,11 @@
 
 #include "mlir/Analysis/Presburger/PWMAFunction.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/PresburgerRelation.h"
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
diff --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
index 3af6baae0e700..a977eb75d30cf 100644
--- a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
+++ b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
@@ -8,7 +8,6 @@
 
 #include "mlir/Analysis/Presburger/PresburgerRelation.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/PWMAFunction.h"
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
 #include "mlir/Analysis/Presburger/Simplex.h"
diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp
index 1969cce93ad2e..2cced6d70643c 100644
--- a/mlir/lib/Analysis/Presburger/Simplex.cpp
+++ b/mlir/lib/Analysis/Presburger/Simplex.cpp
@@ -9,12 +9,12 @@
 #include "mlir/Analysis/Presburger/Simplex.h"
 #include "mlir/Analysis/Presburger/Fraction.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/Matrix.h"
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "mlir/Support/LLVM.h"
 #include "mlir/Support/LogicalResult.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVector.h"
@@ -165,7 +165,7 @@ unsigned SimplexBase::addRow(ArrayRef<MPInt> coeffs, bool makeRestricted) {
     // row, scaled by the coefficient for the variable, accounting for the two
     // rows potentially having different denominators. The new denominator is
     // the lcm of the two.
-    MPInt lcm = presburger::lcm(tableau(newRow, 0), tableau(pos, 0));
+    MPInt lcm = llvm::lcm(tableau(newRow, 0), tableau(pos, 0));
     MPInt nRowCoeff = lcm / tableau(newRow, 0);
     MPInt idxRowCoeff = coeffs[i] * (lcm / tableau(pos, 0));
     tableau(newRow, 0) = lcm;
diff --git a/mlir/lib/Analysis/Presburger/SlowMPInt.cpp b/mlir/lib/Analysis/Presburger/SlowMPInt.cpp
deleted file mode 100644
index ae6f2827be926..0000000000000
--- a/mlir/lib/Analysis/Presburger/SlowMPInt.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-//===- SlowMPInt.cpp - MLIR SlowMPInt Class -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Presburger/SlowMPInt.h"
-#include "mlir/Support/LLVM.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <functional>
-
-using namespace mlir;
-using namespace presburger;
-using namespace detail;
-
-SlowMPInt::SlowMPInt(int64_t val) : val(64, val, /*isSigned=*/true) {}
-SlowMPInt::SlowMPInt() : SlowMPInt(0) {}
-SlowMPInt::SlowMPInt(const llvm::APInt &val) : val(val) {}
-SlowMPInt &SlowMPInt::operator=(int64_t val) { return *this = SlowMPInt(val); }
-SlowMPInt::operator int64_t() const { return val.getSExtValue(); }
-
-llvm::hash_code detail::hash_value(const SlowMPInt &x) {
-  return hash_value(x.val);
-}
-
-/// ---------------------------------------------------------------------------
-/// Printing.
-/// ---------------------------------------------------------------------------
-void SlowMPInt::print(llvm::raw_ostream &os) const { os << val; }
-
-void SlowMPInt::dump() const { print(llvm::errs()); }
-
-llvm::raw_ostream &detail::operator<<(llvm::raw_ostream &os,
-                                      const SlowMPInt &x) {
-  x.print(os);
-  return os;
-}
-
-/// ---------------------------------------------------------------------------
-/// Convenience operator overloads for int64_t.
-/// ---------------------------------------------------------------------------
-SlowMPInt &detail::operator+=(SlowMPInt &a, int64_t b) {
-  return a += SlowMPInt(b);
-}
-SlowMPInt &detail::operator-=(SlowMPInt &a, int64_t b) {
-  return a -= SlowMPInt(b);
-}
-SlowMPInt &detail::operator*=(SlowMPInt &a, int64_t b) {
-  return a *= SlowMPInt(b);
-}
-SlowMPInt &detail::operator/=(SlowMPInt &a, int64_t b) {
-  return a /= SlowMPInt(b);
-}
-SlowMPInt &detail::operator%=(SlowMPInt &a, int64_t b) {
-  return a %= SlowMPInt(b);
-}
-
-bool detail::operator==(const SlowMPInt &a, int64_t b) {
-  return a == SlowMPInt(b);
-}
-bool detail::operator!=(const SlowMPInt &a, int64_t b) {
-  return a != SlowMPInt(b);
-}
-bool detail::operator>(const SlowMPInt &a, int64_t b) {
-  return a > SlowMPInt(b);
-}
-bool detail::operator<(const SlowMPInt &a, int64_t b) {
-  return a < SlowMPInt(b);
-}
-bool detail::operator<=(const SlowMPInt &a, int64_t b) {
-  return a <= SlowMPInt(b);
-}
-bool detail::operator>=(const SlowMPInt &a, int64_t b) {
-  return a >= SlowMPInt(b);
-}
-SlowMPInt detail::operator+(const SlowMPInt &a, int64_t b) {
-  return a + SlowMPInt(b);
-}
-SlowMPInt detail::operator-(const SlowMPInt &a, int64_t b) {
-  return a - SlowMPInt(b);
-}
-SlowMPInt detail::operator*(const SlowMPInt &a, int64_t b) {
-  return a * SlowMPInt(b);
-}
-SlowMPInt detail::operator/(const SlowMPInt &a, int64_t b) {
-  return a / SlowMPInt(b);
-}
-SlowMPInt detail::operator%(const SlowMPInt &a, int64_t b) {
-  return a % SlowMPInt(b);
-}
-
-bool detail::operator==(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) == b;
-}
-bool detail::operator!=(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) != b;
-}
-bool detail::operator>(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) > b;
-}
-bool detail::operator<(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) < b;
-}
-bool detail::operator<=(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) <= b;
-}
-bool detail::operator>=(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) >= b;
-}
-SlowMPInt detail::operator+(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) + b;
-}
-SlowMPInt detail::operator-(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) - b;
-}
-SlowMPInt detail::operator*(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) * b;
-}
-SlowMPInt detail::operator/(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) / b;
-}
-SlowMPInt detail::operator%(int64_t a, const SlowMPInt &b) {
-  return SlowMPInt(a) % b;
-}
-
-static unsigned getMaxWidth(const APInt &a, const APInt &b) {
-  return std::max(a.getBitWidth(), b.getBitWidth());
-}
-
-/// ---------------------------------------------------------------------------
-/// Comparison operators.
-/// ---------------------------------------------------------------------------
-
-// TODO: consider instead making APInt::compare available and using that.
-bool SlowMPInt::operator==(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width) == o.val.sext(width);
-}
-bool SlowMPInt::operator!=(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width) != o.val.sext(width);
-}
-bool SlowMPInt::operator>(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width).sgt(o.val.sext(width));
-}
-bool SlowMPInt::operator<(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width).slt(o.val.sext(width));
-}
-bool SlowMPInt::operator<=(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width).sle(o.val.sext(width));
-}
-bool SlowMPInt::operator>=(const SlowMPInt &o) const {
-  unsigned width = getMaxWidth(val, o.val);
-  return val.sext(width).sge(o.val.sext(width));
-}
-
-/// ---------------------------------------------------------------------------
-/// Arithmetic operators.
-/// ---------------------------------------------------------------------------
-
-/// Bring a and b to have the same width and then call op(a, b, overflow).
-/// If the overflow bit becomes set, resize a and b to double the width and
-/// call op(a, b, overflow), returning its result. The operation with double
-/// widths should not also overflow.
-APInt runOpWithExpandOnOverflow(
-    const APInt &a, const APInt &b,
-    llvm::function_ref<APInt(const APInt &, const APInt &, bool &overflow)>
-        op) {
-  bool overflow;
-  unsigned width = getMaxWidth(a, b);
-  APInt ret = op(a.sext(width), b.sext(width), overflow);
-  if (!overflow)
-    return ret;
-
-  width *= 2;
-  ret = op(a.sext(width), b.sext(width), overflow);
-  assert(!overflow && "double width should be sufficient to avoid overflow!");
-  return ret;
-}
-
-SlowMPInt SlowMPInt::operator+(const SlowMPInt &o) const {
-  return SlowMPInt(
-      runOpWithExpandOnOverflow(val, o.val, std::mem_fn(&APInt::sadd_ov)));
-}
-SlowMPInt SlowMPInt::operator-(const SlowMPInt &o) const {
-  return SlowMPInt(
-      runOpWithExpandOnOverflow(val, o.val, std::mem_fn(&APInt::ssub_ov)));
-}
-SlowMPInt SlowMPInt::operator*(const SlowMPInt &o) const {
-  return SlowMPInt(
-      runOpWithExpandOnOverflow(val, o.val, std::mem_fn(&APInt::smul_ov)));
-}
-SlowMPInt SlowMPInt::operator/(const SlowMPInt &o) const {
-  return SlowMPInt(
-      runOpWithExpandOnOverflow(val, o.val, std::mem_fn(&APInt::sdiv_ov)));
-}
-SlowMPInt detail::abs(const SlowMPInt &x) { return x >= 0 ? x : -x; }
-SlowMPInt detail::ceilDiv(const SlowMPInt &lhs, const SlowMPInt &rhs) {
-  if (rhs == -1)
-    return -lhs;
-  unsigned width = getMaxWidth(lhs.val, rhs.val);
-  return SlowMPInt(llvm::APIntOps::RoundingSDiv(
-      lhs.val.sext(width), rhs.val.sext(width), APInt::Rounding::UP));
-}
-SlowMPInt detail::floorDiv(const SlowMPInt &lhs, const SlowMPInt &rhs) {
-  if (rhs == -1)
-    return -lhs;
-  unsigned width = getMaxWidth(lhs.val, rhs.val);
-  return SlowMPInt(llvm::APIntOps::RoundingSDiv(
-      lhs.val.sext(width), rhs.val.sext(width), APInt::Rounding::DOWN));
-}
-// The RHS is always expected to be positive, and the result
-/// is always non-negative.
-SlowMPInt detail::mod(const SlowMPInt &lhs, const SlowMPInt &rhs) {
-  assert(rhs >= 1 && "mod is only supported for positive divisors!");
-  return lhs % rhs < 0 ? lhs % rhs + rhs : lhs % rhs;
-}
-
-SlowMPInt detail::gcd(const SlowMPInt &a, const SlowMPInt &b) {
-  assert(a >= 0 && b >= 0 && "operands must be non-negative!");
-  unsigned width = getMaxWidth(a.val, b.val);
-  return SlowMPInt(llvm::APIntOps::GreatestCommonDivisor(a.val.sext(width),
-                                                         b.val.sext(width)));
-}
-
-/// Returns the least common multiple of 'a' and 'b'.
-SlowMPInt detail::lcm(const SlowMPInt &a, const SlowMPInt &b) {
-  SlowMPInt x = abs(a);
-  SlowMPInt y = abs(b);
-  return (x * y) / gcd(x, y);
-}
-
-/// This operation cannot overflow.
-SlowMPInt SlowMPInt::operator%(const SlowMPInt &o) const {
-  unsigned width = std::max(val.getBitWidth(), o.val.getBitWidth());
-  return SlowMPInt(val.sext(width).srem(o.val.sext(width)));
-}
-
-SlowMPInt SlowMPInt::operator-() const {
-  if (val.isMinSignedValue()) {
-    /// Overflow only occurs when the value is the minimum possible value.
-    APInt ret = val.sext(2 * val.getBitWidth());
-    return SlowMPInt(-ret);
-  }
-  return SlowMPInt(-val);
-}
-
-/// ---------------------------------------------------------------------------
-/// Assignment operators, preincrement, predecrement.
-/// ---------------------------------------------------------------------------
-SlowMPInt &SlowMPInt::operator+=(const SlowMPInt &o) {
-  *this = *this + o;
-  return *this;
-}
-SlowMPInt &SlowMPInt::operator-=(const SlowMPInt &o) {
-  *this = *this - o;
-  return *this;
-}
-SlowMPInt &SlowMPInt::operator*=(const SlowMPInt &o) {
-  *this = *this * o;
-  return *this;
-}
-SlowMPInt &SlowMPInt::operator/=(const SlowMPInt &o) {
-  *this = *this / o;
-  return *this;
-}
-SlowMPInt &SlowMPInt::operator%=(const SlowMPInt &o) {
-  *this = *this % o;
-  return *this;
-}
-SlowMPInt &SlowMPInt::operator++() {
-  *this += 1;
-  return *this;
-}
-
-SlowMPInt &SlowMPInt::operator--() {
-  *this -= 1;
-  return *this;
-}
diff --git a/mlir/lib/Analysis/Presburger/Utils.cpp b/mlir/lib/Analysis/Presburger/Utils.cpp
index f717a4de5d728..29130e43f0957 100644
--- a/mlir/lib/Analysis/Presburger/Utils.cpp
+++ b/mlir/lib/Analysis/Presburger/Utils.cpp
@@ -12,10 +12,10 @@
 
 #include "mlir/Analysis/Presburger/Utils.h"
 #include "mlir/Analysis/Presburger/IntegerRelation.h"
-#include "mlir/Analysis/Presburger/MPInt.h"
 #include "mlir/Analysis/Presburger/PresburgerSpace.h"
 #include "mlir/Support/LLVM.h"
 #include "mlir/Support/LogicalResult.h"
+#include "llvm/ADT/MPInt.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/raw_ostream.h"
@@ -31,6 +31,7 @@
 
 using namespace mlir;
 using namespace presburger;
+using llvm::mpintFromInt64;
 
 /// Normalize a division's `dividend` and the `divisor` by their GCD. For
 /// example: if the dividend and divisor are [2,0,4] and 4 respectively,
@@ -43,7 +44,7 @@ static void normalizeDivisionByGCD(MutableArrayRef<MPInt> dividend,
     return;
   // We take the absolute value of dividend's coefficients to make sure that
   // `gcd` is positive.
-  MPInt gcd = presburger::gcd(abs(dividend.front()), divisor);
+  MPInt gcd = llvm::gcd(abs(dividend.front()), divisor);
 
   // The reason for ignoring the constant term is as follows.
   // For a division:
@@ -53,7 +54,7 @@ static void normalizeDivisionByGCD(MutableArrayRef<MPInt> dividend,
   // Since `{a/m}/d` in the dividend satisfies 0 <= {a/m}/d < 1/d, it will not
   // influence the result of the floor division and thus, can be ignored.
   for (size_t i = 1, m = dividend.size() - 1; i < m; i++) {
-    gcd = presburger::gcd(abs(dividend[i]), gcd);
+    gcd = llvm::gcd(abs(dividend[i]), gcd);
     if (gcd == 1)
       return;
   }
@@ -346,7 +347,7 @@ SmallVector<MPInt, 8> presburger::getDivLowerBound(ArrayRef<MPInt> dividend,
 MPInt presburger::gcdRange(ArrayRef<MPInt> range) {
   MPInt gcd(0);
   for (const MPInt &elem : range) {
-    gcd = presburger::gcd(gcd, abs(elem));
+    gcd = llvm::gcd(gcd, abs(elem));
     if (gcd == 1)
       return gcd;
   }
@@ -364,7 +365,7 @@ MPInt presburger::normalizeRange(MutableArrayRef<MPInt> range) {
 
 void presburger::normalizeDiv(MutableArrayRef<MPInt> num, MPInt &denom) {
   assert(denom > 0 && "denom must be positive!");
-  MPInt gcd = presburger::gcd(gcdRange(num), denom);
+  MPInt gcd = llvm::gcd(gcdRange(num), denom);
   for (MPInt &coeff : num)
     coeff /= gcd;
   denom /= gcd;
diff --git a/mlir/unittests/Analysis/Presburger/CMakeLists.txt b/mlir/unittests/Analysis/Presburger/CMakeLists.txt
index c98668f63fa5d..b69f514711337 100644
--- a/mlir/unittests/Analysis/Presburger/CMakeLists.txt
+++ b/mlir/unittests/Analysis/Presburger/CMakeLists.txt
@@ -6,7 +6,6 @@ add_mlir_unittest(MLIRPresburgerTests
   IntegerRelationTest.cpp
   LinearTransformTest.cpp
   MatrixTest.cpp
-  MPIntTest.cpp
   Parser.h
   ParserTest.cpp
   PresburgerSetTest.cpp
diff --git a/mlir/unittests/Analysis/Presburger/MPIntTest.cpp b/mlir/unittests/Analysis/Presburger/MPIntTest.cpp
deleted file mode 100644
index 3c145d39352c3..0000000000000
--- a/mlir/unittests/Analysis/Presburger/MPIntTest.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-//===- MPIntTest.cpp - Tests for MPInt ------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/Presburger/MPInt.h"
-#include "mlir/Analysis/Presburger/SlowMPInt.h"
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-using namespace mlir;
-using namespace presburger;
-
-// googletest boilerplate to run the same tests with both MPInt and SlowMPInt.
-template <typename>
-class IntTest : public testing::Test {};
-using TypeList = testing::Types<MPInt, detail::SlowMPInt>;
-// This is for pretty-printing the test name with the name of the class in use.
-class TypeNames {
-public:
-  template <typename T>
-  static std::string GetName(int) { // NOLINT; gtest mandates this name.
-    if (std::is_same<T, MPInt>())
-      return "MPInt";
-    if (std::is_same<T, detail::SlowMPInt>())
-      return "SlowMPInt";
-    llvm_unreachable("Unknown class!");
-  }
-};
-TYPED_TEST_SUITE(IntTest, TypeList, TypeNames);
-
-TYPED_TEST(IntTest, ops) {
-  TypeParam two(2), five(5), seven(7), ten(10);
-  EXPECT_EQ(five + five, ten);
-  EXPECT_EQ(five * five, 2 * ten + five);
-  EXPECT_EQ(five * five, 3 * ten - five);
-  EXPECT_EQ(five * two, ten);
-  EXPECT_EQ(five / two, two);
-  EXPECT_EQ(five % two, two / two);
-
-  EXPECT_EQ(-ten % seven, -10 % 7);
-  EXPECT_EQ(ten % -seven, 10 % -7);
-  EXPECT_EQ(-ten % -seven, -10 % -7);
-  EXPECT_EQ(ten % seven, 10 % 7);
-
-  EXPECT_EQ(-ten / seven, -10 / 7);
-  EXPECT_EQ(ten / -seven, 10 / -7);
-  EXPECT_EQ(-ten / -seven, -10 / -7);
-  EXPECT_EQ(ten / seven, 10 / 7);
-
-  TypeParam x = ten;
-  x += five;
-  EXPECT_EQ(x, 15);
-  x *= two;
-  EXPECT_EQ(x, 30);
-  x /= seven;
-  EXPECT_EQ(x, 4);
-  x -= two * 10;
-  EXPECT_EQ(x, -16);
-  x *= 2 * two;
-  EXPECT_EQ(x, -64);
-  x /= two / -2;
-  EXPECT_EQ(x, 64);
-
-  EXPECT_LE(ten, ten);
-  EXPECT_GE(ten, ten);
-  EXPECT_EQ(ten, ten);
-  EXPECT_FALSE(ten != ten);
-  EXPECT_FALSE(ten < ten);
-  EXPECT_FALSE(ten > ten);
-  EXPECT_LT(five, ten);
-  EXPECT_GT(ten, five);
-}
-
-TYPED_TEST(IntTest, ops64Overloads) {
-  TypeParam two(2), five(5), seven(7), ten(10);
-  EXPECT_EQ(five + 5, ten);
-  EXPECT_EQ(five + 5, 5 + five);
-  EXPECT_EQ(five * 5, 2 * ten + 5);
-  EXPECT_EQ(five * 5, 3 * ten - 5);
-  EXPECT_EQ(five * two, ten);
-  EXPECT_EQ(5 / two, 2);
-  EXPECT_EQ(five / 2, 2);
-  EXPECT_EQ(2 % two, 0);
-  EXPECT_EQ(2 - two, 0);
-  EXPECT_EQ(2 % two, two % 2);
-
-  TypeParam x = ten;
-  x += 5;
-  EXPECT_EQ(x, 15);
-  x *= 2;
-  EXPECT_EQ(x, 30);
-  x /= 7;
-  EXPECT_EQ(x, 4);
-  x -= 20;
-  EXPECT_EQ(x, -16);
-  x *= 4;
-  EXPECT_EQ(x, -64);
-  x /= -1;
-  EXPECT_EQ(x, 64);
-
-  EXPECT_LE(ten, 10);
-  EXPECT_GE(ten, 10);
-  EXPECT_EQ(ten, 10);
-  EXPECT_FALSE(ten != 10);
-  EXPECT_FALSE(ten < 10);
-  EXPECT_FALSE(ten > 10);
-  EXPECT_LT(five, 10);
-  EXPECT_GT(ten, 5);
-
-  EXPECT_LE(10, ten);
-  EXPECT_GE(10, ten);
-  EXPECT_EQ(10, ten);
-  EXPECT_FALSE(10 != ten);
-  EXPECT_FALSE(10 < ten);
-  EXPECT_FALSE(10 > ten);
-  EXPECT_LT(5, ten);
-  EXPECT_GT(10, five);
-}
-
-TYPED_TEST(IntTest, overflows) {
-  TypeParam x(1ll << 60);
-  EXPECT_EQ((x * x - x * x * x * x) / (x * x * x), 1 - (1ll << 60));
-  TypeParam y(1ll << 62);
-  EXPECT_EQ((y + y + y + y + y + y) / y, 6);
-  EXPECT_EQ(-(2 * (-y)), 2 * y); // -(-2^63) overflow.
-  x *= x;
-  EXPECT_EQ(x, (y * y) / 16);
-  y += y;
-  y += y;
-  y += y;
-  y /= 8;
-  EXPECT_EQ(y, 1ll << 62);
-
-  TypeParam min(std::numeric_limits<int64_t>::min());
-  TypeParam one(1);
-  EXPECT_EQ(floorDiv(min, -one), -min);
-  EXPECT_EQ(ceilDiv(min, -one), -min);
-  EXPECT_EQ(abs(min), -min);
-
-  TypeParam z = min;
-  z /= -1;
-  EXPECT_EQ(z, -min);
-  TypeParam w(min);
-  --w;
-  EXPECT_EQ(w, TypeParam(min) - 1);
-  TypeParam u(min);
-  u -= 1;
-  EXPECT_EQ(u, w);
-
-  TypeParam max(std::numeric_limits<int64_t>::max());
-  TypeParam v = max;
-  ++v;
-  EXPECT_EQ(v, max + 1);
-  TypeParam t = max;
-  t += 1;
-  EXPECT_EQ(t, v);
-}
-
-TYPED_TEST(IntTest, floorCeilModAbsLcmGcd) {
-  TypeParam x(1ll << 50), one(1), two(2), three(3);
-
-  // Run on small values and large values.
-  for (const TypeParam &y : {x, x * x}) {
-    EXPECT_EQ(floorDiv(3 * y, three), y);
-    EXPECT_EQ(ceilDiv(3 * y, three), y);
-    EXPECT_EQ(floorDiv(3 * y - 1, three), y - 1);
-    EXPECT_EQ(ceilDiv(3 * y - 1, three), y);
-    EXPECT_EQ(floorDiv(3 * y - 2, three), y - 1);
-    EXPECT_EQ(ceilDiv(3 * y - 2, three), y);
-
-    EXPECT_EQ(mod(3 * y, three), 0);
-    EXPECT_EQ(mod(3 * y + 1, three), one);
-    EXPECT_EQ(mod(3 * y + 2, three), two);
-
-    EXPECT_EQ(floorDiv(3 * y, y), 3);
-    EXPECT_EQ(ceilDiv(3 * y, y), 3);
-    EXPECT_EQ(floorDiv(3 * y - 1, y), 2);
-    EXPECT_EQ(ceilDiv(3 * y - 1, y), 3);
-    EXPECT_EQ(floorDiv(3 * y - 2, y), 2);
-    EXPECT_EQ(ceilDiv(3 * y - 2, y), 3);
-
-    EXPECT_EQ(mod(3 * y, y), 0);
-    EXPECT_EQ(mod(3 * y + 1, y), 1);
-    EXPECT_EQ(mod(3 * y + 2, y), 2);
-
-    EXPECT_EQ(abs(y), y);
-    EXPECT_EQ(abs(-y), y);
-
-    EXPECT_EQ(gcd(3 * y, three), three);
-    EXPECT_EQ(lcm(y, three), 3 * y);
-    EXPECT_EQ(gcd(2 * y, 3 * y), y);
-    EXPECT_EQ(lcm(2 * y, 3 * y), 6 * y);
-    EXPECT_EQ(gcd(15 * y, 6 * y), 3 * y);
-    EXPECT_EQ(lcm(15 * y, 6 * y), 30 * y);
-  }
-}
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 6b00898a7e274..3f13b21cfd73d 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -22,12 +22,14 @@
 #include "mlir/Analysis/Presburger/Simplex.h"
 #include "mlir/IR/MLIRContext.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/MPInt.h"
 
 #include <gtest/gtest.h>
 #include <optional>
 
 namespace mlir {
 namespace presburger {
+using llvm::mpintFromInt64;
 
 inline IntMatrix makeIntMatrix(unsigned numRow, unsigned numColumns,
                                ArrayRef<SmallVector<int, 8>> matrix) {

>From 9153bb6bfd6446d6ec0ea5147495c33a072da9df Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 10 Jun 2024 11:47:43 +0100
Subject: [PATCH 2/2] MPInt: fix compile

---
 llvm/include/llvm/ADT/MPInt.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ADT/MPInt.h b/llvm/include/llvm/ADT/MPInt.h
index dc387d7d0e5db..42a297a844993 100644
--- a/llvm/include/llvm/ADT/MPInt.h
+++ b/llvm/include/llvm/ADT/MPInt.h
@@ -69,7 +69,7 @@ LLVM_ATTRIBUTE_ALWAYS_INLINE bool addOverflow(int64_t X, int64_t Y,
 #if __has_builtin(__builtin_add_overflow)
   return __builtin_add_overflow(X, Y, &Result);
 #else
-  return AddOverflow(x, y, result);
+  return AddOverflow(X, Y, Result);
 #endif
 }
 LLVM_ATTRIBUTE_ALWAYS_INLINE bool subOverflow(int64_t X, int64_t Y,
@@ -77,7 +77,7 @@ LLVM_ATTRIBUTE_ALWAYS_INLINE bool subOverflow(int64_t X, int64_t Y,
 #if __has_builtin(__builtin_sub_overflow)
   return __builtin_sub_overflow(X, Y, &Result);
 #else
-  return SubOverflow(x, y, result);
+  return SubOverflow(X, Y, Result);
 #endif
 }
 LLVM_ATTRIBUTE_ALWAYS_INLINE bool mulOverflow(int64_t X, int64_t Y,
@@ -85,7 +85,7 @@ LLVM_ATTRIBUTE_ALWAYS_INLINE bool mulOverflow(int64_t X, int64_t Y,
 #if __has_builtin(__builtin_mul_overflow)
   return __builtin_mul_overflow(X, Y, &Result);
 #else
-  return MulOverflow(x, y, result);
+  return MulOverflow(X, Y, Result);
 #endif
 }
 } // namespace detail



More information about the Mlir-commits mailing list