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

Ramkumar Ramachandra llvmlistbot at llvm.org
Mon Jun 10 11:28:16 PDT 2024


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

>From ff840ef5322cc3377e7b51744d9102a86215649d 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/4] 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/DynamicAPInt.h          | 711 ++++++++++++++++++
 llvm/include/llvm/ADT/SlowDynamicAPInt.h      | 140 ++++
 llvm/lib/Support/CMakeLists.txt               |   2 +
 llvm/lib/Support/DynamicAPInt.cpp             |  29 +
 llvm/lib/Support/SlowDynamicAPInt.cpp         | 288 +++++++
 llvm/unittests/ADT/CMakeLists.txt             |   1 +
 llvm/unittests/ADT/DynamicAPIntTest.cpp       | 200 +++++
 .../mlir/Analysis/Presburger/Barvinok.h       |   2 +-
 .../mlir/Analysis/Presburger/Fraction.h       |  32 +-
 .../Analysis/Presburger/IntegerRelation.h     | 102 +--
 .../Analysis/Presburger/LinearTransform.h     |   6 +-
 mlir/include/mlir/Analysis/Presburger/MPInt.h | 617 ---------------
 .../include/mlir/Analysis/Presburger/Matrix.h |  26 +-
 .../mlir/Analysis/Presburger/PWMAFunction.h   |  18 +-
 .../Analysis/Presburger/PresburgerRelation.h  |   8 +-
 .../mlir/Analysis/Presburger/Simplex.h        |  41 +-
 .../mlir/Analysis/Presburger/SlowMPInt.h      | 136 ----
 mlir/include/mlir/Analysis/Presburger/Utils.h |  62 +-
 mlir/include/mlir/Support/LLVM.h              |   2 +
 .../Analysis/FlatLinearValueConstraints.cpp   |   3 +-
 mlir/lib/Analysis/Presburger/Barvinok.cpp     |   6 +-
 mlir/lib/Analysis/Presburger/CMakeLists.txt   |   2 -
 .../Analysis/Presburger/IntegerRelation.cpp   | 192 ++---
 .../Analysis/Presburger/LinearTransform.cpp   |  13 +-
 mlir/lib/Analysis/Presburger/MPInt.cpp        |  38 -
 mlir/lib/Analysis/Presburger/Matrix.cpp       |  23 +-
 mlir/lib/Analysis/Presburger/PWMAFunction.cpp |  39 +-
 .../Presburger/PresburgerRelation.cpp         |  58 +-
 mlir/lib/Analysis/Presburger/Simplex.cpp      | 172 ++---
 mlir/lib/Analysis/Presburger/SlowMPInt.cpp    | 290 -------
 mlir/lib/Analysis/Presburger/Utils.cpp        | 137 ++--
 .../Analysis/Presburger/CMakeLists.txt        |   1 -
 .../Analysis/Presburger/FractionTest.cpp      |   2 +-
 .../Presburger/IntegerPolyhedronTest.cpp      |  22 +-
 .../Presburger/LinearTransformTest.cpp        |   3 +-
 .../Analysis/Presburger/MPIntTest.cpp         | 200 -----
 .../Analysis/Presburger/MatrixTest.cpp        |   2 +-
 .../Analysis/Presburger/SimplexTest.cpp       |  29 +-
 mlir/unittests/Analysis/Presburger/Utils.h    |  20 +-
 .../Analysis/Presburger/UtilsTest.cpp         |  47 +-
 40 files changed, 1940 insertions(+), 1782 deletions(-)
 create mode 100644 llvm/include/llvm/ADT/DynamicAPInt.h
 create mode 100644 llvm/include/llvm/ADT/SlowDynamicAPInt.h
 create mode 100644 llvm/lib/Support/DynamicAPInt.cpp
 create mode 100644 llvm/lib/Support/SlowDynamicAPInt.cpp
 create mode 100644 llvm/unittests/ADT/DynamicAPIntTest.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/DynamicAPInt.h b/llvm/include/llvm/ADT/DynamicAPInt.h
new file mode 100644
index 0000000000000..98fee5e7462a4
--- /dev/null
+++ b/llvm/include/llvm/ADT/DynamicAPInt.h
@@ -0,0 +1,711 @@
+//===- DyanmicAPInt.h - DynamicAPInt 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_DYNAMICAPINT_H
+#define LLVM_ADT_DYNAMICAPINT_H
+
+#include "llvm/ADT/SlowDynamicAPInt.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 dynamic arbitrary-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 DynamicAPInt {
+  union {
+    int64_t ValSmall;
+    detail::SlowDynamicAPInt ValLarge;
+  };
+  unsigned HoldsLarge;
+
+  LLVM_ATTRIBUTE_ALWAYS_INLINE void initSmall(int64_t O) {
+    if (LLVM_UNLIKELY(isLarge()))
+      ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
+    ValSmall = O;
+    HoldsLarge = false;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE void
+  initLarge(const detail::SlowDynamicAPInt &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::SlowDynamicAPInt(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 DynamicAPInt(
+      const detail::SlowDynamicAPInt &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::SlowDynamicAPInt &
+  getLarge() const {
+    assert(isLarge() &&
+           "getLarge should only be called when the value stored is large!");
+    return ValLarge;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE detail::SlowDynamicAPInt &getLarge() {
+    assert(isLarge() &&
+           "getLarge should only be called when the value stored is large!");
+    return ValLarge;
+  }
+  explicit operator detail::SlowDynamicAPInt() const {
+    if (isSmall())
+      return detail::SlowDynamicAPInt(getSmall());
+    return getLarge();
+  }
+
+public:
+  LLVM_ATTRIBUTE_ALWAYS_INLINE explicit DynamicAPInt(int64_t Val)
+      : ValSmall(Val), HoldsLarge(false) {}
+  LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt() : DynamicAPInt(0) {}
+  LLVM_ATTRIBUTE_ALWAYS_INLINE ~DynamicAPInt() {
+    if (LLVM_UNLIKELY(isLarge()))
+      ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt(const DynamicAPInt &O)
+      : ValSmall(O.ValSmall), HoldsLarge(false) {
+    if (LLVM_UNLIKELY(O.isLarge()))
+      initLarge(O.ValLarge);
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator=(const DynamicAPInt &O) {
+    if (LLVM_LIKELY(O.isSmall())) {
+      initSmall(O.ValSmall);
+      return *this;
+    }
+    initLarge(O.ValLarge);
+    return *this;
+  }
+  LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &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 DynamicAPInt &O) const;
+  bool operator!=(const DynamicAPInt &O) const;
+  bool operator>(const DynamicAPInt &O) const;
+  bool operator<(const DynamicAPInt &O) const;
+  bool operator<=(const DynamicAPInt &O) const;
+  bool operator>=(const DynamicAPInt &O) const;
+  DynamicAPInt operator+(const DynamicAPInt &O) const;
+  DynamicAPInt operator-(const DynamicAPInt &O) const;
+  DynamicAPInt operator*(const DynamicAPInt &O) const;
+  DynamicAPInt operator/(const DynamicAPInt &O) const;
+  DynamicAPInt operator%(const DynamicAPInt &O) const;
+  DynamicAPInt &operator+=(const DynamicAPInt &O);
+  DynamicAPInt &operator-=(const DynamicAPInt &O);
+  DynamicAPInt &operator*=(const DynamicAPInt &O);
+  DynamicAPInt &operator/=(const DynamicAPInt &O);
+  DynamicAPInt &operator%=(const DynamicAPInt &O);
+  DynamicAPInt operator-() const;
+  DynamicAPInt &operator++();
+  DynamicAPInt &operator--();
+
+  // Divide by a number that is known to be positive.
+  // This is slightly more efficient because it saves an overflow check.
+  DynamicAPInt divByPositive(const DynamicAPInt &O) const;
+  DynamicAPInt &divByPositiveInPlace(const DynamicAPInt &O);
+
+  friend DynamicAPInt abs(const DynamicAPInt &X);
+  friend DynamicAPInt ceilDiv(const DynamicAPInt &LHS, const DynamicAPInt &RHS);
+  friend DynamicAPInt floorDiv(const DynamicAPInt &LHS,
+                               const DynamicAPInt &RHS);
+  // The operands must be non-negative for gcd.
+  friend DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B);
+  friend DynamicAPInt lcm(const DynamicAPInt &A, const DynamicAPInt &B);
+  friend DynamicAPInt mod(const DynamicAPInt &LHS, const DynamicAPInt &RHS);
+
+  /// ---------------------------------------------------------------------------
+  /// Convenience operator overloads for int64_t.
+  /// ---------------------------------------------------------------------------
+  friend DynamicAPInt &operator+=(DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt &operator-=(DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt &operator*=(DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt &operator/=(DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt &operator%=(DynamicAPInt &A, int64_t B);
+
+  friend bool operator==(const DynamicAPInt &A, int64_t B);
+  friend bool operator!=(const DynamicAPInt &A, int64_t B);
+  friend bool operator>(const DynamicAPInt &A, int64_t B);
+  friend bool operator<(const DynamicAPInt &A, int64_t B);
+  friend bool operator<=(const DynamicAPInt &A, int64_t B);
+  friend bool operator>=(const DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt operator+(const DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt operator-(const DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt operator*(const DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt operator/(const DynamicAPInt &A, int64_t B);
+  friend DynamicAPInt operator%(const DynamicAPInt &A, int64_t B);
+
+  friend bool operator==(int64_t A, const DynamicAPInt &B);
+  friend bool operator!=(int64_t A, const DynamicAPInt &B);
+  friend bool operator>(int64_t A, const DynamicAPInt &B);
+  friend bool operator<(int64_t A, const DynamicAPInt &B);
+  friend bool operator<=(int64_t A, const DynamicAPInt &B);
+  friend bool operator>=(int64_t A, const DynamicAPInt &B);
+  friend DynamicAPInt operator+(int64_t A, const DynamicAPInt &B);
+  friend DynamicAPInt operator-(int64_t A, const DynamicAPInt &B);
+  friend DynamicAPInt operator*(int64_t A, const DynamicAPInt &B);
+  friend DynamicAPInt operator/(int64_t A, const DynamicAPInt &B);
+  friend DynamicAPInt operator%(int64_t A, const DynamicAPInt &B);
+
+  friend hash_code hash_value(const DynamicAPInt &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 DynamicAPInt &X) {
+  X.print(OS);
+  return OS;
+}
+#endif
+
+/// Redeclarations of friend declaration above to
+/// make it discoverable by lookups.
+hash_code hash_value(const DynamicAPInt &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 int64fromDynamicAPInt(const DynamicAPInt &X) {
+  return int64_t(X);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt dynamicAPIntFromInt64(int64_t X) {
+  return DynamicAPInt(X);
+}
+
+// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt mod(const DynamicAPInt &LHS,
+                                              const DynamicAPInt &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
+DynamicAPInt::operator==(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() == O.getSmall();
+  return detail::SlowDynamicAPInt(*this) == detail::SlowDynamicAPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool
+DynamicAPInt::operator!=(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() != O.getSmall();
+  return detail::SlowDynamicAPInt(*this) != detail::SlowDynamicAPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool
+DynamicAPInt::operator>(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() > O.getSmall();
+  return detail::SlowDynamicAPInt(*this) > detail::SlowDynamicAPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool
+DynamicAPInt::operator<(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() < O.getSmall();
+  return detail::SlowDynamicAPInt(*this) < detail::SlowDynamicAPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool
+DynamicAPInt::operator<=(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() <= O.getSmall();
+  return detail::SlowDynamicAPInt(*this) <= detail::SlowDynamicAPInt(O);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool
+DynamicAPInt::operator>=(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return getSmall() >= O.getSmall();
+  return detail::SlowDynamicAPInt(*this) >= detail::SlowDynamicAPInt(O);
+}
+
+/// ---------------------------------------------------------------------------
+/// Arithmetic operators.
+/// ---------------------------------------------------------------------------
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::operator+(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    DynamicAPInt Result;
+    bool Overflow =
+        detail::addOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return DynamicAPInt(detail::SlowDynamicAPInt(*this) +
+                        detail::SlowDynamicAPInt(O));
+  }
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) +
+                      detail::SlowDynamicAPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::operator-(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    DynamicAPInt Result;
+    bool Overflow =
+        detail::subOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return DynamicAPInt(detail::SlowDynamicAPInt(*this) -
+                        detail::SlowDynamicAPInt(O));
+  }
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) -
+                      detail::SlowDynamicAPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::operator*(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    DynamicAPInt Result;
+    bool Overflow =
+        detail::mulOverflow(getSmall(), O.getSmall(), Result.getSmall());
+    if (LLVM_LIKELY(!Overflow))
+      return Result;
+    return DynamicAPInt(detail::SlowDynamicAPInt(*this) *
+                        detail::SlowDynamicAPInt(O));
+  }
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) *
+                      detail::SlowDynamicAPInt(O));
+}
+
+// Division overflows only occur when negating the minimal possible value.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::divByPositive(const DynamicAPInt &O) const {
+  assert(O > 0);
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return DynamicAPInt(getSmall() / O.getSmall());
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) /
+                      detail::SlowDynamicAPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::operator/(const DynamicAPInt &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 DynamicAPInt(getSmall() / O.getSmall());
+  }
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) /
+                      detail::SlowDynamicAPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt abs(const DynamicAPInt &X) {
+  return DynamicAPInt(X >= 0 ? X : -X);
+}
+// Division overflows only occur when negating the minimal possible value.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt ceilDiv(const DynamicAPInt &LHS,
+                                                  const DynamicAPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall())) {
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(LHS.getSmall(), RHS.getSmall())))
+      return -LHS;
+    return DynamicAPInt(detail::ceilDiv(LHS.getSmall(), RHS.getSmall()));
+  }
+  return DynamicAPInt(
+      ceilDiv(detail::SlowDynamicAPInt(LHS), detail::SlowDynamicAPInt(RHS)));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt floorDiv(const DynamicAPInt &LHS,
+                                                   const DynamicAPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall())) {
+    if (LLVM_UNLIKELY(detail::divWouldOverflow(LHS.getSmall(), RHS.getSmall())))
+      return -LHS;
+    return DynamicAPInt(detail::floorDiv(LHS.getSmall(), RHS.getSmall()));
+  }
+  return DynamicAPInt(
+      floorDiv(detail::SlowDynamicAPInt(LHS), detail::SlowDynamicAPInt(RHS)));
+}
+// The RHS is always expected to be positive, and the result
+/// is always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt mod(const DynamicAPInt &LHS,
+                                              const DynamicAPInt &RHS) {
+  if (LLVM_LIKELY(LHS.isSmall() && RHS.isSmall()))
+    return DynamicAPInt(detail::mod(LHS.getSmall(), RHS.getSmall()));
+  return DynamicAPInt(
+      mod(detail::SlowDynamicAPInt(LHS), detail::SlowDynamicAPInt(RHS)));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt gcd(const DynamicAPInt &A,
+                                              const DynamicAPInt &B) {
+  assert(A >= 0 && B >= 0 && "operands must be non-negative!");
+  if (LLVM_LIKELY(A.isSmall() && B.isSmall()))
+    return DynamicAPInt(std::gcd(A.getSmall(), B.getSmall()));
+  return DynamicAPInt(
+      gcd(detail::SlowDynamicAPInt(A), detail::SlowDynamicAPInt(B)));
+}
+
+/// Returns the least common multiple of A and B.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt lcm(const DynamicAPInt &A,
+                                              const DynamicAPInt &B) {
+  DynamicAPInt X = abs(A);
+  DynamicAPInt Y = abs(B);
+  return (X * Y) / gcd(X, Y);
+}
+
+/// This operation cannot overflow.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt
+DynamicAPInt::operator%(const DynamicAPInt &O) const {
+  if (LLVM_LIKELY(isSmall() && O.isSmall()))
+    return DynamicAPInt(getSmall() % O.getSmall());
+  return DynamicAPInt(detail::SlowDynamicAPInt(*this) %
+                      detail::SlowDynamicAPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt DynamicAPInt::operator-() const {
+  if (LLVM_LIKELY(isSmall())) {
+    if (LLVM_LIKELY(getSmall() != std::numeric_limits<int64_t>::min()))
+      return DynamicAPInt(-getSmall());
+    return DynamicAPInt(-detail::SlowDynamicAPInt(*this));
+  }
+  return DynamicAPInt(-detail::SlowDynamicAPInt(*this));
+}
+
+/// ---------------------------------------------------------------------------
+/// Assignment operators, preincrement, predecrement.
+/// ---------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::operator+=(const DynamicAPInt &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 = DynamicAPInt(detail::SlowDynamicAPInt(*this) +
+                                detail::SlowDynamicAPInt(O));
+  }
+  return *this = DynamicAPInt(detail::SlowDynamicAPInt(*this) +
+                              detail::SlowDynamicAPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::operator-=(const DynamicAPInt &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 = DynamicAPInt(detail::SlowDynamicAPInt(*this) -
+                                detail::SlowDynamicAPInt(O));
+  }
+  return *this = DynamicAPInt(detail::SlowDynamicAPInt(*this) -
+                              detail::SlowDynamicAPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::operator*=(const DynamicAPInt &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 = DynamicAPInt(detail::SlowDynamicAPInt(*this) *
+                                detail::SlowDynamicAPInt(O));
+  }
+  return *this = DynamicAPInt(detail::SlowDynamicAPInt(*this) *
+                              detail::SlowDynamicAPInt(O));
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::operator/=(const DynamicAPInt &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 = DynamicAPInt(detail::SlowDynamicAPInt(*this) /
+                              detail::SlowDynamicAPInt(O));
+}
+
+// Division overflows only occur when the divisor is -1.
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::divByPositiveInPlace(const DynamicAPInt &O) {
+  assert(O > 0);
+  if (LLVM_LIKELY(isSmall() && O.isSmall())) {
+    getSmall() /= O.getSmall();
+    return *this;
+  }
+  return *this = DynamicAPInt(detail::SlowDynamicAPInt(*this) /
+                              detail::SlowDynamicAPInt(O));
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &
+DynamicAPInt::operator%=(const DynamicAPInt &O) {
+  return *this = *this % O;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &DynamicAPInt::operator++() {
+  return *this += 1;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &DynamicAPInt::operator--() {
+  return *this -= 1;
+}
+
+/// ----------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ----------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator+=(DynamicAPInt &A,
+                                                      int64_t B) {
+  return A = A + B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator-=(DynamicAPInt &A,
+                                                      int64_t B) {
+  return A = A - B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator*=(DynamicAPInt &A,
+                                                      int64_t B) {
+  return A = A * B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator/=(DynamicAPInt &A,
+                                                      int64_t B) {
+  return A = A / B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt &operator%=(DynamicAPInt &A,
+                                                      int64_t B) {
+  return A = A % B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator+(const DynamicAPInt &A,
+                                                    int64_t B) {
+  return A + DynamicAPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator-(const DynamicAPInt &A,
+                                                    int64_t B) {
+  return A - DynamicAPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator*(const DynamicAPInt &A,
+                                                    int64_t B) {
+  return A * DynamicAPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator/(const DynamicAPInt &A,
+                                                    int64_t B) {
+  return A / DynamicAPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator%(const DynamicAPInt &A,
+                                                    int64_t B) {
+  return A % DynamicAPInt(B);
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator+(int64_t A,
+                                                    const DynamicAPInt &B) {
+  return DynamicAPInt(A) + B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator-(int64_t A,
+                                                    const DynamicAPInt &B) {
+  return DynamicAPInt(A) - B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator*(int64_t A,
+                                                    const DynamicAPInt &B) {
+  return DynamicAPInt(A) * B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator/(int64_t A,
+                                                    const DynamicAPInt &B) {
+  return DynamicAPInt(A) / B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator%(int64_t A,
+                                                    const DynamicAPInt &B) {
+  return DynamicAPInt(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 DynamicAPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() == B;
+  return A.getLarge() == B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(const DynamicAPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() != B;
+  return A.getLarge() != B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(const DynamicAPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() > B;
+  return A.getLarge() > B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(const DynamicAPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() < B;
+  return A.getLarge() < B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(const DynamicAPInt &A, int64_t B) {
+  if (LLVM_LIKELY(A.isSmall()))
+    return A.getSmall() <= B;
+  return A.getLarge() <= B;
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(const DynamicAPInt &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 DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A == B.getSmall();
+  return A == B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator!=(int64_t A, const DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A != B.getSmall();
+  return A != B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>(int64_t A, const DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A > B.getSmall();
+  return A > B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<(int64_t A, const DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A < B.getSmall();
+  return A < B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator<=(int64_t A, const DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A <= B.getSmall();
+  return A <= B.getLarge();
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool operator>=(int64_t A, const DynamicAPInt &B) {
+  if (LLVM_LIKELY(B.isSmall()))
+    return A >= B.getSmall();
+  return A >= B.getLarge();
+}
+} // namespace llvm
+
+#endif // LLVM_ADT_DYNAMICAPINT_H
diff --git a/llvm/include/llvm/ADT/SlowDynamicAPInt.h b/llvm/include/llvm/ADT/SlowDynamicAPInt.h
new file mode 100644
index 0000000000000..009deab6c6c92
--- /dev/null
+++ b/llvm/include/llvm/ADT/SlowDynamicAPInt.h
@@ -0,0 +1,140 @@
+//===- SlowDynamicAPInt.h - SlowDynamicAPInt 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 DynamicAPInt class,
+// and is not intended to be used directly.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SLOWDYNAMICAPINT_H
+#define LLVM_ADT_SLOWDYNAMICAPINT_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm::detail {
+/// A simple class providing dynamic arbitrary-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.
+/// SlowDynamicAPInt is primarily intended to be used as a slow fallback path
+/// for the upcoming DynamicAPInt class.
+class SlowDynamicAPInt {
+  APInt Val;
+
+public:
+  explicit SlowDynamicAPInt(int64_t Val);
+  SlowDynamicAPInt();
+  explicit SlowDynamicAPInt(const APInt &Val);
+  SlowDynamicAPInt &operator=(int64_t Val);
+  explicit operator int64_t() const;
+  SlowDynamicAPInt operator-() const;
+  bool operator==(const SlowDynamicAPInt &O) const;
+  bool operator!=(const SlowDynamicAPInt &O) const;
+  bool operator>(const SlowDynamicAPInt &O) const;
+  bool operator<(const SlowDynamicAPInt &O) const;
+  bool operator<=(const SlowDynamicAPInt &O) const;
+  bool operator>=(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt operator+(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt operator-(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt operator*(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt operator/(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt operator%(const SlowDynamicAPInt &O) const;
+  SlowDynamicAPInt &operator+=(const SlowDynamicAPInt &O);
+  SlowDynamicAPInt &operator-=(const SlowDynamicAPInt &O);
+  SlowDynamicAPInt &operator*=(const SlowDynamicAPInt &O);
+  SlowDynamicAPInt &operator/=(const SlowDynamicAPInt &O);
+  SlowDynamicAPInt &operator%=(const SlowDynamicAPInt &O);
+
+  SlowDynamicAPInt &operator++();
+  SlowDynamicAPInt &operator--();
+
+  friend SlowDynamicAPInt abs(const SlowDynamicAPInt &X);
+  friend SlowDynamicAPInt ceilDiv(const SlowDynamicAPInt &LHS,
+                                  const SlowDynamicAPInt &RHS);
+  friend SlowDynamicAPInt floorDiv(const SlowDynamicAPInt &LHS,
+                                   const SlowDynamicAPInt &RHS);
+  /// The operands must be non-negative for gcd.
+  friend SlowDynamicAPInt gcd(const SlowDynamicAPInt &A,
+                              const SlowDynamicAPInt &B);
+
+  /// Overload to compute a hash_code for a SlowDynamicAPInt value.
+  friend hash_code hash_value(const SlowDynamicAPInt &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 SlowDynamicAPInt &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.
+SlowDynamicAPInt mod(const SlowDynamicAPInt &LHS, const SlowDynamicAPInt &RHS);
+
+/// Returns the least common multiple of A and B.
+SlowDynamicAPInt lcm(const SlowDynamicAPInt &A, const SlowDynamicAPInt &B);
+
+/// Redeclarations of friend declarations above to
+/// make it discoverable by lookups.
+SlowDynamicAPInt abs(const SlowDynamicAPInt &X);
+SlowDynamicAPInt ceilDiv(const SlowDynamicAPInt &LHS,
+                         const SlowDynamicAPInt &RHS);
+SlowDynamicAPInt floorDiv(const SlowDynamicAPInt &LHS,
+                          const SlowDynamicAPInt &RHS);
+SlowDynamicAPInt gcd(const SlowDynamicAPInt &A, const SlowDynamicAPInt &B);
+hash_code hash_value(const SlowDynamicAPInt &X); // NOLINT
+
+/// ---------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ---------------------------------------------------------------------------
+SlowDynamicAPInt &operator+=(SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt &operator-=(SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt &operator*=(SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt &operator/=(SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt &operator%=(SlowDynamicAPInt &A, int64_t B);
+
+bool operator==(const SlowDynamicAPInt &A, int64_t B);
+bool operator!=(const SlowDynamicAPInt &A, int64_t B);
+bool operator>(const SlowDynamicAPInt &A, int64_t B);
+bool operator<(const SlowDynamicAPInt &A, int64_t B);
+bool operator<=(const SlowDynamicAPInt &A, int64_t B);
+bool operator>=(const SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt operator+(const SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt operator-(const SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt operator*(const SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt operator/(const SlowDynamicAPInt &A, int64_t B);
+SlowDynamicAPInt operator%(const SlowDynamicAPInt &A, int64_t B);
+
+bool operator==(int64_t A, const SlowDynamicAPInt &B);
+bool operator!=(int64_t A, const SlowDynamicAPInt &B);
+bool operator>(int64_t A, const SlowDynamicAPInt &B);
+bool operator<(int64_t A, const SlowDynamicAPInt &B);
+bool operator<=(int64_t A, const SlowDynamicAPInt &B);
+bool operator>=(int64_t A, const SlowDynamicAPInt &B);
+SlowDynamicAPInt operator+(int64_t A, const SlowDynamicAPInt &B);
+SlowDynamicAPInt operator-(int64_t A, const SlowDynamicAPInt &B);
+SlowDynamicAPInt operator*(int64_t A, const SlowDynamicAPInt &B);
+SlowDynamicAPInt operator/(int64_t A, const SlowDynamicAPInt &B);
+SlowDynamicAPInt operator%(int64_t A, const SlowDynamicAPInt &B);
+} // namespace llvm::detail
+
+#endif // LLVM_ADT_SLOWDYNAMICAPINT_H
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 5df36f811efe9..507eef2451063 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
+  DynamicAPInt.cpp
   MSP430Attributes.cpp
   MSP430AttributeParser.cpp
   NativeFormatting.cpp
@@ -223,6 +224,7 @@ add_llvm_component_library(LLVMSupport
   SHA1.cpp
   SHA256.cpp
   Signposts.cpp
+  SlowDynamicAPInt.cpp
   SmallPtrSet.cpp
   SmallVector.cpp
   SourceMgr.cpp
diff --git a/llvm/lib/Support/DynamicAPInt.cpp b/llvm/lib/Support/DynamicAPInt.cpp
new file mode 100644
index 0000000000000..ed4d13d9786ce
--- /dev/null
+++ b/llvm/lib/Support/DynamicAPInt.cpp
@@ -0,0 +1,29 @@
+//===- DyanmicAPInt.cpp - DynamicAPInt Implementation -----------*- 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
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/ADT/DynamicAPInt.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 DynamicAPInt &X) {
+  if (X.isSmall())
+    return llvm::hash_value(X.getSmall());
+  return detail::hash_value(X.getLarge());
+}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+raw_ostream &DynamicAPInt::print(raw_ostream &OS) const {
+  if (isSmall())
+    return OS << ValSmall;
+  return OS << ValLarge;
+}
+
+void DynamicAPInt::dump() const { print(dbgs()); }
+#endif
diff --git a/llvm/lib/Support/SlowDynamicAPInt.cpp b/llvm/lib/Support/SlowDynamicAPInt.cpp
new file mode 100644
index 0000000000000..e8a4d266a7801
--- /dev/null
+++ b/llvm/lib/Support/SlowDynamicAPInt.cpp
@@ -0,0 +1,288 @@
+//===- SlowDynamicAPInt.cpp - SlowDyanmicAPInt Implementation -------------===//
+//
+// 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/SlowDynamicAPInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace detail;
+
+SlowDynamicAPInt::SlowDynamicAPInt(int64_t Val)
+    : Val(64, Val, /*isSigned=*/true) {}
+SlowDynamicAPInt::SlowDynamicAPInt() : SlowDynamicAPInt(0) {}
+SlowDynamicAPInt::SlowDynamicAPInt(const APInt &Val) : Val(Val) {}
+SlowDynamicAPInt &SlowDynamicAPInt::operator=(int64_t Val) {
+  return *this = SlowDynamicAPInt(Val);
+}
+SlowDynamicAPInt::operator int64_t() const { return Val.getSExtValue(); }
+
+hash_code detail::hash_value(const SlowDynamicAPInt &X) {
+  return hash_value(X.Val);
+}
+
+/// ---------------------------------------------------------------------------
+/// Convenience operator overloads for int64_t.
+/// ---------------------------------------------------------------------------
+SlowDynamicAPInt &detail::operator+=(SlowDynamicAPInt &A, int64_t B) {
+  return A += SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt &detail::operator-=(SlowDynamicAPInt &A, int64_t B) {
+  return A -= SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt &detail::operator*=(SlowDynamicAPInt &A, int64_t B) {
+  return A *= SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt &detail::operator/=(SlowDynamicAPInt &A, int64_t B) {
+  return A /= SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt &detail::operator%=(SlowDynamicAPInt &A, int64_t B) {
+  return A %= SlowDynamicAPInt(B);
+}
+
+bool detail::operator==(const SlowDynamicAPInt &A, int64_t B) {
+  return A == SlowDynamicAPInt(B);
+}
+bool detail::operator!=(const SlowDynamicAPInt &A, int64_t B) {
+  return A != SlowDynamicAPInt(B);
+}
+bool detail::operator>(const SlowDynamicAPInt &A, int64_t B) {
+  return A > SlowDynamicAPInt(B);
+}
+bool detail::operator<(const SlowDynamicAPInt &A, int64_t B) {
+  return A < SlowDynamicAPInt(B);
+}
+bool detail::operator<=(const SlowDynamicAPInt &A, int64_t B) {
+  return A <= SlowDynamicAPInt(B);
+}
+bool detail::operator>=(const SlowDynamicAPInt &A, int64_t B) {
+  return A >= SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt detail::operator+(const SlowDynamicAPInt &A, int64_t B) {
+  return A + SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt detail::operator-(const SlowDynamicAPInt &A, int64_t B) {
+  return A - SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt detail::operator*(const SlowDynamicAPInt &A, int64_t B) {
+  return A * SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt detail::operator/(const SlowDynamicAPInt &A, int64_t B) {
+  return A / SlowDynamicAPInt(B);
+}
+SlowDynamicAPInt detail::operator%(const SlowDynamicAPInt &A, int64_t B) {
+  return A % SlowDynamicAPInt(B);
+}
+
+bool detail::operator==(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) == B;
+}
+bool detail::operator!=(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) != B;
+}
+bool detail::operator>(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) > B;
+}
+bool detail::operator<(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) < B;
+}
+bool detail::operator<=(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) <= B;
+}
+bool detail::operator>=(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) >= B;
+}
+SlowDynamicAPInt detail::operator+(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) + B;
+}
+SlowDynamicAPInt detail::operator-(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) - B;
+}
+SlowDynamicAPInt detail::operator*(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) * B;
+}
+SlowDynamicAPInt detail::operator/(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(A) / B;
+}
+SlowDynamicAPInt detail::operator%(int64_t A, const SlowDynamicAPInt &B) {
+  return SlowDynamicAPInt(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 SlowDynamicAPInt::operator==(const SlowDynamicAPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width) == O.Val.sext(Width);
+}
+bool SlowDynamicAPInt::operator!=(const SlowDynamicAPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width) != O.Val.sext(Width);
+}
+bool SlowDynamicAPInt::operator>(const SlowDynamicAPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).sgt(O.Val.sext(Width));
+}
+bool SlowDynamicAPInt::operator<(const SlowDynamicAPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).slt(O.Val.sext(Width));
+}
+bool SlowDynamicAPInt::operator<=(const SlowDynamicAPInt &O) const {
+  unsigned Width = getMaxWidth(Val, O.Val);
+  return Val.sext(Width).sle(O.Val.sext(Width));
+}
+bool SlowDynamicAPInt::operator>=(const SlowDynamicAPInt &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;
+}
+
+SlowDynamicAPInt SlowDynamicAPInt::operator+(const SlowDynamicAPInt &O) const {
+  return SlowDynamicAPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sadd_ov)));
+}
+SlowDynamicAPInt SlowDynamicAPInt::operator-(const SlowDynamicAPInt &O) const {
+  return SlowDynamicAPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::ssub_ov)));
+}
+SlowDynamicAPInt SlowDynamicAPInt::operator*(const SlowDynamicAPInt &O) const {
+  return SlowDynamicAPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::smul_ov)));
+}
+SlowDynamicAPInt SlowDynamicAPInt::operator/(const SlowDynamicAPInt &O) const {
+  return SlowDynamicAPInt(
+      runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sdiv_ov)));
+}
+SlowDynamicAPInt detail::abs(const SlowDynamicAPInt &X) {
+  return X >= 0 ? X : -X;
+}
+SlowDynamicAPInt detail::ceilDiv(const SlowDynamicAPInt &LHS,
+                                 const SlowDynamicAPInt &RHS) {
+  if (RHS == -1)
+    return -LHS;
+  unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
+  return SlowDynamicAPInt(APIntOps::RoundingSDiv(
+      LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::UP));
+}
+SlowDynamicAPInt detail::floorDiv(const SlowDynamicAPInt &LHS,
+                                  const SlowDynamicAPInt &RHS) {
+  if (RHS == -1)
+    return -LHS;
+  unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
+  return SlowDynamicAPInt(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.
+SlowDynamicAPInt detail::mod(const SlowDynamicAPInt &LHS,
+                             const SlowDynamicAPInt &RHS) {
+  assert(RHS >= 1 && "mod is only supported for positive divisors!");
+  return LHS % RHS < 0 ? LHS % RHS + RHS : LHS % RHS;
+}
+
+SlowDynamicAPInt detail::gcd(const SlowDynamicAPInt &A,
+                             const SlowDynamicAPInt &B) {
+  assert(A >= 0 && B >= 0 && "operands must be non-negative!");
+  unsigned Width = getMaxWidth(A.Val, B.Val);
+  return SlowDynamicAPInt(
+      APIntOps::GreatestCommonDivisor(A.Val.sext(Width), B.Val.sext(Width)));
+}
+
+/// Returns the least common multiple of A and B.
+SlowDynamicAPInt detail::lcm(const SlowDynamicAPInt &A,
+                             const SlowDynamicAPInt &B) {
+  SlowDynamicAPInt X = abs(A);
+  SlowDynamicAPInt Y = abs(B);
+  return (X * Y) / gcd(X, Y);
+}
+
+/// This operation cannot overflow.
+SlowDynamicAPInt SlowDynamicAPInt::operator%(const SlowDynamicAPInt &O) const {
+  unsigned Width = std::max(Val.getBitWidth(), O.Val.getBitWidth());
+  return SlowDynamicAPInt(Val.sext(Width).srem(O.Val.sext(Width)));
+}
+
+SlowDynamicAPInt SlowDynamicAPInt::operator-() const {
+  if (Val.isMinSignedValue()) {
+    /// Overflow only occurs when the value is the minimum possible value.
+    APInt Ret = Val.sext(2 * Val.getBitWidth());
+    return SlowDynamicAPInt(-Ret);
+  }
+  return SlowDynamicAPInt(-Val);
+}
+
+/// ---------------------------------------------------------------------------
+/// Assignment operators, preincrement, predecrement.
+/// ---------------------------------------------------------------------------
+SlowDynamicAPInt &SlowDynamicAPInt::operator+=(const SlowDynamicAPInt &O) {
+  *this = *this + O;
+  return *this;
+}
+SlowDynamicAPInt &SlowDynamicAPInt::operator-=(const SlowDynamicAPInt &O) {
+  *this = *this - O;
+  return *this;
+}
+SlowDynamicAPInt &SlowDynamicAPInt::operator*=(const SlowDynamicAPInt &O) {
+  *this = *this * O;
+  return *this;
+}
+SlowDynamicAPInt &SlowDynamicAPInt::operator/=(const SlowDynamicAPInt &O) {
+  *this = *this / O;
+  return *this;
+}
+SlowDynamicAPInt &SlowDynamicAPInt::operator%=(const SlowDynamicAPInt &O) {
+  *this = *this % O;
+  return *this;
+}
+SlowDynamicAPInt &SlowDynamicAPInt::operator++() {
+  *this += 1;
+  return *this;
+}
+
+SlowDynamicAPInt &SlowDynamicAPInt::operator--() {
+  *this -= 1;
+  return *this;
+}
+
+/// ---------------------------------------------------------------------------
+/// Printing.
+/// ---------------------------------------------------------------------------
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+void SlowDynamicAPInt::print(raw_ostream &OS) const { OS << Val; }
+
+void SlowDynamicAPInt::dump() const { print(dbgs()); }
+#endif
diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index 85c140e63fecd..c4dd53bcac087 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -53,6 +53,7 @@ add_llvm_unittest(ADTTests
   LazyAtomicPointerTest.cpp
   MappedIteratorTest.cpp
   MapVectorTest.cpp
+  DynamicAPIntTest.cpp
   PackedVectorTest.cpp
   PagedVectorTest.cpp
   PointerEmbeddedIntTest.cpp
diff --git a/llvm/unittests/ADT/DynamicAPIntTest.cpp b/llvm/unittests/ADT/DynamicAPIntTest.cpp
new file mode 100644
index 0000000000000..932b750608b3e
--- /dev/null
+++ b/llvm/unittests/ADT/DynamicAPIntTest.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/DynamicAPInt.h"
+#include "llvm/ADT/SlowDynamicAPInt.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<DynamicAPInt, detail::SlowDynamicAPInt>;
+
+// 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, DynamicAPInt>())
+      return "MPInt";
+    if (std::is_same<T, detail::SlowDynamicAPInt>())
+      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/Barvinok.h b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
index cd1ea3a9571ba..c9a1645b5e632 100644
--- a/mlir/include/mlir/Analysis/Presburger/Barvinok.h
+++ b/mlir/include/mlir/Analysis/Presburger/Barvinok.h
@@ -74,7 +74,7 @@ inline PolyhedronH defineHRep(int numVars, int numSymbols = 0) {
 /// Barvinok, A., and J. E. Pommersheim. "An algorithmic theory of lattice
 /// points in polyhedra." p. 107 If it has more rays than the dimension, return
 /// 0.
-MPInt getIndex(const ConeV &cone);
+DynamicAPInt getIndex(const ConeV &cone);
 
 /// Given a cone in H-representation, return its dual. The dual cone is in
 /// V-representation.
diff --git a/mlir/include/mlir/Analysis/Presburger/Fraction.h b/mlir/include/mlir/Analysis/Presburger/Fraction.h
index c07bb767f50bf..f4f1be97147bf 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/DynamicAPInt.h"
 
 namespace mlir {
 namespace presburger {
+using llvm::DynamicAPInt;
 
 /// A class to represent fractions. The sign of the fraction is represented
 /// in the sign of the numerator; the denominator is always positive.
@@ -30,7 +30,7 @@ struct Fraction {
   Fraction() = default;
 
   /// Construct a Fraction from a numerator and denominator.
-  Fraction(const MPInt &oNum, const MPInt &oDen = MPInt(1))
+  Fraction(const DynamicAPInt &oNum, const DynamicAPInt &oDen = DynamicAPInt(1))
       : num(oNum), den(oDen) {
     if (den < 0) {
       num = -num;
@@ -38,14 +38,16 @@ struct Fraction {
     }
   }
   /// Overloads for passing literals.
-  Fraction(const MPInt &num, int64_t den) : Fraction(num, MPInt(den)) {}
-  Fraction(int64_t num, const MPInt &den = MPInt(1))
-      : Fraction(MPInt(num), den) {}
-  Fraction(int64_t num, int64_t den) : Fraction(MPInt(num), MPInt(den)) {}
+  Fraction(const DynamicAPInt &num, int64_t den)
+      : Fraction(num, DynamicAPInt(den)) {}
+  Fraction(int64_t num, const DynamicAPInt &den = DynamicAPInt(1))
+      : Fraction(DynamicAPInt(num), den) {}
+  Fraction(int64_t num, int64_t den)
+      : Fraction(DynamicAPInt(num), DynamicAPInt(den)) {}
 
   // Return the value of the fraction as an integer. This should only be called
   // when the fraction's value is really an integer.
-  MPInt getAsInteger() const {
+  DynamicAPInt getAsInteger() const {
     assert(num % den == 0 && "Get as integer called on non-integral fraction!");
     return num / den;
   }
@@ -56,14 +58,14 @@ struct Fraction {
 
   /// The numerator and denominator, respectively. The denominator is always
   /// positive.
-  MPInt num{0}, den{1};
+  DynamicAPInt num{0}, den{1};
 };
 
 /// Three-way comparison between two fractions.
 /// Returns +1, 0, and -1 if the first fraction is greater than, equal to, or
 /// less than the second fraction, respectively.
 inline int compare(const Fraction &x, const Fraction &y) {
-  MPInt diff = x.num * y.den - y.num * x.den;
+  DynamicAPInt diff = x.num * y.den - y.num * x.den;
   if (diff > 0)
     return +1;
   if (diff < 0)
@@ -71,9 +73,9 @@ inline int compare(const Fraction &x, const Fraction &y) {
   return 0;
 }
 
-inline MPInt floor(const Fraction &f) { return floorDiv(f.num, f.den); }
+inline DynamicAPInt floor(const Fraction &f) { return floorDiv(f.num, f.den); }
 
-inline MPInt ceil(const Fraction &f) { return ceilDiv(f.num, f.den); }
+inline DynamicAPInt ceil(const Fraction &f) { return ceilDiv(f.num, f.den); }
 
 inline Fraction operator-(const Fraction &x) { return Fraction(-x.num, x.den); }
 
@@ -109,7 +111,7 @@ inline Fraction abs(const Fraction &f) {
 inline Fraction reduce(const Fraction &f) {
   if (f == Fraction(0))
     return Fraction(0, 1);
-  MPInt g = gcd(abs(f.num), abs(f.den));
+  DynamicAPInt g = gcd(abs(f.num), abs(f.den));
   return Fraction(f.num / g, f.den / g);
 }
 
@@ -130,8 +132,8 @@ inline Fraction operator-(const Fraction &x, const Fraction &y) {
 }
 
 // Find the integer nearest to a given fraction.
-inline MPInt round(const Fraction &f) {
-  MPInt rem = f.num % f.den;
+inline DynamicAPInt round(const Fraction &f) {
+  DynamicAPInt rem = f.num % f.den;
   return (f.num / f.den) + (rem > f.den / 2);
 }
 
diff --git a/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h b/mlir/include/mlir/Analysis/Presburger/IntegerRelation.h
index 163f365c623d7..40e96e2583d22 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/DynamicAPInt.h"
 #include <optional>
 
 namespace mlir {
 namespace presburger {
+using llvm::DynamicAPInt;
+using llvm::int64fromDynamicAPInt;
 
 class IntegerRelation;
 class IntegerPolyhedron;
@@ -166,16 +169,18 @@ class IntegerRelation {
   bool isSubsetOf(const IntegerRelation &other) const;
 
   /// Returns the value at the specified equality row and column.
-  inline MPInt atEq(unsigned i, unsigned j) const { return equalities(i, j); }
+  inline DynamicAPInt atEq(unsigned i, unsigned j) const {
+    return equalities(i, j);
+  }
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
   inline int64_t atEq64(unsigned i, unsigned j) const {
     return int64_t(equalities(i, j));
   }
-  inline MPInt &atEq(unsigned i, unsigned j) { return equalities(i, j); }
+  inline DynamicAPInt &atEq(unsigned i, unsigned j) { return equalities(i, j); }
 
   /// Returns the value at the specified inequality row and column.
-  inline MPInt atIneq(unsigned i, unsigned j) const {
+  inline DynamicAPInt atIneq(unsigned i, unsigned j) const {
     return inequalities(i, j);
   }
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
@@ -183,7 +188,9 @@ class IntegerRelation {
   inline int64_t atIneq64(unsigned i, unsigned j) const {
     return int64_t(inequalities(i, j));
   }
-  inline MPInt &atIneq(unsigned i, unsigned j) { return inequalities(i, j); }
+  inline DynamicAPInt &atIneq(unsigned i, unsigned j) {
+    return inequalities(i, j);
+  }
 
   unsigned getNumConstraints() const {
     return getNumInequalities() + getNumEqualities();
@@ -217,10 +224,10 @@ class IntegerRelation {
     return inequalities.getNumReservedRows();
   }
 
-  inline ArrayRef<MPInt> getEquality(unsigned idx) const {
+  inline ArrayRef<DynamicAPInt> getEquality(unsigned idx) const {
     return equalities.getRow(idx);
   }
-  inline ArrayRef<MPInt> getInequality(unsigned idx) const {
+  inline ArrayRef<DynamicAPInt> getInequality(unsigned idx) const {
     return inequalities.getRow(idx);
   }
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
@@ -297,13 +304,15 @@ class IntegerRelation {
   unsigned appendVar(VarKind kind, unsigned num = 1);
 
   /// Adds an inequality (>= 0) from the coefficients specified in `inEq`.
-  void addInequality(ArrayRef<MPInt> inEq);
+  void addInequality(ArrayRef<DynamicAPInt> inEq);
   void addInequality(ArrayRef<int64_t> inEq) {
-    addInequality(getMPIntVec(inEq));
+    addInequality(getDynamicAPIntVec(inEq));
   }
   /// Adds an equality from the coefficients specified in `eq`.
-  void addEquality(ArrayRef<MPInt> eq);
-  void addEquality(ArrayRef<int64_t> eq) { addEquality(getMPIntVec(eq)); }
+  void addEquality(ArrayRef<DynamicAPInt> eq);
+  void addEquality(ArrayRef<int64_t> eq) {
+    addEquality(getDynamicAPIntVec(eq));
+  }
 
   /// Eliminate the `posB^th` local variable, replacing every instance of it
   /// with the `posA^th` local variable. This should be used when the two
@@ -338,7 +347,7 @@ class IntegerRelation {
   /// For a generic integer sampling operation, findIntegerSample is more
   /// robust and should be preferred. Note that Domain is minimized first, then
   /// range.
-  MaybeOptimum<SmallVector<MPInt, 8>> findIntegerLexMin() const;
+  MaybeOptimum<SmallVector<DynamicAPInt, 8>> findIntegerLexMin() const;
 
   /// Swap the posA^th variable with the posB^th variable.
   virtual void swapVar(unsigned posA, unsigned posB);
@@ -348,9 +357,9 @@ class IntegerRelation {
 
   /// Sets the `values.size()` variables starting at `po`s to the specified
   /// values and removes them.
-  void setAndEliminate(unsigned pos, ArrayRef<MPInt> values);
+  void setAndEliminate(unsigned pos, ArrayRef<DynamicAPInt> values);
   void setAndEliminate(unsigned pos, ArrayRef<int64_t> values) {
-    setAndEliminate(pos, getMPIntVec(values));
+    setAndEliminate(pos, getDynamicAPIntVec(values));
   }
 
   /// Replaces the contents of this IntegerRelation with `other`.
@@ -399,26 +408,26 @@ class IntegerRelation {
   ///
   /// Returns an integer sample point if one exists, or an empty Optional
   /// otherwise. The returned value also includes values of local ids.
-  std::optional<SmallVector<MPInt, 8>> findIntegerSample() const;
+  std::optional<SmallVector<DynamicAPInt, 8>> findIntegerSample() const;
 
   /// Compute an overapproximation of the number of integer points in the
   /// relation. Symbol vars currently not supported. If the computed
   /// overapproximation is infinite, an empty optional is returned.
-  std::optional<MPInt> computeVolume() const;
+  std::optional<DynamicAPInt> computeVolume() const;
 
   /// Returns true if the given point satisfies the constraints, or false
   /// otherwise. Takes the values of all vars including locals.
-  bool containsPoint(ArrayRef<MPInt> point) const;
+  bool containsPoint(ArrayRef<DynamicAPInt> point) const;
   bool containsPoint(ArrayRef<int64_t> point) const {
-    return containsPoint(getMPIntVec(point));
+    return containsPoint(getDynamicAPIntVec(point));
   }
   /// Given the values of non-local vars, return a satisfying assignment to the
   /// local if one exists, or an empty optional otherwise.
-  std::optional<SmallVector<MPInt, 8>>
-  containsPointNoLocal(ArrayRef<MPInt> point) const;
-  std::optional<SmallVector<MPInt, 8>>
+  std::optional<SmallVector<DynamicAPInt, 8>>
+  containsPointNoLocal(ArrayRef<DynamicAPInt> point) const;
+  std::optional<SmallVector<DynamicAPInt, 8>>
   containsPointNoLocal(ArrayRef<int64_t> point) const {
-    return containsPointNoLocal(getMPIntVec(point));
+    return containsPointNoLocal(getDynamicAPIntVec(point));
   }
 
   /// Returns a `DivisonRepr` representing the division representation of local
@@ -433,15 +442,16 @@ class IntegerRelation {
   DivisionRepr getLocalReprs(std::vector<MaybeLocalRepr> *repr = nullptr) const;
 
   /// Adds a constant bound for the specified variable.
-  void addBound(BoundType type, unsigned pos, const MPInt &value);
+  void addBound(BoundType type, unsigned pos, const DynamicAPInt &value);
   void addBound(BoundType type, unsigned pos, int64_t value) {
-    addBound(type, pos, MPInt(value));
+    addBound(type, pos, DynamicAPInt(value));
   }
 
   /// Adds a constant bound for the specified expression.
-  void addBound(BoundType type, ArrayRef<MPInt> expr, const MPInt &value);
+  void addBound(BoundType type, ArrayRef<DynamicAPInt> expr,
+                const DynamicAPInt &value);
   void addBound(BoundType type, ArrayRef<int64_t> expr, int64_t value) {
-    addBound(type, getMPIntVec(expr), MPInt(value));
+    addBound(type, getDynamicAPIntVec(expr), DynamicAPInt(value));
   }
 
   /// Adds a new local variable as the floordiv of an affine function of other
@@ -449,9 +459,10 @@ class IntegerRelation {
   /// respect to a positive constant `divisor`. Two constraints are added to the
   /// system to capture equivalence with the floordiv:
   /// q = dividend floordiv c    <=>   c*q <= dividend <= c*q + c - 1.
-  void addLocalFloorDiv(ArrayRef<MPInt> dividend, const MPInt &divisor);
+  void addLocalFloorDiv(ArrayRef<DynamicAPInt> dividend,
+                        const DynamicAPInt &divisor);
   void addLocalFloorDiv(ArrayRef<int64_t> dividend, int64_t divisor) {
-    addLocalFloorDiv(getMPIntVec(dividend), MPInt(divisor));
+    addLocalFloorDiv(getDynamicAPIntVec(dividend), DynamicAPInt(divisor));
   }
 
   /// Projects out (aka eliminates) `num` variables starting at position
@@ -507,10 +518,11 @@ class IntegerRelation {
   /// equality). Ex: if the lower bound is [(s0 + s2 - 1) floordiv 32] for a
   /// system with three symbolic variables, *lb = [1, 0, 1], lbDivisor = 32. See
   /// comments at function definition for examples.
-  std::optional<MPInt> getConstantBoundOnDimSize(
-      unsigned pos, SmallVectorImpl<MPInt> *lb = nullptr,
-      MPInt *boundFloorDivisor = nullptr, SmallVectorImpl<MPInt> *ub = nullptr,
-      unsigned *minLbPos = nullptr, unsigned *minUbPos = nullptr) const;
+  std::optional<DynamicAPInt> getConstantBoundOnDimSize(
+      unsigned pos, SmallVectorImpl<DynamicAPInt> *lb = nullptr,
+      DynamicAPInt *boundFloorDivisor = nullptr,
+      SmallVectorImpl<DynamicAPInt> *ub = nullptr, unsigned *minLbPos = nullptr,
+      unsigned *minUbPos = nullptr) const;
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
   std::optional<int64_t> getConstantBoundOnDimSize64(
@@ -518,27 +530,30 @@ class IntegerRelation {
       int64_t *boundFloorDivisor = nullptr,
       SmallVectorImpl<int64_t> *ub = nullptr, unsigned *minLbPos = nullptr,
       unsigned *minUbPos = nullptr) const {
-    SmallVector<MPInt, 8> ubMPInt, lbMPInt;
-    MPInt boundFloorDivisorMPInt;
-    std::optional<MPInt> result = getConstantBoundOnDimSize(
-        pos, &lbMPInt, &boundFloorDivisorMPInt, &ubMPInt, minLbPos, minUbPos);
+    SmallVector<DynamicAPInt, 8> ubDynamicAPInt, lbDynamicAPInt;
+    DynamicAPInt boundFloorDivisorDynamicAPInt;
+    std::optional<DynamicAPInt> result = getConstantBoundOnDimSize(
+        pos, &lbDynamicAPInt, &boundFloorDivisorDynamicAPInt, &ubDynamicAPInt,
+        minLbPos, minUbPos);
     if (lb)
-      *lb = getInt64Vec(lbMPInt);
+      *lb = getInt64Vec(lbDynamicAPInt);
     if (ub)
-      *ub = getInt64Vec(ubMPInt);
+      *ub = getInt64Vec(ubDynamicAPInt);
     if (boundFloorDivisor)
-      *boundFloorDivisor = static_cast<int64_t>(boundFloorDivisorMPInt);
-    return llvm::transformOptional(result, int64FromMPInt);
+      *boundFloorDivisor = static_cast<int64_t>(boundFloorDivisorDynamicAPInt);
+    return llvm::transformOptional(result, int64fromDynamicAPInt);
   }
 
   /// Returns the constant bound for the pos^th variable if there is one;
   /// std::nullopt otherwise.
-  std::optional<MPInt> getConstantBound(BoundType type, unsigned pos) const;
+  std::optional<DynamicAPInt> getConstantBound(BoundType type,
+                                               unsigned pos) const;
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
   std::optional<int64_t> getConstantBound64(BoundType type,
                                             unsigned pos) const {
-    return llvm::transformOptional(getConstantBound(type, pos), int64FromMPInt);
+    return llvm::transformOptional(getConstantBound(type, pos),
+                                   int64fromDynamicAPInt);
   }
 
   /// Removes constraints that are independent of (i.e., do not have a
@@ -746,12 +761,13 @@ class IntegerRelation {
   /// Returns the constant lower bound if isLower is true, and the upper
   /// bound if isLower is false.
   template <bool isLower>
-  std::optional<MPInt> computeConstantLowerOrUpperBound(unsigned pos);
+  std::optional<DynamicAPInt> computeConstantLowerOrUpperBound(unsigned pos);
   /// The same, but casts to int64_t. This is unsafe and will assert-fail if the
   /// value does not fit in an int64_t.
   template <bool isLower>
   std::optional<int64_t> computeConstantLowerOrUpperBound64(unsigned pos) {
-    return computeConstantLowerOrUpperBound<isLower>(pos).map(int64FromMPInt);
+    return computeConstantLowerOrUpperBound<isLower>(pos).map(
+        int64fromDynamicAPInt);
   }
 
   /// Eliminates a single variable at `position` from equality and inequality
diff --git a/mlir/include/mlir/Analysis/Presburger/LinearTransform.h b/mlir/include/mlir/Analysis/Presburger/LinearTransform.h
index b5c761439f0b7..eeac9f1dc3938 100644
--- a/mlir/include/mlir/Analysis/Presburger/LinearTransform.h
+++ b/mlir/include/mlir/Analysis/Presburger/LinearTransform.h
@@ -40,13 +40,15 @@ class LinearTransform {
 
   // The given vector is interpreted as a row vector v. Post-multiply v with
   // this transform, say T, and return vT.
-  SmallVector<MPInt, 8> preMultiplyWithRow(ArrayRef<MPInt> rowVec) const {
+  SmallVector<DynamicAPInt, 8>
+  preMultiplyWithRow(ArrayRef<DynamicAPInt> rowVec) const {
     return matrix.preMultiplyWithRow(rowVec);
   }
 
   // The given vector is interpreted as a column vector v. Pre-multiply v with
   // this transform, say T, and return Tv.
-  SmallVector<MPInt, 8> postMultiplyWithColumn(ArrayRef<MPInt> colVec) const {
+  SmallVector<DynamicAPInt, 8>
+  postMultiplyWithColumn(ArrayRef<DynamicAPInt> colVec) const {
     return matrix.postMultiplyWithColumn(colVec);
   }
 
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/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h
index c20a7bcecd52d..61c18dfb1efbe 100644
--- a/mlir/include/mlir/Analysis/Presburger/Matrix.h
+++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h
@@ -7,8 +7,8 @@
 //===----------------------------------------------------------------------===//
 //
 // This is a simple 2D matrix class that supports reading, writing, resizing,
-// swapping rows, and swapping columns. It can hold integers (MPInt) or rational
-// numbers (Fraction).
+// swapping rows, and swapping columns. It can hold integers (DynamicAPInt) or
+// rational numbers (Fraction).
 //
 //===----------------------------------------------------------------------===//
 
@@ -34,13 +34,13 @@ namespace presburger {
 /// (i, j) is stored at data[i*nReservedColumns + j]. The reserved but unused
 /// columns always have all zero values. The reserved rows are just reserved
 /// space in the underlying SmallVector's capacity.
-/// This class only works for the types MPInt and Fraction, since the method
-/// implementations are in the Matrix.cpp file. Only these two types have
+/// This class only works for the types DynamicAPInt and Fraction, since the
+/// method implementations are in the Matrix.cpp file. Only these two types have
 /// been explicitly instantiated there.
 template <typename T>
 class Matrix {
-  static_assert(std::is_same_v<T, MPInt> || std::is_same_v<T, Fraction>,
-                "T must be MPInt or Fraction.");
+  static_assert(std::is_same_v<T, DynamicAPInt> || std::is_same_v<T, Fraction>,
+                "T must be DynamicAPInt or Fraction.");
 
 public:
   Matrix() = delete;
@@ -244,19 +244,19 @@ class Matrix {
   SmallVector<T, 16> data;
 };
 
-extern template class Matrix<MPInt>;
+extern template class Matrix<DynamicAPInt>;
 extern template class Matrix<Fraction>;
 
 // An inherited class for integer matrices, with no new data attributes.
 // This is only used for the matrix-related methods which apply only
 // to integers (hermite normal form computation and row normalisation).
-class IntMatrix : public Matrix<MPInt> {
+class IntMatrix : public Matrix<DynamicAPInt> {
 public:
   IntMatrix(unsigned rows, unsigned columns, unsigned reservedRows = 0,
             unsigned reservedColumns = 0)
-      : Matrix<MPInt>(rows, columns, reservedRows, reservedColumns){};
+      : Matrix<DynamicAPInt>(rows, columns, reservedRows, reservedColumns){};
 
-  IntMatrix(Matrix<MPInt> m) : Matrix<MPInt>(std::move(m)){};
+  IntMatrix(Matrix<DynamicAPInt> m) : Matrix<DynamicAPInt>(std::move(m)){};
 
   /// Return the identity matrix of the specified dimension.
   static IntMatrix identity(unsigned dimension);
@@ -275,10 +275,10 @@ class IntMatrix : public Matrix<MPInt> {
 
   /// Divide the first `nCols` of the specified row by their GCD.
   /// Returns the GCD of the first `nCols` of the specified row.
-  MPInt normalizeRow(unsigned row, unsigned nCols);
+  DynamicAPInt normalizeRow(unsigned row, unsigned nCols);
   /// Divide the columns of the specified row by their GCD.
   /// Returns the GCD of the columns of the specified row.
-  MPInt normalizeRow(unsigned row);
+  DynamicAPInt normalizeRow(unsigned row);
 
   // Compute the determinant of the matrix (cubic time).
   // Stores the integer inverse of the matrix in the pointer
@@ -287,7 +287,7 @@ class IntMatrix : public Matrix<MPInt> {
   // For a matrix M, the integer inverse is the matrix M' such that
   // M x M' = M'  M = det(M) x I.
   // Assert-fails if the matrix is not square.
-  MPInt determinant(IntMatrix *inverse = nullptr) const;
+  DynamicAPInt determinant(IntMatrix *inverse = nullptr) const;
 };
 
 // An inherited class for rational matrices, with no new data attributes.
diff --git a/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h b/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
index 236cc90ad66ac..fcc39bf0e0537 100644
--- a/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
+++ b/mlir/include/mlir/Analysis/Presburger/PWMAFunction.h
@@ -67,7 +67,9 @@ class MultiAffineFunction {
   /// Get a matrix with each row representing row^th output expression.
   const IntMatrix &getOutputMatrix() const { return output; }
   /// Get the `i^th` output expression.
-  ArrayRef<MPInt> getOutputExpr(unsigned i) const { return output.getRow(i); }
+  ArrayRef<DynamicAPInt> getOutputExpr(unsigned i) const {
+    return output.getRow(i);
+  }
 
   /// Get the divisions used in this function.
   const DivisionRepr &getDivs() const { return divs; }
@@ -80,9 +82,9 @@ class MultiAffineFunction {
   void mergeDivs(MultiAffineFunction &other);
 
   //// Return the output of the function at the given point.
-  SmallVector<MPInt, 8> valueAt(ArrayRef<MPInt> point) const;
-  SmallVector<MPInt, 8> valueAt(ArrayRef<int64_t> point) const {
-    return valueAt(getMPIntVec(point));
+  SmallVector<DynamicAPInt, 8> valueAt(ArrayRef<DynamicAPInt> point) const;
+  SmallVector<DynamicAPInt, 8> valueAt(ArrayRef<int64_t> point) const {
+    return valueAt(getDynamicAPIntVec(point));
   }
 
   /// Return whether the `this` and `other` are equal when the domain is
@@ -191,9 +193,11 @@ class PWMAFunction {
   PresburgerSet getDomain() const;
 
   /// Return the output of the function at the given point.
-  std::optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<MPInt> point) const;
-  std::optional<SmallVector<MPInt, 8>> valueAt(ArrayRef<int64_t> point) const {
-    return valueAt(getMPIntVec(point));
+  std::optional<SmallVector<DynamicAPInt, 8>>
+  valueAt(ArrayRef<DynamicAPInt> point) const;
+  std::optional<SmallVector<DynamicAPInt, 8>>
+  valueAt(ArrayRef<int64_t> point) const {
+    return valueAt(getDynamicAPIntVec(point));
   }
 
   /// Return all the pieces of this piece-wise function.
diff --git a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
index 9634df6d58a1a..f7e06a6b22a95 100644
--- a/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
+++ b/mlir/include/mlir/Analysis/Presburger/PresburgerRelation.h
@@ -142,9 +142,9 @@ class PresburgerRelation {
   SymbolicLexOpt findSymbolicIntegerLexMax() const;
 
   /// Return true if the set contains the given point, and false otherwise.
-  bool containsPoint(ArrayRef<MPInt> point) const;
+  bool containsPoint(ArrayRef<DynamicAPInt> point) const;
   bool containsPoint(ArrayRef<int64_t> point) const {
-    return containsPoint(getMPIntVec(point));
+    return containsPoint(getDynamicAPIntVec(point));
   }
 
   /// Return the complement of this set. All local variables in the set must
@@ -187,7 +187,7 @@ class PresburgerRelation {
 
   /// Find an integer sample from the given set. This should not be called if
   /// any of the disjuncts in the union are unbounded.
-  bool findIntegerSample(SmallVectorImpl<MPInt> &sample);
+  bool findIntegerSample(SmallVectorImpl<DynamicAPInt> &sample);
 
   /// Compute an overapproximation of the number of integer points in the
   /// disjunct. Symbol vars are currently not supported. If the computed
@@ -196,7 +196,7 @@ class PresburgerRelation {
   /// This currently just sums up the overapproximations of the volumes of the
   /// disjuncts, so the approximation might be far from the true volume in the
   /// case when there is a lot of overlap between disjuncts.
-  std::optional<MPInt> computeVolume() const;
+  std::optional<DynamicAPInt> computeVolume() const;
 
   /// Simplifies the representation of a PresburgerRelation.
   ///
diff --git a/mlir/include/mlir/Analysis/Presburger/Simplex.h b/mlir/include/mlir/Analysis/Presburger/Simplex.h
index 7ee74c150867c..ff26e94e019c8 100644
--- a/mlir/include/mlir/Analysis/Presburger/Simplex.h
+++ b/mlir/include/mlir/Analysis/Presburger/Simplex.h
@@ -166,7 +166,7 @@ class SimplexBase {
   /// Add an inequality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
   /// is the current number of variables, then the corresponding inequality is
   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} >= 0.
-  virtual void addInequality(ArrayRef<MPInt> coeffs) = 0;
+  virtual void addInequality(ArrayRef<DynamicAPInt> coeffs) = 0;
 
   /// Returns the number of variables in the tableau.
   unsigned getNumVariables() const;
@@ -177,7 +177,7 @@ class SimplexBase {
   /// Add an equality to the tableau. If coeffs is c_0, c_1, ... c_n, where n
   /// is the current number of variables, then the corresponding equality is
   /// c_n + c_0*x_0 + c_1*x_1 + ... + c_{n-1}*x_{n-1} == 0.
-  void addEquality(ArrayRef<MPInt> coeffs);
+  void addEquality(ArrayRef<DynamicAPInt> coeffs);
 
   /// Add new variables to the end of the list of variables.
   void appendVariable(unsigned count = 1);
@@ -186,7 +186,8 @@ class SimplexBase {
   /// integer value is the floor div of `coeffs` and `denom`.
   ///
   /// `denom` must be positive.
-  void addDivisionVariable(ArrayRef<MPInt> coeffs, const MPInt &denom);
+  void addDivisionVariable(ArrayRef<DynamicAPInt> coeffs,
+                           const DynamicAPInt &denom);
 
   /// Mark the tableau as being empty.
   void markEmpty();
@@ -295,7 +296,7 @@ class SimplexBase {
   /// con.
   ///
   /// Returns the index of the new Unknown in con.
-  unsigned addRow(ArrayRef<MPInt> coeffs, bool makeRestricted = false);
+  unsigned addRow(ArrayRef<DynamicAPInt> coeffs, bool makeRestricted = false);
 
   /// Swap the two rows/columns in the tableau and associated data structures.
   void swapRows(unsigned i, unsigned j);
@@ -423,7 +424,7 @@ class LexSimplexBase : public SimplexBase {
   ///
   /// This just adds the inequality to the tableau and does not try to create a
   /// consistent tableau configuration.
-  void addInequality(ArrayRef<MPInt> coeffs) final;
+  void addInequality(ArrayRef<DynamicAPInt> coeffs) final;
 
   /// Get a snapshot of the current state. This is used for rolling back.
   unsigned getSnapshot() { return SimplexBase::getSnapshotBasis(); }
@@ -495,15 +496,15 @@ class LexSimplex : public LexSimplexBase {
   ///
   /// Note: this should be used only when the lexmin is really needed. To obtain
   /// any integer sample, use Simplex::findIntegerSample as that is more robust.
-  MaybeOptimum<SmallVector<MPInt, 8>> findIntegerLexMin();
+  MaybeOptimum<SmallVector<DynamicAPInt, 8>> findIntegerLexMin();
 
   /// Return whether the specified inequality is redundant/separate for the
   /// polytope. Redundant means every point satisfies the given inequality, and
   /// separate means no point satisfies it.
   ///
   /// These checks are integer-exact.
-  bool isSeparateInequality(ArrayRef<MPInt> coeffs);
-  bool isRedundantInequality(ArrayRef<MPInt> coeffs);
+  bool isSeparateInequality(ArrayRef<DynamicAPInt> coeffs);
+  bool isRedundantInequality(ArrayRef<DynamicAPInt> coeffs);
 
 private:
   /// Returns the current sample point, which may contain non-integer (rational)
@@ -656,11 +657,11 @@ class SymbolicLexSimplex : public LexSimplexBase {
   /// Get the numerator of the symbolic sample of the specific row.
   /// This is an affine expression in the symbols with integer coefficients.
   /// The last element is the constant term. This ignores the big M coefficient.
-  SmallVector<MPInt, 8> getSymbolicSampleNumerator(unsigned row) const;
+  SmallVector<DynamicAPInt, 8> getSymbolicSampleNumerator(unsigned row) const;
 
   /// Get an affine inequality in the symbols with integer coefficients that
   /// holds iff the symbolic sample of the specified row is non-negative.
-  SmallVector<MPInt, 8> getSymbolicSampleIneq(unsigned row) const;
+  SmallVector<DynamicAPInt, 8> getSymbolicSampleIneq(unsigned row) const;
 
   /// Return whether all the coefficients of the symbolic sample are integers.
   ///
@@ -710,7 +711,7 @@ class Simplex : public SimplexBase {
   ///
   /// This also tries to restore the tableau configuration to a consistent
   /// state and marks the Simplex empty if this is not possible.
-  void addInequality(ArrayRef<MPInt> coeffs) final;
+  void addInequality(ArrayRef<DynamicAPInt> coeffs) final;
 
   /// Compute the maximum or minimum value of the given row, depending on
   /// direction. The specified row is never pivoted. On return, the row may
@@ -726,7 +727,7 @@ class Simplex : public SimplexBase {
   /// Returns a Fraction denoting the optimum, or a null value if no optimum
   /// exists, i.e., if the expression is unbounded in this direction.
   MaybeOptimum<Fraction> computeOptimum(Direction direction,
-                                        ArrayRef<MPInt> coeffs);
+                                        ArrayRef<DynamicAPInt> coeffs);
 
   /// Returns whether the perpendicular of the specified constraint is a
   /// is a direction along which the polytope is bounded.
@@ -768,14 +769,14 @@ class Simplex : public SimplexBase {
   /// Returns a (min, max) pair denoting the minimum and maximum integer values
   /// of the given expression. If no integer value exists, both results will be
   /// of kind Empty.
-  std::pair<MaybeOptimum<MPInt>, MaybeOptimum<MPInt>>
-  computeIntegerBounds(ArrayRef<MPInt> coeffs);
+  std::pair<MaybeOptimum<DynamicAPInt>, MaybeOptimum<DynamicAPInt>>
+  computeIntegerBounds(ArrayRef<DynamicAPInt> coeffs);
 
   /// Check if the simplex takes only one rational value along the
   /// direction of `coeffs`.
   ///
   /// `this` must be nonempty.
-  bool isFlatAlong(ArrayRef<MPInt> coeffs);
+  bool isFlatAlong(ArrayRef<DynamicAPInt> coeffs);
 
   /// Returns true if the polytope is unbounded, i.e., extends to infinity in
   /// some direction. Otherwise, returns false.
@@ -787,7 +788,7 @@ class Simplex : public SimplexBase {
 
   /// Returns an integer sample point if one exists, or std::nullopt
   /// otherwise. This should only be called for bounded sets.
-  std::optional<SmallVector<MPInt, 8>> findIntegerSample();
+  std::optional<SmallVector<DynamicAPInt, 8>> findIntegerSample();
 
   enum class IneqType { Redundant, Cut, Separate };
 
@@ -797,13 +798,13 @@ class Simplex : public SimplexBase {
   /// Redundant   The inequality is satisfied in the polytope
   /// Cut         The inequality is satisfied by some points, but not by others
   /// Separate    The inequality is not satisfied by any point
-  IneqType findIneqType(ArrayRef<MPInt> coeffs);
+  IneqType findIneqType(ArrayRef<DynamicAPInt> coeffs);
 
   /// Check if the specified inequality already holds in the polytope.
-  bool isRedundantInequality(ArrayRef<MPInt> coeffs);
+  bool isRedundantInequality(ArrayRef<DynamicAPInt> coeffs);
 
   /// Check if the specified equality already holds in the polytope.
-  bool isRedundantEquality(ArrayRef<MPInt> coeffs);
+  bool isRedundantEquality(ArrayRef<DynamicAPInt> coeffs);
 
   /// Returns true if this Simplex's polytope is a rational subset of `rel`.
   /// Otherwise, returns false.
@@ -811,7 +812,7 @@ class Simplex : public SimplexBase {
 
   /// Returns the current sample point if it is integral. Otherwise, returns
   /// std::nullopt.
-  std::optional<SmallVector<MPInt, 8>> getSamplePointIfIntegral() const;
+  std::optional<SmallVector<DynamicAPInt, 8>> getSamplePointIfIntegral() const;
 
   /// Returns the current sample point, which may contain non-integer (rational)
   /// coordinates. Returns an empty optional when the tableau is empty.
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..9b93e52b48490 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/DynamicAPInt.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
@@ -118,7 +117,7 @@ struct MaybeLocalRepr {
 class DivisionRepr {
 public:
   DivisionRepr(unsigned numVars, unsigned numDivs)
-      : dividends(numDivs, numVars + 1), denoms(numDivs, MPInt(0)) {}
+      : dividends(numDivs, numVars + 1), denoms(numDivs, DynamicAPInt(0)) {}
 
   DivisionRepr(unsigned numVars) : dividends(0, numVars + 1) {}
 
@@ -137,21 +136,27 @@ class DivisionRepr {
   void clearRepr(unsigned i) { denoms[i] = 0; }
 
   // Get the dividend of the `i^th` division.
-  MutableArrayRef<MPInt> getDividend(unsigned i) { return dividends.getRow(i); }
-  ArrayRef<MPInt> getDividend(unsigned i) const { return dividends.getRow(i); }
+  MutableArrayRef<DynamicAPInt> getDividend(unsigned i) {
+    return dividends.getRow(i);
+  }
+  ArrayRef<DynamicAPInt> getDividend(unsigned i) const {
+    return dividends.getRow(i);
+  }
 
   // For a given point containing values for each variable other than the
   // division variables, try to find the values for each division variable from
   // their division representation.
-  SmallVector<std::optional<MPInt>, 4> divValuesAt(ArrayRef<MPInt> point) const;
+  SmallVector<std::optional<DynamicAPInt>, 4>
+  divValuesAt(ArrayRef<DynamicAPInt> point) const;
 
   // Get the `i^th` denominator.
-  MPInt &getDenom(unsigned i) { return denoms[i]; }
-  MPInt getDenom(unsigned i) const { return denoms[i]; }
+  DynamicAPInt &getDenom(unsigned i) { return denoms[i]; }
+  DynamicAPInt getDenom(unsigned i) const { return denoms[i]; }
 
-  ArrayRef<MPInt> getDenoms() const { return denoms; }
+  ArrayRef<DynamicAPInt> getDenoms() const { return denoms; }
 
-  void setDiv(unsigned i, ArrayRef<MPInt> dividend, const MPInt &divisor) {
+  void setDiv(unsigned i, ArrayRef<DynamicAPInt> dividend,
+              const DynamicAPInt &divisor) {
     dividends.setRow(i, dividend);
     denoms[i] = divisor;
   }
@@ -161,7 +166,8 @@ class DivisionRepr {
   // simplify the expression.
   void normalizeDivs();
 
-  void insertDiv(unsigned pos, ArrayRef<MPInt> dividend, const MPInt &divisor);
+  void insertDiv(unsigned pos, ArrayRef<DynamicAPInt> dividend,
+                 const DynamicAPInt &divisor);
   void insertDiv(unsigned pos, unsigned num = 1);
 
   /// Removes duplicate divisions. On every possible duplicate division found,
@@ -187,7 +193,7 @@ class DivisionRepr {
   /// Denominators of each division. If a denominator of a division is `0`, the
   /// division variable is considered to not have a division representation.
   /// Otherwise, the denominator is positive.
-  SmallVector<MPInt, 4> denoms;
+  SmallVector<DynamicAPInt, 4> denoms;
 };
 
 /// If `q` is defined to be equal to `expr floordiv d`, this equivalent to
@@ -205,12 +211,12 @@ class DivisionRepr {
 /// The coefficient of `q` in `dividend` must be zero, as it is not allowed for
 /// local variable to be a floor division of an expression involving itself.
 /// The divisor must be positive.
-SmallVector<MPInt, 8> getDivUpperBound(ArrayRef<MPInt> dividend,
-                                       const MPInt &divisor,
-                                       unsigned localVarIdx);
-SmallVector<MPInt, 8> getDivLowerBound(ArrayRef<MPInt> dividend,
-                                       const MPInt &divisor,
-                                       unsigned localVarIdx);
+SmallVector<DynamicAPInt, 8> getDivUpperBound(ArrayRef<DynamicAPInt> dividend,
+                                              const DynamicAPInt &divisor,
+                                              unsigned localVarIdx);
+SmallVector<DynamicAPInt, 8> getDivLowerBound(ArrayRef<DynamicAPInt> dividend,
+                                              const DynamicAPInt &divisor,
+                                              unsigned localVarIdx);
 
 llvm::SmallBitVector getSubrangeBitVector(unsigned len, unsigned setOffset,
                                           unsigned numSet);
@@ -219,10 +225,10 @@ llvm::SmallBitVector getSubrangeBitVector(unsigned len, unsigned setOffset,
 /// function of other variables (where the divisor is a positive constant).
 /// `foundRepr` contains a boolean for each variable indicating if the
 /// explicit representation for that variable has already been computed.
-/// Return the given array as an array of MPInts.
-SmallVector<MPInt, 8> getMPIntVec(ArrayRef<int64_t> range);
+/// Return the given array as an array of DynamicAPInts.
+SmallVector<DynamicAPInt, 8> getDynamicAPIntVec(ArrayRef<int64_t> range);
 /// Return the given array as an array of int64_t.
-SmallVector<int64_t, 8> getInt64Vec(ArrayRef<MPInt> range);
+SmallVector<int64_t, 8> getInt64Vec(ArrayRef<DynamicAPInt> range);
 
 /// Returns the `MaybeLocalRepr` struct which contains the indices of the
 /// constraints that can be expressed as a floordiv of an affine function. If
@@ -231,8 +237,8 @@ SmallVector<int64_t, 8> getInt64Vec(ArrayRef<MPInt> range);
 /// not be computed, the kind attribute in `MaybeLocalRepr` is set to None.
 MaybeLocalRepr computeSingleVarRepr(const IntegerRelation &cst,
                                     ArrayRef<bool> foundRepr, unsigned pos,
-                                    MutableArrayRef<MPInt> dividend,
-                                    MPInt &divisor);
+                                    MutableArrayRef<DynamicAPInt> dividend,
+                                    DynamicAPInt &divisor);
 
 /// The following overload using int64_t is required for a callsite in
 /// AffineStructures.h.
@@ -257,25 +263,25 @@ void mergeLocalVars(IntegerRelation &relA, IntegerRelation &relB,
                     llvm::function_ref<bool(unsigned i, unsigned j)> merge);
 
 /// Compute the gcd of the range.
-MPInt gcdRange(ArrayRef<MPInt> range);
+DynamicAPInt gcdRange(ArrayRef<DynamicAPInt> range);
 
 /// Divide the range by its gcd and return the gcd.
-MPInt normalizeRange(MutableArrayRef<MPInt> range);
+DynamicAPInt normalizeRange(MutableArrayRef<DynamicAPInt> range);
 
 /// Normalize the given (numerator, denominator) pair by dividing out the
 /// common factors between them. The numerator here is an affine expression
 /// with integer coefficients. The denominator must be positive.
-void normalizeDiv(MutableArrayRef<MPInt> num, MPInt &denom);
+void normalizeDiv(MutableArrayRef<DynamicAPInt> num, DynamicAPInt &denom);
 
 /// Return `coeffs` with all the elements negated.
-SmallVector<MPInt, 8> getNegatedCoeffs(ArrayRef<MPInt> coeffs);
+SmallVector<DynamicAPInt, 8> getNegatedCoeffs(ArrayRef<DynamicAPInt> coeffs);
 
 /// Return the complement of the given inequality.
 ///
 /// The complement of a_1 x_1 + ... + a_n x_ + c >= 0 is
 /// a_1 x_1 + ... + a_n x_ + c < 0, i.e., -a_1 x_1 - ... - a_n x_ - c - 1 >= 0,
 /// since all the variables are constrained to be integers.
-SmallVector<MPInt, 8> getComplementIneq(ArrayRef<MPInt> ineq);
+SmallVector<DynamicAPInt, 8> getComplementIneq(ArrayRef<DynamicAPInt> ineq);
 
 /// Compute the dot product of two vectors.
 /// The vectors must have the same sizes.
diff --git a/mlir/include/mlir/Support/LLVM.h b/mlir/include/mlir/Support/LLVM.h
index 235d84c5beff1..7baca03998f5b 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 DynamicAPInt;
 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::DynamicAPInt;
 template <typename Fn>
 using function_ref = llvm::function_ref<Fn>;
 using llvm::iterator_range;
diff --git a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
index bf7e3121ea32a..9886cc1de26b9 100644
--- a/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
+++ b/mlir/lib/Analysis/FlatLinearValueConstraints.cpp
@@ -1318,7 +1318,8 @@ mlir::getMultiAffineFunctionFromMap(AffineMap map,
          "AffineMap cannot produce divs without local representation");
 
   // TODO: We shouldn't have to do this conversion.
-  Matrix<MPInt> mat(map.getNumResults(), map.getNumInputs() + divs.getNumDivs() + 1);
+  Matrix<DynamicAPInt> mat(map.getNumResults(),
+                           map.getNumInputs() + divs.getNumDivs() + 1);
   for (unsigned i = 0, e = flattenedExprs.size(); i < e; ++i)
     for (unsigned j = 0, f = flattenedExprs[i].size(); j < f; ++j)
       mat(i, j) = flattenedExprs[i][j];
diff --git a/mlir/lib/Analysis/Presburger/Barvinok.cpp b/mlir/lib/Analysis/Presburger/Barvinok.cpp
index 0b55185c43782..e16b9269b75fc 100644
--- a/mlir/lib/Analysis/Presburger/Barvinok.cpp
+++ b/mlir/lib/Analysis/Presburger/Barvinok.cpp
@@ -61,9 +61,9 @@ ConeH mlir::presburger::detail::getDual(ConeV cone) {
 }
 
 /// Find the index of a cone in V-representation.
-MPInt mlir::presburger::detail::getIndex(const ConeV &cone) {
+DynamicAPInt mlir::presburger::detail::getIndex(const ConeV &cone) {
   if (cone.getNumRows() > cone.getNumColumns())
-    return MPInt(0);
+    return DynamicAPInt(0);
 
   return cone.determinant();
 }
@@ -413,7 +413,7 @@ mlir::presburger::detail::computePolytopeGeneratingFunction(
     // constant terms zero.
     ConeH tangentCone = defineHRep(numVars);
     for (unsigned j = 0, e = subset.getNumRows(); j < e; ++j) {
-      SmallVector<MPInt> ineq(numVars + 1);
+      SmallVector<DynamicAPInt> ineq(numVars + 1);
       for (unsigned k = 0; k < numVars; ++k)
         ineq[k] = subset(j, k);
       tangentCone.addInequality(ineq);
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..75215fbab5282 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"
@@ -157,9 +156,10 @@ IntegerRelation::findRationalLexMin() const {
   return maybeLexMin;
 }
 
-MaybeOptimum<SmallVector<MPInt, 8>> IntegerRelation::findIntegerLexMin() const {
+MaybeOptimum<SmallVector<DynamicAPInt, 8>>
+IntegerRelation::findIntegerLexMin() const {
   assert(getNumSymbolVars() == 0 && "Symbols are not supported!");
-  MaybeOptimum<SmallVector<MPInt, 8>> maybeLexMin =
+  MaybeOptimum<SmallVector<DynamicAPInt, 8>> maybeLexMin =
       LexSimplex(*this).findIntegerLexMin();
 
   if (!maybeLexMin.isBounded())
@@ -176,8 +176,8 @@ MaybeOptimum<SmallVector<MPInt, 8>> IntegerRelation::findIntegerLexMin() const {
   return maybeLexMin;
 }
 
-static bool rangeIsZero(ArrayRef<MPInt> range) {
-  return llvm::all_of(range, [](const MPInt &x) { return x == 0; });
+static bool rangeIsZero(ArrayRef<DynamicAPInt> range) {
+  return llvm::all_of(range, [](const DynamicAPInt &x) { return x == 0; });
 }
 
 static void removeConstraintsInvolvingVarRange(IntegerRelation &poly,
@@ -363,14 +363,14 @@ unsigned IntegerRelation::appendVar(VarKind kind, unsigned num) {
   return insertVar(kind, pos, num);
 }
 
-void IntegerRelation::addEquality(ArrayRef<MPInt> eq) {
+void IntegerRelation::addEquality(ArrayRef<DynamicAPInt> eq) {
   assert(eq.size() == getNumCols());
   unsigned row = equalities.appendExtraRow();
   for (unsigned i = 0, e = eq.size(); i < e; ++i)
     equalities(row, i) = eq[i];
 }
 
-void IntegerRelation::addInequality(ArrayRef<MPInt> inEq) {
+void IntegerRelation::addInequality(ArrayRef<DynamicAPInt> inEq) {
   assert(inEq.size() == getNumCols());
   unsigned row = inequalities.appendExtraRow();
   for (unsigned i = 0, e = inEq.size(); i < e; ++i)
@@ -541,7 +541,8 @@ bool IntegerRelation::hasConsistentState() const {
   return true;
 }
 
-void IntegerRelation::setAndEliminate(unsigned pos, ArrayRef<MPInt> values) {
+void IntegerRelation::setAndEliminate(unsigned pos,
+                                      ArrayRef<DynamicAPInt> values) {
   if (values.empty())
     return;
   assert(pos + values.size() <= getNumVars() &&
@@ -567,7 +568,7 @@ void IntegerRelation::clearAndCopyFrom(const IntegerRelation &other) {
 bool IntegerRelation::findConstraintWithNonZeroAt(unsigned colIdx, bool isEq,
                                                   unsigned *rowIdx) const {
   assert(colIdx < getNumCols() && "position out of bounds");
-  auto at = [&](unsigned rowIdx) -> MPInt {
+  auto at = [&](unsigned rowIdx) -> DynamicAPInt {
     return isEq ? atEq(rowIdx, colIdx) : atIneq(rowIdx, colIdx);
   };
   unsigned e = isEq ? getNumEqualities() : getNumInequalities();
@@ -594,7 +595,7 @@ bool IntegerRelation::hasInvalidConstraint() const {
     for (unsigned i = 0, e = numRows; i < e; ++i) {
       unsigned j;
       for (j = 0; j < numCols - 1; ++j) {
-        MPInt v = isEq ? atEq(i, j) : atIneq(i, j);
+        DynamicAPInt v = isEq ? atEq(i, j) : atIneq(i, j);
         // Skip rows with non-zero variable coefficients.
         if (v != 0)
           break;
@@ -604,7 +605,7 @@ bool IntegerRelation::hasInvalidConstraint() const {
       }
       // Check validity of constant term at 'numCols - 1' w.r.t 'isEq'.
       // Example invalid constraints include: '1 == 0' or '-1 >= 0'
-      MPInt v = isEq ? atEq(i, numCols - 1) : atIneq(i, numCols - 1);
+      DynamicAPInt v = isEq ? atEq(i, numCols - 1) : atIneq(i, numCols - 1);
       if ((isEq && v != 0) || (!isEq && v < 0)) {
         return true;
       }
@@ -626,26 +627,26 @@ static void eliminateFromConstraint(IntegerRelation *constraints,
   // Skip if equality 'rowIdx' if same as 'pivotRow'.
   if (isEq && rowIdx == pivotRow)
     return;
-  auto at = [&](unsigned i, unsigned j) -> MPInt {
+  auto at = [&](unsigned i, unsigned j) -> DynamicAPInt {
     return isEq ? constraints->atEq(i, j) : constraints->atIneq(i, j);
   };
-  MPInt leadCoeff = at(rowIdx, pivotCol);
+  DynamicAPInt leadCoeff = at(rowIdx, pivotCol);
   // Skip if leading coefficient at 'rowIdx' is already zero.
   if (leadCoeff == 0)
     return;
-  MPInt pivotCoeff = constraints->atEq(pivotRow, pivotCol);
+  DynamicAPInt pivotCoeff = constraints->atEq(pivotRow, pivotCol);
   int sign = (leadCoeff * pivotCoeff > 0) ? -1 : 1;
-  MPInt lcm = presburger::lcm(pivotCoeff, leadCoeff);
-  MPInt pivotMultiplier = sign * (lcm / abs(pivotCoeff));
-  MPInt rowMultiplier = lcm / abs(leadCoeff);
+  DynamicAPInt lcm = llvm::lcm(pivotCoeff, leadCoeff);
+  DynamicAPInt pivotMultiplier = sign * (lcm / abs(pivotCoeff));
+  DynamicAPInt rowMultiplier = lcm / abs(leadCoeff);
 
   unsigned numCols = constraints->getNumCols();
   for (unsigned j = 0; j < numCols; ++j) {
     // Skip updating column 'j' if it was just eliminated.
     if (j >= elimColStart && j < pivotCol)
       continue;
-    MPInt v = pivotMultiplier * constraints->atEq(pivotRow, j) +
-              rowMultiplier * at(rowIdx, j);
+    DynamicAPInt v = pivotMultiplier * constraints->atEq(pivotRow, j) +
+                     rowMultiplier * at(rowIdx, j);
     isEq ? constraints->atEq(rowIdx, j) = v
          : constraints->atIneq(rowIdx, j) = v;
   }
@@ -757,11 +758,11 @@ bool IntegerRelation::isEmptyByGCDTest() const {
   assert(hasConsistentState());
   unsigned numCols = getNumCols();
   for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
-    MPInt gcd = abs(atEq(i, 0));
+    DynamicAPInt 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));
+    DynamicAPInt v = abs(atEq(i, numCols - 1));
     if (gcd > 0 && (v % gcd != 0)) {
       return true;
     }
@@ -864,7 +865,7 @@ bool IntegerRelation::isIntegerEmpty() const { return !findIntegerSample(); }
 ///
 /// Concatenating the samples from B and C gives a sample v in S*T, so the
 /// returned sample T*v is a sample in S.
-std::optional<SmallVector<MPInt, 8>>
+std::optional<SmallVector<DynamicAPInt, 8>>
 IntegerRelation::findIntegerSample() const {
   // First, try the GCD test heuristic.
   if (isEmptyByGCDTest())
@@ -904,7 +905,7 @@ IntegerRelation::findIntegerSample() const {
   boundedSet.removeVarRange(numBoundedDims, boundedSet.getNumVars());
 
   // 3) Try to obtain a sample from the bounded set.
-  std::optional<SmallVector<MPInt, 8>> boundedSample =
+  std::optional<SmallVector<DynamicAPInt, 8>> boundedSample =
       Simplex(boundedSet).findIntegerSample();
   if (!boundedSample)
     return {};
@@ -943,7 +944,7 @@ IntegerRelation::findIntegerSample() const {
   // amount for the shrunken cone.
   for (unsigned i = 0, e = cone.getNumInequalities(); i < e; ++i) {
     for (unsigned j = 0; j < cone.getNumVars(); ++j) {
-      MPInt coeff = cone.atIneq(i, j);
+      DynamicAPInt coeff = cone.atIneq(i, j);
       if (coeff < 0)
         cone.atIneq(i, cone.getNumVars()) += coeff;
     }
@@ -960,10 +961,11 @@ IntegerRelation::findIntegerSample() const {
   SmallVector<Fraction, 8> shrunkenConeSample =
       *shrunkenConeSimplex.getRationalSample();
 
-  SmallVector<MPInt, 8> coneSample(llvm::map_range(shrunkenConeSample, ceil));
+  SmallVector<DynamicAPInt, 8> coneSample(
+      llvm::map_range(shrunkenConeSample, ceil));
 
   // 6) Return transform * concat(boundedSample, coneSample).
-  SmallVector<MPInt, 8> &sample = *boundedSample;
+  SmallVector<DynamicAPInt, 8> &sample = *boundedSample;
   sample.append(coneSample.begin(), coneSample.end());
   return transform.postMultiplyWithColumn(sample);
 }
@@ -971,10 +973,11 @@ IntegerRelation::findIntegerSample() const {
 /// Helper to evaluate an affine expression at a point.
 /// The expression is a list of coefficients for the dimensions followed by the
 /// constant term.
-static MPInt valueAt(ArrayRef<MPInt> expr, ArrayRef<MPInt> point) {
+static DynamicAPInt valueAt(ArrayRef<DynamicAPInt> expr,
+                            ArrayRef<DynamicAPInt> point) {
   assert(expr.size() == 1 + point.size() &&
          "Dimensionalities of point and expression don't match!");
-  MPInt value = expr.back();
+  DynamicAPInt value = expr.back();
   for (unsigned i = 0; i < point.size(); ++i)
     value += expr[i] * point[i];
   return value;
@@ -983,7 +986,7 @@ static MPInt valueAt(ArrayRef<MPInt> expr, ArrayRef<MPInt> point) {
 /// A point satisfies an equality iff the value of the equality at the
 /// expression is zero, and it satisfies an inequality iff the value of the
 /// inequality at that point is non-negative.
-bool IntegerRelation::containsPoint(ArrayRef<MPInt> point) const {
+bool IntegerRelation::containsPoint(ArrayRef<DynamicAPInt> point) const {
   for (unsigned i = 0, e = getNumEqualities(); i < e; ++i) {
     if (valueAt(getEquality(i), point) != 0)
       return false;
@@ -1003,8 +1006,8 @@ bool IntegerRelation::containsPoint(ArrayRef<MPInt> point) const {
 /// compute the values of the locals that have division representations and
 /// only use the integer emptiness check for the locals that don't have this.
 /// Handling this correctly requires ordering the divs, though.
-std::optional<SmallVector<MPInt, 8>>
-IntegerRelation::containsPointNoLocal(ArrayRef<MPInt> point) const {
+std::optional<SmallVector<DynamicAPInt, 8>>
+IntegerRelation::containsPointNoLocal(ArrayRef<DynamicAPInt> point) const {
   assert(point.size() == getNumVars() - getNumLocalVars() &&
          "Point should contain all vars except locals!");
   assert(getVarKindOffset(VarKind::Local) == getNumVars() - getNumLocalVars() &&
@@ -1061,7 +1064,7 @@ void IntegerRelation::gcdTightenInequalities() {
   unsigned numCols = getNumCols();
   for (unsigned i = 0, e = getNumInequalities(); i < e; ++i) {
     // Normalize the constraint and tighten the constant term by the GCD.
-    MPInt gcd = inequalities.normalizeRow(i, getNumCols() - 1);
+    DynamicAPInt gcd = inequalities.normalizeRow(i, getNumCols() - 1);
     if (gcd > 1)
       atIneq(i, numCols - 1) = floorDiv(atIneq(i, numCols - 1), gcd);
   }
@@ -1233,14 +1236,14 @@ void IntegerRelation::removeRedundantConstraints() {
   equalities.resizeVertically(pos);
 }
 
-std::optional<MPInt> IntegerRelation::computeVolume() const {
+std::optional<DynamicAPInt> IntegerRelation::computeVolume() const {
   assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
 
   Simplex simplex(*this);
   // If the polytope is rationally empty, there are certainly no integer
   // points.
   if (simplex.isEmpty())
-    return MPInt(0);
+    return DynamicAPInt(0);
 
   // Just find the maximum and minimum integer value of each non-local var
   // separately, thus finding the number of integer values each such var can
@@ -1256,8 +1259,8 @@ std::optional<MPInt> IntegerRelation::computeVolume() const {
   //
   // If there is no such empty dimension, if any dimension is unbounded we
   // just return the result as unbounded.
-  MPInt count(1);
-  SmallVector<MPInt, 8> dim(getNumVars() + 1);
+  DynamicAPInt count(1);
+  SmallVector<DynamicAPInt, 8> dim(getNumVars() + 1);
   bool hasUnboundedVar = false;
   for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i) {
     dim[i] = 1;
@@ -1277,13 +1280,13 @@ std::optional<MPInt> IntegerRelation::computeVolume() const {
     // In this case there are no valid integer points and the volume is
     // definitely zero.
     if (min.getBoundedOptimum() > max.getBoundedOptimum())
-      return MPInt(0);
+      return DynamicAPInt(0);
 
     count *= (*max - *min + 1);
   }
 
   if (count == 0)
-    return MPInt(0);
+    return DynamicAPInt(0);
   if (hasUnboundedVar)
     return {};
   return count;
@@ -1476,7 +1479,7 @@ void IntegerRelation::convertVarKind(VarKind srcKind, unsigned varStart,
 }
 
 void IntegerRelation::addBound(BoundType type, unsigned pos,
-                               const MPInt &value) {
+                               const DynamicAPInt &value) {
   assert(pos < getNumCols());
   if (type == BoundType::EQ) {
     unsigned row = equalities.appendExtraRow();
@@ -1490,8 +1493,8 @@ void IntegerRelation::addBound(BoundType type, unsigned pos,
   }
 }
 
-void IntegerRelation::addBound(BoundType type, ArrayRef<MPInt> expr,
-                               const MPInt &value) {
+void IntegerRelation::addBound(BoundType type, ArrayRef<DynamicAPInt> expr,
+                               const DynamicAPInt &value) {
   assert(type != BoundType::EQ && "EQ not implemented");
   assert(expr.size() == getNumCols());
   unsigned row = inequalities.appendExtraRow();
@@ -1506,15 +1509,15 @@ void IntegerRelation::addBound(BoundType type, ArrayRef<MPInt> expr,
 /// respect to a positive constant 'divisor'. Two constraints are added to the
 /// system to capture equivalence with the floordiv.
 ///      q = expr floordiv c    <=>   c*q <= expr <= c*q + c - 1.
-void IntegerRelation::addLocalFloorDiv(ArrayRef<MPInt> dividend,
-                                       const MPInt &divisor) {
+void IntegerRelation::addLocalFloorDiv(ArrayRef<DynamicAPInt> dividend,
+                                       const DynamicAPInt &divisor) {
   assert(dividend.size() == getNumCols() && "incorrect dividend size");
   assert(divisor > 0 && "positive divisor expected");
 
   appendVar(VarKind::Local);
 
-  SmallVector<MPInt, 8> dividendCopy(dividend.begin(), dividend.end());
-  dividendCopy.insert(dividendCopy.end() - 1, MPInt(0));
+  SmallVector<DynamicAPInt, 8> dividendCopy(dividend.begin(), dividend.end());
+  dividendCopy.insert(dividendCopy.end() - 1, DynamicAPInt(0));
   addInequality(
       getDivLowerBound(dividendCopy, divisor, dividendCopy.size() - 2));
   addInequality(
@@ -1530,7 +1533,7 @@ static int findEqualityToConstant(const IntegerRelation &cst, unsigned pos,
                                   bool symbolic = false) {
   assert(pos < cst.getNumVars() && "invalid position");
   for (unsigned r = 0, e = cst.getNumEqualities(); r < e; r++) {
-    MPInt v = cst.atEq(r, pos);
+    DynamicAPInt v = cst.atEq(r, pos);
     if (v * v != 1)
       continue;
     unsigned c;
@@ -1559,7 +1562,7 @@ LogicalResult IntegerRelation::constantFoldVar(unsigned pos) {
 
   // atEq(rowIdx, pos) is either -1 or 1.
   assert(atEq(rowIdx, pos) * atEq(rowIdx, pos) == 1);
-  MPInt constVal = -atEq(rowIdx, getNumCols() - 1) / atEq(rowIdx, pos);
+  DynamicAPInt constVal = -atEq(rowIdx, getNumCols() - 1) / atEq(rowIdx, pos);
   setAndEliminate(pos, constVal);
   return success();
 }
@@ -1585,9 +1588,10 @@ void IntegerRelation::constantFoldVarRange(unsigned pos, unsigned num) {
 //       s0 + s1 + 16 <= d0 <= s0 + s1 + 31, returns 16.
 //       s0 - 7 <= 8*j <= s0 returns 1 with lb = s0, lbDivisor = 8 (since lb =
 //       ceil(s0 - 7 / 8) = floor(s0 / 8)).
-std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
-    unsigned pos, SmallVectorImpl<MPInt> *lb, MPInt *boundFloorDivisor,
-    SmallVectorImpl<MPInt> *ub, unsigned *minLbPos, unsigned *minUbPos) const {
+std::optional<DynamicAPInt> IntegerRelation::getConstantBoundOnDimSize(
+    unsigned pos, SmallVectorImpl<DynamicAPInt> *lb,
+    DynamicAPInt *boundFloorDivisor, SmallVectorImpl<DynamicAPInt> *ub,
+    unsigned *minLbPos, unsigned *minUbPos) const {
   assert(pos < getNumDimVars() && "Invalid variable position");
 
   // Find an equality for 'pos'^th variable that equates it to some function
@@ -1599,7 +1603,7 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
     // TODO: this can be handled in the future by using the explicit
     // representation of the local vars.
     if (!std::all_of(eq.begin() + getNumDimAndSymbolVars(), eq.end() - 1,
-                     [](const MPInt &coeff) { return coeff == 0; }))
+                     [](const DynamicAPInt &coeff) { return coeff == 0; }))
       return std::nullopt;
 
     // This variable can only take a single value.
@@ -1609,7 +1613,7 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
       if (ub)
         ub->resize(getNumSymbolVars() + 1);
       for (unsigned c = 0, f = getNumSymbolVars() + 1; c < f; c++) {
-        MPInt v = atEq(eqPos, pos);
+        DynamicAPInt v = atEq(eqPos, pos);
         // atEq(eqRow, pos) is either -1 or 1.
         assert(v * v == 1);
         (*lb)[c] = v < 0 ? atEq(eqPos, getNumDimVars() + c) / -v
@@ -1626,7 +1630,7 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
       *minLbPos = eqPos;
     if (minUbPos)
       *minUbPos = eqPos;
-    return MPInt(1);
+    return DynamicAPInt(1);
   }
 
   // Check if the variable appears at all in any of the inequalities.
@@ -1650,7 +1654,7 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
                                /*eqIndices=*/nullptr, /*offset=*/0,
                                /*num=*/getNumDimVars());
 
-  std::optional<MPInt> minDiff;
+  std::optional<DynamicAPInt> minDiff;
   unsigned minLbPosition = 0, minUbPosition = 0;
   for (auto ubPos : ubIndices) {
     for (auto lbPos : lbIndices) {
@@ -1667,11 +1671,11 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
         }
       if (j < getNumCols() - 1)
         continue;
-      MPInt diff = ceilDiv(atIneq(ubPos, getNumCols() - 1) +
-                               atIneq(lbPos, getNumCols() - 1) + 1,
-                           atIneq(lbPos, pos));
+      DynamicAPInt diff = ceilDiv(atIneq(ubPos, getNumCols() - 1) +
+                                      atIneq(lbPos, getNumCols() - 1) + 1,
+                                  atIneq(lbPos, pos));
       // This bound is non-negative by definition.
-      diff = std::max<MPInt>(diff, MPInt(0));
+      diff = std::max<DynamicAPInt>(diff, DynamicAPInt(0));
       if (minDiff == std::nullopt || diff < minDiff) {
         minDiff = diff;
         minLbPosition = lbPos;
@@ -1711,7 +1715,7 @@ std::optional<MPInt> IntegerRelation::getConstantBoundOnDimSize(
 }
 
 template <bool isLower>
-std::optional<MPInt>
+std::optional<DynamicAPInt>
 IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
   assert(pos < getNumVars() && "invalid position");
   // Project to 'pos'.
@@ -1733,7 +1737,7 @@ IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
     // If it doesn't, there isn't a bound on it.
     return std::nullopt;
 
-  std::optional<MPInt> minOrMaxConst;
+  std::optional<DynamicAPInt> minOrMaxConst;
 
   // Take the max across all const lower bounds (or min across all constant
   // upper bounds).
@@ -1754,7 +1758,7 @@ IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
       // Not a constant bound.
       continue;
 
-    MPInt boundConst =
+    DynamicAPInt boundConst =
         isLower ? ceilDiv(-atIneq(r, getNumCols() - 1), atIneq(r, 0))
                 : floorDiv(atIneq(r, getNumCols() - 1), -atIneq(r, 0));
     if (isLower) {
@@ -1768,8 +1772,8 @@ IntegerRelation::computeConstantLowerOrUpperBound(unsigned pos) {
   return minOrMaxConst;
 }
 
-std::optional<MPInt> IntegerRelation::getConstantBound(BoundType type,
-                                                       unsigned pos) const {
+std::optional<DynamicAPInt>
+IntegerRelation::getConstantBound(BoundType type, unsigned pos) const {
   if (type == BoundType::LB)
     return IntegerRelation(*this)
         .computeConstantLowerOrUpperBound</*isLower=*/true>(pos);
@@ -1778,13 +1782,14 @@ std::optional<MPInt> IntegerRelation::getConstantBound(BoundType type,
         .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
 
   assert(type == BoundType::EQ && "expected EQ");
-  std::optional<MPInt> lb =
+  std::optional<DynamicAPInt> lb =
       IntegerRelation(*this).computeConstantLowerOrUpperBound</*isLower=*/true>(
           pos);
-  std::optional<MPInt> ub =
+  std::optional<DynamicAPInt> ub =
       IntegerRelation(*this)
           .computeConstantLowerOrUpperBound</*isLower=*/false>(pos);
-  return (lb && ub && *lb == *ub) ? std::optional<MPInt>(*ub) : std::nullopt;
+  return (lb && ub && *lb == *ub) ? std::optional<DynamicAPInt>(*ub)
+                                  : std::nullopt;
 }
 
 // A simple (naive and conservative) check for hyper-rectangularity.
@@ -1825,10 +1830,10 @@ void IntegerRelation::removeTrivialRedundancy() {
   // A map used to detect redundancy stemming from constraints that only differ
   // in their constant term. The value stored is <row position, const term>
   // for a given row.
-  SmallDenseMap<ArrayRef<MPInt>, std::pair<unsigned, MPInt>>
+  SmallDenseMap<ArrayRef<DynamicAPInt>, std::pair<unsigned, DynamicAPInt>>
       rowsWithoutConstTerm;
   // To unique rows.
-  SmallDenseSet<ArrayRef<MPInt>, 8> rowSet;
+  SmallDenseSet<ArrayRef<DynamicAPInt>, 8> rowSet;
 
   // Check if constraint is of the form <non-negative-constant> >= 0.
   auto isTriviallyValid = [&](unsigned r) -> bool {
@@ -1842,8 +1847,8 @@ void IntegerRelation::removeTrivialRedundancy() {
   // Detect and mark redundant constraints.
   SmallVector<bool, 256> redunIneq(getNumInequalities(), false);
   for (unsigned r = 0, e = getNumInequalities(); r < e; r++) {
-    MPInt *rowStart = &inequalities(r, 0);
-    auto row = ArrayRef<MPInt>(rowStart, getNumCols());
+    DynamicAPInt *rowStart = &inequalities(r, 0);
+    auto row = ArrayRef<DynamicAPInt>(rowStart, getNumCols());
     if (isTriviallyValid(r) || !rowSet.insert(row).second) {
       redunIneq[r] = true;
       continue;
@@ -1853,8 +1858,9 @@ void IntegerRelation::removeTrivialRedundancy() {
     // everything other than the one with the smallest constant term redundant.
     // (eg: among i - 16j - 5 >= 0, i - 16j - 1 >=0, i - 16j - 7 >= 0, the
     // former two are redundant).
-    MPInt constTerm = atIneq(r, getNumCols() - 1);
-    auto rowWithoutConstTerm = ArrayRef<MPInt>(rowStart, getNumCols() - 1);
+    DynamicAPInt constTerm = atIneq(r, getNumCols() - 1);
+    auto rowWithoutConstTerm =
+        ArrayRef<DynamicAPInt>(rowStart, getNumCols() - 1);
     const auto &ret =
         rowsWithoutConstTerm.insert({rowWithoutConstTerm, {r, constTerm}});
     if (!ret.second) {
@@ -2010,19 +2016,19 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow,
   // integer exact.
   for (auto ubPos : ubIndices) {
     for (auto lbPos : lbIndices) {
-      SmallVector<MPInt, 4> ineq;
+      SmallVector<DynamicAPInt, 4> ineq;
       ineq.reserve(newRel.getNumCols());
-      MPInt lbCoeff = atIneq(lbPos, pos);
+      DynamicAPInt lbCoeff = atIneq(lbPos, pos);
       // Note that in the comments above, ubCoeff is the negation of the
       // coefficient in the canonical form as the view taken here is that of the
       // term being moved to the other size of '>='.
-      MPInt ubCoeff = -atIneq(ubPos, pos);
+      DynamicAPInt ubCoeff = -atIneq(ubPos, pos);
       // TODO: refactor this loop to avoid all branches inside.
       for (unsigned l = 0, e = getNumCols(); l < e; l++) {
         if (l == pos)
           continue;
         assert(lbCoeff >= 1 && ubCoeff >= 1 && "bounds wrongly identified");
-        MPInt lcm = presburger::lcm(lbCoeff, ubCoeff);
+        DynamicAPInt 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!");
@@ -2047,7 +2053,7 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow,
 
   // Copy over the constraints not involving this variable.
   for (auto nbPos : nbIndices) {
-    SmallVector<MPInt, 4> ineq;
+    SmallVector<DynamicAPInt, 4> ineq;
     ineq.reserve(getNumCols() - 1);
     for (unsigned l = 0, e = getNumCols(); l < e; l++) {
       if (l == pos)
@@ -2062,7 +2068,7 @@ void IntegerRelation::fourierMotzkinEliminate(unsigned pos, bool darkShadow,
 
   // Copy over the equalities.
   for (unsigned r = 0, e = getNumEqualities(); r < e; r++) {
-    SmallVector<MPInt, 4> eq;
+    SmallVector<DynamicAPInt, 4> eq;
     eq.reserve(newRel.getNumCols());
     for (unsigned l = 0, e = getNumCols(); l < e; l++) {
       if (l == pos)
@@ -2126,7 +2132,8 @@ enum BoundCmpResult { Greater, Less, Equal, Unknown };
 
 /// Compares two affine bounds whose coefficients are provided in 'first' and
 /// 'second'. The last coefficient is the constant term.
-static BoundCmpResult compareBounds(ArrayRef<MPInt> a, ArrayRef<MPInt> b) {
+static BoundCmpResult compareBounds(ArrayRef<DynamicAPInt> a,
+                                    ArrayRef<DynamicAPInt> b) {
   assert(a.size() == b.size());
 
   // For the bounds to be comparable, their corresponding variable
@@ -2178,20 +2185,20 @@ IntegerRelation::unionBoundingBox(const IntegerRelation &otherCst) {
   IntegerRelation commonCst(PresburgerSpace::getRelationSpace());
   getCommonConstraints(*this, otherCst, commonCst);
 
-  std::vector<SmallVector<MPInt, 8>> boundingLbs;
-  std::vector<SmallVector<MPInt, 8>> boundingUbs;
+  std::vector<SmallVector<DynamicAPInt, 8>> boundingLbs;
+  std::vector<SmallVector<DynamicAPInt, 8>> boundingUbs;
   boundingLbs.reserve(2 * getNumDimVars());
   boundingUbs.reserve(2 * getNumDimVars());
 
   // To hold lower and upper bounds for each dimension.
-  SmallVector<MPInt, 4> lb, otherLb, ub, otherUb;
+  SmallVector<DynamicAPInt, 4> lb, otherLb, ub, otherUb;
   // To compute min of lower bounds and max of upper bounds for each dimension.
-  SmallVector<MPInt, 4> minLb(getNumSymbolVars() + 1);
-  SmallVector<MPInt, 4> maxUb(getNumSymbolVars() + 1);
+  SmallVector<DynamicAPInt, 4> minLb(getNumSymbolVars() + 1);
+  SmallVector<DynamicAPInt, 4> maxUb(getNumSymbolVars() + 1);
   // To compute final new lower and upper bounds for the union.
-  SmallVector<MPInt, 8> newLb(getNumCols()), newUb(getNumCols());
+  SmallVector<DynamicAPInt, 8> newLb(getNumCols()), newUb(getNumCols());
 
-  MPInt lbFloorDivisor, otherLbFloorDivisor;
+  DynamicAPInt lbFloorDivisor, otherLbFloorDivisor;
   for (unsigned d = 0, e = getNumDimVars(); d < e; ++d) {
     auto extent = getConstantBoundOnDimSize(d, &lb, &lbFloorDivisor, &ub);
     if (!extent.has_value())
@@ -2254,7 +2261,8 @@ IntegerRelation::unionBoundingBox(const IntegerRelation &otherCst) {
     // Copy over the symbolic part + constant term.
     std::copy(minLb.begin(), minLb.end(), newLb.begin() + getNumDimVars());
     std::transform(newLb.begin() + getNumDimVars(), newLb.end(),
-                   newLb.begin() + getNumDimVars(), std::negate<MPInt>());
+                   newLb.begin() + getNumDimVars(),
+                   std::negate<DynamicAPInt>());
     std::copy(maxUb.begin(), maxUb.end(), newUb.begin() + getNumDimVars());
 
     boundingLbs.push_back(newLb);
@@ -2349,14 +2357,14 @@ IntegerPolyhedron IntegerRelation::getDomainSet() const {
 
 bool IntegerRelation::removeDuplicateConstraints() {
   bool changed = false;
-  SmallDenseMap<ArrayRef<MPInt>, unsigned> hashTable;
+  SmallDenseMap<ArrayRef<DynamicAPInt>, unsigned> hashTable;
   unsigned ineqs = getNumInequalities(), cols = getNumCols();
 
   if (ineqs <= 1)
     return changed;
 
   // Check if the non-constant part of the constraint is the same.
-  ArrayRef<MPInt> row = getInequality(0).drop_back();
+  ArrayRef<DynamicAPInt> row = getInequality(0).drop_back();
   hashTable.insert({row, 0});
   for (unsigned k = 1; k < ineqs; ++k) {
     row = getInequality(k).drop_back();
@@ -2376,11 +2384,11 @@ bool IntegerRelation::removeDuplicateConstraints() {
   }
 
   // Check the neg form of each inequality, need an extra vector to store it.
-  SmallVector<MPInt> negIneq(cols - 1);
+  SmallVector<DynamicAPInt> negIneq(cols - 1);
   for (unsigned k = 0; k < ineqs; ++k) {
     row = getInequality(k).drop_back();
     negIneq.assign(row.begin(), row.end());
-    for (MPInt &ele : negIneq)
+    for (DynamicAPInt &ele : negIneq)
       ele = -ele;
     if (!hashTable.contains(negIneq))
       continue;
diff --git a/mlir/lib/Analysis/Presburger/LinearTransform.cpp b/mlir/lib/Analysis/Presburger/LinearTransform.cpp
index 3e080e698b199..ecab634967694 100644
--- a/mlir/lib/Analysis/Presburger/LinearTransform.cpp
+++ b/mlir/lib/Analysis/Presburger/LinearTransform.cpp
@@ -8,7 +8,6 @@
 
 #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 <utility>
@@ -48,21 +47,21 @@ IntegerRelation LinearTransform::applyTo(const IntegerRelation &rel) const {
   IntegerRelation result(rel.getSpace());
 
   for (unsigned i = 0, e = rel.getNumEqualities(); i < e; ++i) {
-    ArrayRef<MPInt> eq = rel.getEquality(i);
+    ArrayRef<DynamicAPInt> eq = rel.getEquality(i);
 
-    const MPInt &c = eq.back();
+    const DynamicAPInt &c = eq.back();
 
-    SmallVector<MPInt, 8> newEq = preMultiplyWithRow(eq.drop_back());
+    SmallVector<DynamicAPInt, 8> newEq = preMultiplyWithRow(eq.drop_back());
     newEq.push_back(c);
     result.addEquality(newEq);
   }
 
   for (unsigned i = 0, e = rel.getNumInequalities(); i < e; ++i) {
-    ArrayRef<MPInt> ineq = rel.getInequality(i);
+    ArrayRef<DynamicAPInt> ineq = rel.getInequality(i);
 
-    const MPInt &c = ineq.back();
+    const DynamicAPInt &c = ineq.back();
 
-    SmallVector<MPInt, 8> newIneq = preMultiplyWithRow(ineq.drop_back());
+    SmallVector<DynamicAPInt, 8> newIneq = preMultiplyWithRow(ineq.drop_back());
     newIneq.push_back(c);
     result.addInequality(newIneq);
   }
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..134b805648d9f 100644
--- a/mlir/lib/Analysis/Presburger/Matrix.cpp
+++ b/mlir/lib/Analysis/Presburger/Matrix.cpp
@@ -8,7 +8,6 @@
 
 #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/Support/MathExtras.h"
@@ -372,12 +371,12 @@ SmallVector<T, 8> Matrix<T>::postMultiplyWithColumn(ArrayRef<T> colVec) const {
 /// sourceCol. This brings M(row, targetCol) to the range [0, M(row,
 /// sourceCol)). Apply the same column operation to otherMatrix, with the same
 /// integer multiple.
-static void modEntryColumnOperation(Matrix<MPInt> &m, unsigned row,
+static void modEntryColumnOperation(Matrix<DynamicAPInt> &m, unsigned row,
                                     unsigned sourceCol, unsigned targetCol,
-                                    Matrix<MPInt> &otherMatrix) {
+                                    Matrix<DynamicAPInt> &otherMatrix) {
   assert(m(row, sourceCol) != 0 && "Cannot divide by zero!");
   assert(m(row, sourceCol) > 0 && "Source must be positive!");
-  MPInt ratio = -floorDiv(m(row, targetCol), m(row, sourceCol));
+  DynamicAPInt ratio = -floorDiv(m(row, targetCol), m(row, sourceCol));
   m.addToColumn(sourceCol, targetCol, ratio);
   otherMatrix.addToColumn(sourceCol, targetCol, ratio);
 }
@@ -444,7 +443,7 @@ bool Matrix<T>::hasConsistentState() const {
 
 namespace mlir {
 namespace presburger {
-template class Matrix<MPInt>;
+template class Matrix<DynamicAPInt>;
 template class Matrix<Fraction>;
 } // namespace presburger
 } // namespace mlir
@@ -542,25 +541,25 @@ std::pair<IntMatrix, IntMatrix> IntMatrix::computeHermiteNormalForm() const {
   return {h, u};
 }
 
-MPInt IntMatrix::normalizeRow(unsigned row, unsigned cols) {
+DynamicAPInt IntMatrix::normalizeRow(unsigned row, unsigned cols) {
   return normalizeRange(getRow(row).slice(0, cols));
 }
 
-MPInt IntMatrix::normalizeRow(unsigned row) {
+DynamicAPInt IntMatrix::normalizeRow(unsigned row) {
   return normalizeRow(row, getNumColumns());
 }
 
-MPInt IntMatrix::determinant(IntMatrix *inverse) const {
+DynamicAPInt IntMatrix::determinant(IntMatrix *inverse) const {
   assert(nRows == nColumns &&
          "determinant can only be calculated for square matrices!");
 
   FracMatrix m(*this);
 
   FracMatrix fracInverse(nRows, nColumns);
-  MPInt detM = m.determinant(&fracInverse).getAsInteger();
+  DynamicAPInt detM = m.determinant(&fracInverse).getAsInteger();
 
   if (detM == 0)
-    return MPInt(0);
+    return DynamicAPInt(0);
 
   if (!inverse)
     return detM;
@@ -718,7 +717,7 @@ FracMatrix FracMatrix::gramSchmidt() const {
 //
 // We repeat this until k = n and return.
 void FracMatrix::LLL(Fraction delta) {
-  MPInt nearest;
+  DynamicAPInt nearest;
   Fraction mu;
 
   // `gsOrth` holds the Gram-Schmidt orthogonalisation
@@ -762,7 +761,7 @@ IntMatrix FracMatrix::normalizeRows() const {
   unsigned numColumns = getNumColumns();
   IntMatrix normalized(numRows, numColumns);
 
-  MPInt lcmDenoms = MPInt(1);
+  DynamicAPInt lcmDenoms = DynamicAPInt(1);
   for (unsigned i = 0; i < numRows; i++) {
     // For a row, first compute the LCM of the denominators.
     for (unsigned j = 0; j < numColumns; j++)
diff --git a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
index d55962616de17..664670d506d53 100644
--- a/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
+++ b/mlir/lib/Analysis/Presburger/PWMAFunction.cpp
@@ -8,7 +8,6 @@
 
 #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"
@@ -41,11 +40,11 @@ void MultiAffineFunction::assertIsConsistent() const {
 // Return the result of subtracting the two given vectors pointwise.
 // The vectors must be of the same size.
 // e.g., [3, 4, 6] - [2, 5, 1] = [1, -1, 5].
-static SmallVector<MPInt, 8> subtractExprs(ArrayRef<MPInt> vecA,
-                                           ArrayRef<MPInt> vecB) {
+static SmallVector<DynamicAPInt, 8> subtractExprs(ArrayRef<DynamicAPInt> vecA,
+                                                  ArrayRef<DynamicAPInt> vecB) {
   assert(vecA.size() == vecB.size() &&
          "Cannot subtract vectors of differing lengths!");
-  SmallVector<MPInt, 8> result;
+  SmallVector<DynamicAPInt, 8> result;
   result.reserve(vecA.size());
   for (unsigned i = 0, e = vecA.size(); i < e; ++i)
     result.push_back(vecA[i] - vecB[i]);
@@ -67,18 +66,19 @@ void MultiAffineFunction::print(raw_ostream &os) const {
   output.print(os);
 }
 
-SmallVector<MPInt, 8>
-MultiAffineFunction::valueAt(ArrayRef<MPInt> point) const {
+SmallVector<DynamicAPInt, 8>
+MultiAffineFunction::valueAt(ArrayRef<DynamicAPInt> point) const {
   assert(point.size() == getNumDomainVars() + getNumSymbolVars() &&
          "Point has incorrect dimensionality!");
 
-  SmallVector<MPInt, 8> pointHomogenous{llvm::to_vector(point)};
+  SmallVector<DynamicAPInt, 8> pointHomogenous{llvm::to_vector(point)};
   // Get the division values at this point.
-  SmallVector<std::optional<MPInt>, 8> divValues = divs.divValuesAt(point);
+  SmallVector<std::optional<DynamicAPInt>, 8> divValues =
+      divs.divValuesAt(point);
   // The given point didn't include the values of the divs which the output is a
   // function of; we have computed one possible set of values and use them here.
   pointHomogenous.reserve(pointHomogenous.size() + divValues.size());
-  for (const std::optional<MPInt> &divVal : divValues)
+  for (const std::optional<DynamicAPInt> &divVal : divValues)
     pointHomogenous.push_back(*divVal);
   // The matrix `output` has an affine expression in the ith row, corresponding
   // to the expression for the ith value in the output vector. The last column
@@ -86,7 +86,8 @@ MultiAffineFunction::valueAt(ArrayRef<MPInt> point) const {
   // a 1 appended at the end. We can see that output * v gives the desired
   // output vector.
   pointHomogenous.emplace_back(1);
-  SmallVector<MPInt, 8> result = output.postMultiplyWithColumn(pointHomogenous);
+  SmallVector<DynamicAPInt, 8> result =
+      output.postMultiplyWithColumn(pointHomogenous);
   assert(result.size() == getNumOutputs());
   return result;
 }
@@ -138,7 +139,7 @@ void MultiAffineFunction::mergeDivs(MultiAffineFunction &other) {
 
   other.divs.insertDiv(0, nDivs);
 
-  SmallVector<MPInt, 8> div(other.divs.getNumVars() + 1);
+  SmallVector<DynamicAPInt, 8> div(other.divs.getNumVars() + 1);
   for (unsigned i = 0; i < nDivs; ++i) {
     // Zero fill.
     std::fill(div.begin(), div.end(), 0);
@@ -232,7 +233,7 @@ MultiAffineFunction::getLexSet(OrderingKind comp,
 
   for (unsigned level = 0; level < funcA.getNumOutputs(); ++level) {
     // Create the expression `outA - outB` for this level.
-    SmallVector<MPInt, 8> subExpr =
+    SmallVector<DynamicAPInt, 8> subExpr =
         subtractExprs(funcA.getOutputExpr(level), funcB.getOutputExpr(level));
 
     // TODO: Implement all comparison cases.
@@ -242,14 +243,14 @@ MultiAffineFunction::getLexSet(OrderingKind comp,
       //        outA - outB <= -1
       //        outA <= outB - 1
       //        outA < outB
-      levelSet.addBound(BoundType::UB, subExpr, MPInt(-1));
+      levelSet.addBound(BoundType::UB, subExpr, DynamicAPInt(-1));
       break;
     case OrderingKind::GT:
       // For greater than, we add a lower bound of 1:
       //        outA - outB >= 1
       //        outA > outB + 1
       //        outA > outB
-      levelSet.addBound(BoundType::LB, subExpr, MPInt(1));
+      levelSet.addBound(BoundType::LB, subExpr, DynamicAPInt(1));
       break;
     case OrderingKind::GE:
     case OrderingKind::LE:
@@ -389,7 +390,7 @@ void MultiAffineFunction::subtract(const MultiAffineFunction &other) {
   MultiAffineFunction copyOther = other;
   mergeDivs(copyOther);
   for (unsigned i = 0, e = getNumOutputs(); i < e; ++i)
-    output.addToRow(i, copyOther.getOutputExpr(i), MPInt(-1));
+    output.addToRow(i, copyOther.getOutputExpr(i), DynamicAPInt(-1));
 
   // Check consistency.
   assertIsConsistent();
@@ -429,14 +430,14 @@ IntegerRelation MultiAffineFunction::getAsRelation() const {
 
   // Add equalities such that the i^th range variable is equal to the i^th
   // output expression.
-  SmallVector<MPInt, 8> eq(result.getNumCols());
+  SmallVector<DynamicAPInt, 8> eq(result.getNumCols());
   for (unsigned i = 0, e = getNumOutputs(); i < e; ++i) {
     // TODO: Add functions to get VarKind offsets in output in MAF and use them
     // here.
     // The output expression does not contain range variables, while the
     // equality does. So, we need to copy all variables and mark all range
     // variables as 0 in the equality.
-    ArrayRef<MPInt> expr = getOutputExpr(i);
+    ArrayRef<DynamicAPInt> expr = getOutputExpr(i);
     // Copy domain variables in `expr` to domain variables in `eq`.
     std::copy(expr.begin(), expr.begin() + getNumDomainVars(), eq.begin());
     // Fill the range variables in `eq` as zero.
@@ -462,8 +463,8 @@ void PWMAFunction::removeOutputs(unsigned start, unsigned end) {
     piece.output.removeOutputs(start, end);
 }
 
-std::optional<SmallVector<MPInt, 8>>
-PWMAFunction::valueAt(ArrayRef<MPInt> point) const {
+std::optional<SmallVector<DynamicAPInt, 8>>
+PWMAFunction::valueAt(ArrayRef<DynamicAPInt> point) const {
   assert(point.size() == getNumDomainVars() + getNumSymbolVars());
 
   for (const Piece &piece : pieces)
diff --git a/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp b/mlir/lib/Analysis/Presburger/PresburgerRelation.cpp
index 3af6baae0e700..6173f774d0475 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"
@@ -122,7 +121,7 @@ PresburgerRelation::unionSet(const PresburgerRelation &set) const {
 }
 
 /// A point is contained in the union iff any of the parts contain the point.
-bool PresburgerRelation::containsPoint(ArrayRef<MPInt> point) const {
+bool PresburgerRelation::containsPoint(ArrayRef<DynamicAPInt> point) const {
   return llvm::any_of(disjuncts, [&](const IntegerRelation &disjunct) {
     return (disjunct.containsPointNoLocal(point));
   });
@@ -286,15 +285,15 @@ SymbolicLexOpt PresburgerRelation::findSymbolicIntegerLexMax() const {
 ///
 /// For every eq `coeffs == 0` there are two possible ineqs to index into.
 /// The first is coeffs >= 0 and the second is coeffs <= 0.
-static SmallVector<MPInt, 8> getIneqCoeffsFromIdx(const IntegerRelation &rel,
-                                                  unsigned idx) {
+static SmallVector<DynamicAPInt, 8>
+getIneqCoeffsFromIdx(const IntegerRelation &rel, unsigned idx) {
   assert(idx < rel.getNumInequalities() + 2 * rel.getNumEqualities() &&
          "idx out of bounds!");
   if (idx < rel.getNumInequalities())
     return llvm::to_vector<8>(rel.getInequality(idx));
 
   idx -= rel.getNumInequalities();
-  ArrayRef<MPInt> eqCoeffs = rel.getEquality(idx / 2);
+  ArrayRef<DynamicAPInt> eqCoeffs = rel.getEquality(idx / 2);
 
   if (idx % 2 == 0)
     return llvm::to_vector<8>(eqCoeffs);
@@ -554,7 +553,7 @@ static PresburgerRelation getSetDifference(IntegerRelation b,
         // state before adding this complement constraint, and add s_ij to b.
         simplex.rollback(frame.simplexSnapshot);
         b.truncate(frame.bCounts);
-        SmallVector<MPInt, 8> ineq =
+        SmallVector<DynamicAPInt, 8> ineq =
             getIneqCoeffsFromIdx(frame.sI, *frame.lastIneqProcessed);
         b.addInequality(ineq);
         simplex.addInequality(ineq);
@@ -572,7 +571,7 @@ static PresburgerRelation getSetDifference(IntegerRelation b,
       frame.simplexSnapshot = simplex.getSnapshot();
 
       unsigned idx = frame.ineqsToProcess.back();
-      SmallVector<MPInt, 8> ineq =
+      SmallVector<DynamicAPInt, 8> ineq =
           getComplementIneq(getIneqCoeffsFromIdx(frame.sI, idx));
       b.addInequality(ineq);
       simplex.addInequality(ineq);
@@ -670,10 +669,11 @@ bool PresburgerRelation::isIntegerEmpty() const {
   return llvm::all_of(disjuncts, std::mem_fn(&IntegerRelation::isIntegerEmpty));
 }
 
-bool PresburgerRelation::findIntegerSample(SmallVectorImpl<MPInt> &sample) {
+bool PresburgerRelation::findIntegerSample(
+    SmallVectorImpl<DynamicAPInt> &sample) {
   // A sample exists iff any of the disjuncts contains a sample.
   for (const IntegerRelation &disjunct : disjuncts) {
-    if (std::optional<SmallVector<MPInt, 8>> opt =
+    if (std::optional<SmallVector<DynamicAPInt, 8>> opt =
             disjunct.findIntegerSample()) {
       sample = std::move(*opt);
       return true;
@@ -682,13 +682,13 @@ bool PresburgerRelation::findIntegerSample(SmallVectorImpl<MPInt> &sample) {
   return false;
 }
 
-std::optional<MPInt> PresburgerRelation::computeVolume() const {
+std::optional<DynamicAPInt> PresburgerRelation::computeVolume() const {
   assert(getNumSymbolVars() == 0 && "Symbols are not yet supported!");
   // The sum of the volumes of the disjuncts is a valid overapproximation of the
   // volume of their union, even if they overlap.
-  MPInt result(0);
+  DynamicAPInt result(0);
   for (const IntegerRelation &disjunct : disjuncts) {
-    std::optional<MPInt> volume = disjunct.computeVolume();
+    std::optional<DynamicAPInt> volume = disjunct.computeVolume();
     if (!volume)
       return {};
     result += *volume;
@@ -723,20 +723,20 @@ class presburger::SetCoalescer {
 
   /// The list of all inversed equalities during typing. This ensures that
   /// the constraints exist even after the typing function has concluded.
-  SmallVector<SmallVector<MPInt, 2>, 2> negEqs;
+  SmallVector<SmallVector<DynamicAPInt, 2>, 2> negEqs;
 
   /// `redundantIneqsA` is the inequalities of `a` that are redundant for `b`
   /// (similarly for `cuttingIneqsA`, `redundantIneqsB`, and `cuttingIneqsB`).
-  SmallVector<ArrayRef<MPInt>, 2> redundantIneqsA;
-  SmallVector<ArrayRef<MPInt>, 2> cuttingIneqsA;
+  SmallVector<ArrayRef<DynamicAPInt>, 2> redundantIneqsA;
+  SmallVector<ArrayRef<DynamicAPInt>, 2> cuttingIneqsA;
 
-  SmallVector<ArrayRef<MPInt>, 2> redundantIneqsB;
-  SmallVector<ArrayRef<MPInt>, 2> cuttingIneqsB;
+  SmallVector<ArrayRef<DynamicAPInt>, 2> redundantIneqsB;
+  SmallVector<ArrayRef<DynamicAPInt>, 2> cuttingIneqsB;
 
   /// Given a Simplex `simp` and one of its inequalities `ineq`, check
   /// that the facet of `simp` where `ineq` holds as an equality is contained
   /// within `a`.
-  bool isFacetContained(ArrayRef<MPInt> ineq, Simplex &simp);
+  bool isFacetContained(ArrayRef<DynamicAPInt> ineq, Simplex &simp);
 
   /// Removes redundant constraints from `disjunct`, adds it to `disjuncts` and
   /// removes the disjuncts at position `i` and `j`. Updates `simplices` to
@@ -760,13 +760,13 @@ class presburger::SetCoalescer {
   /// Types the inequality `ineq` according to its `IneqType` for `simp` into
   /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
   /// inequalities were encountered. Otherwise, returns failure.
-  LogicalResult typeInequality(ArrayRef<MPInt> ineq, Simplex &simp);
+  LogicalResult typeInequality(ArrayRef<DynamicAPInt> ineq, Simplex &simp);
 
   /// Types the equality `eq`, i.e. for `eq` == 0, types both `eq` >= 0 and
   /// -`eq` >= 0 according to their `IneqType` for `simp` into
   /// `redundantIneqsB` and `cuttingIneqsB`. Returns success, if no separate
   /// inequalities were encountered. Otherwise, returns failure.
-  LogicalResult typeEquality(ArrayRef<MPInt> eq, Simplex &simp);
+  LogicalResult typeEquality(ArrayRef<DynamicAPInt> eq, Simplex &simp);
 
   /// Replaces the element at position `i` with the last element and erases
   /// the last element for both `disjuncts` and `simplices`.
@@ -843,10 +843,11 @@ PresburgerRelation SetCoalescer::coalesce() {
 /// Given a Simplex `simp` and one of its inequalities `ineq`, check
 /// that all inequalities of `cuttingIneqsB` are redundant for the facet of
 /// `simp` where `ineq` holds as an equality is contained within `a`.
-bool SetCoalescer::isFacetContained(ArrayRef<MPInt> ineq, Simplex &simp) {
+bool SetCoalescer::isFacetContained(ArrayRef<DynamicAPInt> ineq,
+                                    Simplex &simp) {
   SimplexRollbackScopeExit scopeExit(simp);
   simp.addEquality(ineq);
-  return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<MPInt> curr) {
+  return llvm::all_of(cuttingIneqsB, [&simp](ArrayRef<DynamicAPInt> curr) {
     return simp.isRedundantInequality(curr);
   });
 }
@@ -908,23 +909,23 @@ LogicalResult SetCoalescer::coalescePairCutCase(unsigned i, unsigned j) {
   /// redundant ones are, so only the cutting ones remain to be checked.
   Simplex &simp = simplices[i];
   IntegerRelation &disjunct = disjuncts[i];
-  if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<MPInt> curr) {
+  if (llvm::any_of(cuttingIneqsA, [this, &simp](ArrayRef<DynamicAPInt> curr) {
         return !isFacetContained(curr, simp);
       }))
     return failure();
   IntegerRelation newSet(disjunct.getSpace());
 
-  for (ArrayRef<MPInt> curr : redundantIneqsA)
+  for (ArrayRef<DynamicAPInt> curr : redundantIneqsA)
     newSet.addInequality(curr);
 
-  for (ArrayRef<MPInt> curr : redundantIneqsB)
+  for (ArrayRef<DynamicAPInt> curr : redundantIneqsB)
     newSet.addInequality(curr);
 
   addCoalescedDisjunct(i, j, newSet);
   return success();
 }
 
-LogicalResult SetCoalescer::typeInequality(ArrayRef<MPInt> ineq,
+LogicalResult SetCoalescer::typeInequality(ArrayRef<DynamicAPInt> ineq,
                                            Simplex &simp) {
   Simplex::IneqType type = simp.findIneqType(ineq);
   if (type == Simplex::IneqType::Redundant)
@@ -936,11 +937,12 @@ LogicalResult SetCoalescer::typeInequality(ArrayRef<MPInt> ineq,
   return success();
 }
 
-LogicalResult SetCoalescer::typeEquality(ArrayRef<MPInt> eq, Simplex &simp) {
+LogicalResult SetCoalescer::typeEquality(ArrayRef<DynamicAPInt> eq,
+                                         Simplex &simp) {
   if (typeInequality(eq, simp).failed())
     return failure();
   negEqs.push_back(getNegatedCoeffs(eq));
-  ArrayRef<MPInt> inv(negEqs.back());
+  ArrayRef<DynamicAPInt> inv(negEqs.back());
   if (typeInequality(inv, simp).failed())
     return failure();
   return success();
diff --git a/mlir/lib/Analysis/Presburger/Simplex.cpp b/mlir/lib/Analysis/Presburger/Simplex.cpp
index 1969cce93ad2e..2cdd79d42732d 100644
--- a/mlir/lib/Analysis/Presburger/Simplex.cpp
+++ b/mlir/lib/Analysis/Presburger/Simplex.cpp
@@ -9,7 +9,6 @@
 #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"
@@ -37,10 +36,11 @@ const int nullIndex = std::numeric_limits<int>::max();
 
 // Return a + scale*b;
 LLVM_ATTRIBUTE_UNUSED
-static SmallVector<MPInt, 8>
-scaleAndAddForAssert(ArrayRef<MPInt> a, const MPInt &scale, ArrayRef<MPInt> b) {
+static SmallVector<DynamicAPInt, 8>
+scaleAndAddForAssert(ArrayRef<DynamicAPInt> a, const DynamicAPInt &scale,
+                     ArrayRef<DynamicAPInt> b) {
   assert(a.size() == b.size());
-  SmallVector<MPInt, 8> res;
+  SmallVector<DynamicAPInt, 8> res;
   res.reserve(a.size());
   for (unsigned i = 0, e = a.size(); i < e; ++i)
     res.push_back(a[i] + scale * b[i]);
@@ -116,7 +116,8 @@ unsigned SimplexBase::addZeroRow(bool makeRestricted) {
 /// Add a new row to the tableau corresponding to the given constant term and
 /// list of coefficients. The coefficients are specified as a vector of
 /// (variable index, coefficient) pairs.
-unsigned SimplexBase::addRow(ArrayRef<MPInt> coeffs, bool makeRestricted) {
+unsigned SimplexBase::addRow(ArrayRef<DynamicAPInt> coeffs,
+                             bool makeRestricted) {
   assert(coeffs.size() == var.size() + 1 &&
          "Incorrect number of coefficients!");
   assert(var.size() + getNumFixedCols() == getNumColumns() &&
@@ -139,7 +140,7 @@ unsigned SimplexBase::addRow(ArrayRef<MPInt> coeffs, bool makeRestricted) {
     //
     // Symbols don't use the big M parameter since they do not get lex
     // optimized.
-    MPInt bigMCoeff(0);
+    DynamicAPInt bigMCoeff(0);
     for (unsigned i = 0; i < coeffs.size() - 1; ++i)
       if (!var[i].isSymbol)
         bigMCoeff -= coeffs[i];
@@ -165,9 +166,9 @@ 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 nRowCoeff = lcm / tableau(newRow, 0);
-    MPInt idxRowCoeff = coeffs[i] * (lcm / tableau(pos, 0));
+    DynamicAPInt lcm = llvm::lcm(tableau(newRow, 0), tableau(pos, 0));
+    DynamicAPInt nRowCoeff = lcm / tableau(newRow, 0);
+    DynamicAPInt idxRowCoeff = coeffs[i] * (lcm / tableau(pos, 0));
     tableau(newRow, 0) = lcm;
     for (unsigned col = 1, e = getNumColumns(); col < e; ++col)
       tableau(newRow, col) =
@@ -180,7 +181,7 @@ unsigned SimplexBase::addRow(ArrayRef<MPInt> coeffs, bool makeRestricted) {
 }
 
 namespace {
-bool signMatchesDirection(const MPInt &elem, Direction direction) {
+bool signMatchesDirection(const DynamicAPInt &elem, Direction direction) {
   assert(elem != 0 && "elem should not be 0");
   return direction == Direction::Up ? elem > 0 : elem < 0;
 }
@@ -276,7 +277,7 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::findRationalLexMin() {
 /// The constraint is violated when added (it would be useless otherwise)
 /// so we immediately try to move it to a column.
 LogicalResult LexSimplexBase::addCut(unsigned row) {
-  MPInt d = tableau(row, 0);
+  DynamicAPInt d = tableau(row, 0);
   unsigned cutRow = addZeroRow(/*makeRestricted=*/true);
   tableau(cutRow, 0) = d;
   tableau(cutRow, 1) = -mod(-tableau(row, 1), d); // -c%d.
@@ -300,7 +301,7 @@ std::optional<unsigned> LexSimplex::maybeGetNonIntegralVarRow() const {
   return {};
 }
 
-MaybeOptimum<SmallVector<MPInt, 8>> LexSimplex::findIntegerLexMin() {
+MaybeOptimum<SmallVector<DynamicAPInt, 8>> LexSimplex::findIntegerLexMin() {
   // We first try to make the tableau consistent.
   if (restoreRationalConsistency().failed())
     return OptimumKind::Empty;
@@ -331,19 +332,19 @@ MaybeOptimum<SmallVector<MPInt, 8>> LexSimplex::findIntegerLexMin() {
       llvm::map_range(*sample, std::mem_fn(&Fraction::getAsInteger)));
 }
 
-bool LexSimplex::isSeparateInequality(ArrayRef<MPInt> coeffs) {
+bool LexSimplex::isSeparateInequality(ArrayRef<DynamicAPInt> coeffs) {
   SimplexRollbackScopeExit scopeExit(*this);
   addInequality(coeffs);
   return findIntegerLexMin().isEmpty();
 }
 
-bool LexSimplex::isRedundantInequality(ArrayRef<MPInt> coeffs) {
+bool LexSimplex::isRedundantInequality(ArrayRef<DynamicAPInt> coeffs) {
   return isSeparateInequality(getComplementIneq(coeffs));
 }
 
-SmallVector<MPInt, 8>
+SmallVector<DynamicAPInt, 8>
 SymbolicLexSimplex::getSymbolicSampleNumerator(unsigned row) const {
-  SmallVector<MPInt, 8> sample;
+  SmallVector<DynamicAPInt, 8> sample;
   sample.reserve(nSymbol + 1);
   for (unsigned col = 3; col < 3 + nSymbol; ++col)
     sample.push_back(tableau(row, col));
@@ -351,9 +352,9 @@ SymbolicLexSimplex::getSymbolicSampleNumerator(unsigned row) const {
   return sample;
 }
 
-SmallVector<MPInt, 8>
+SmallVector<DynamicAPInt, 8>
 SymbolicLexSimplex::getSymbolicSampleIneq(unsigned row) const {
-  SmallVector<MPInt, 8> sample = getSymbolicSampleNumerator(row);
+  SmallVector<DynamicAPInt, 8> sample = getSymbolicSampleNumerator(row);
   // The inequality is equivalent to the GCD-normalized one.
   normalizeRange(sample);
   return sample;
@@ -366,14 +367,15 @@ void LexSimplexBase::appendSymbol() {
   nSymbol++;
 }
 
-static bool isRangeDivisibleBy(ArrayRef<MPInt> range, const MPInt &divisor) {
+static bool isRangeDivisibleBy(ArrayRef<DynamicAPInt> range,
+                               const DynamicAPInt &divisor) {
   assert(divisor > 0 && "divisor must be positive!");
-  return llvm::all_of(range,
-                      [divisor](const MPInt &x) { return x % divisor == 0; });
+  return llvm::all_of(
+      range, [divisor](const DynamicAPInt &x) { return x % divisor == 0; });
 }
 
 bool SymbolicLexSimplex::isSymbolicSampleIntegral(unsigned row) const {
-  MPInt denom = tableau(row, 0);
+  DynamicAPInt denom = tableau(row, 0);
   return tableau(row, 1) % denom == 0 &&
          isRangeDivisibleBy(tableau.getRow(row).slice(3, nSymbol), denom);
 }
@@ -412,7 +414,7 @@ bool SymbolicLexSimplex::isSymbolicSampleIntegral(unsigned row) const {
 /// This constraint is violated when added so we immediately try to move it to a
 /// column.
 LogicalResult SymbolicLexSimplex::addSymbolicCut(unsigned row) {
-  MPInt d = tableau(row, 0);
+  DynamicAPInt d = tableau(row, 0);
   if (isRangeDivisibleBy(tableau.getRow(row).slice(3, nSymbol), d)) {
     // The coefficients of symbols in the symbol numerator are divisible
     // by the denominator, so we can add the constraint directly,
@@ -421,9 +423,9 @@ LogicalResult SymbolicLexSimplex::addSymbolicCut(unsigned row) {
   }
 
   // Construct the division variable `q = ((-c%d) + sum_i (-a_i%d)s_i)/d`.
-  SmallVector<MPInt, 8> divCoeffs;
+  SmallVector<DynamicAPInt, 8> divCoeffs;
   divCoeffs.reserve(nSymbol + 1);
-  MPInt divDenom = d;
+  DynamicAPInt divDenom = d;
   for (unsigned col = 3; col < 3 + nSymbol; ++col)
     divCoeffs.push_back(mod(-tableau(row, col), divDenom)); // (-a_i%d)s_i
   divCoeffs.push_back(mod(-tableau(row, 1), divDenom));     // -c%d.
@@ -464,7 +466,7 @@ void SymbolicLexSimplex::recordOutput(SymbolicLexOpt &result) const {
       return;
     }
 
-    MPInt denom = tableau(u.pos, 0);
+    DynamicAPInt denom = tableau(u.pos, 0);
     if (tableau(u.pos, 2) < denom) {
       // M + u has a sample value of fM + something, where f < 1, so
       // u = (f - 1)M + something, which has a negative coefficient for M,
@@ -475,8 +477,8 @@ void SymbolicLexSimplex::recordOutput(SymbolicLexOpt &result) const {
     assert(tableau(u.pos, 2) == denom &&
            "Coefficient of M should not be greater than 1!");
 
-    SmallVector<MPInt, 8> sample = getSymbolicSampleNumerator(u.pos);
-    for (MPInt &elem : sample) {
+    SmallVector<DynamicAPInt, 8> sample = getSymbolicSampleNumerator(u.pos);
+    for (DynamicAPInt &elem : sample) {
       assert(elem % denom == 0 && "coefficients must be integral!");
       elem /= denom;
     }
@@ -573,7 +575,7 @@ SymbolicLexOpt SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
         continue;
       }
 
-      SmallVector<MPInt, 8> symbolicSample;
+      SmallVector<DynamicAPInt, 8> symbolicSample;
       unsigned splitRow = 0;
       for (unsigned e = getNumRows(); splitRow < e; ++splitRow) {
         if (tableau(splitRow, 2) > 0)
@@ -658,7 +660,7 @@ SymbolicLexOpt SymbolicLexSimplex::computeSymbolicIntegerLexMin() {
       // was negative.
       assert(u.orientation == Orientation::Row &&
              "The split row should have been returned to row orientation!");
-      SmallVector<MPInt, 8> splitIneq =
+      SmallVector<DynamicAPInt, 8> splitIneq =
           getComplementIneq(getSymbolicSampleIneq(u.pos));
       normalizeRange(splitIneq);
       if (moveRowUnknownToColumn(u.pos).failed()) {
@@ -834,7 +836,7 @@ unsigned LexSimplexBase::getLexMinPivotColumn(unsigned row, unsigned colA,
   // all possible values of the symbols.
   auto getSampleChangeCoeffForVar = [this, row](unsigned col,
                                                 const Unknown &u) -> Fraction {
-    MPInt a = tableau(row, col);
+    DynamicAPInt a = tableau(row, col);
     if (u.orientation == Orientation::Column) {
       // Pivot column case.
       if (u.pos == col)
@@ -849,7 +851,7 @@ unsigned LexSimplexBase::getLexMinPivotColumn(unsigned row, unsigned colA,
       return {1, 1};
 
     // Non-pivot row case.
-    MPInt c = tableau(u.pos, col);
+    DynamicAPInt c = tableau(u.pos, col);
     return {c, a};
   };
 
@@ -883,7 +885,7 @@ std::optional<SimplexBase::Pivot>
 Simplex::findPivot(int row, Direction direction) const {
   std::optional<unsigned> col;
   for (unsigned j = 2, e = getNumColumns(); j < e; ++j) {
-    MPInt elem = tableau(row, j);
+    DynamicAPInt elem = tableau(row, j);
     if (elem == 0)
       continue;
 
@@ -1032,18 +1034,18 @@ std::optional<unsigned> Simplex::findPivotRow(std::optional<unsigned> skipRow,
   // retConst being used uninitialized in the initialization of `diff` below. In
   // reality, these are always initialized when that line is reached since these
   // are set whenever retRow is set.
-  MPInt retElem, retConst;
+  DynamicAPInt retElem, retConst;
   for (unsigned row = nRedundant, e = getNumRows(); row < e; ++row) {
     if (skipRow && row == *skipRow)
       continue;
-    MPInt elem = tableau(row, col);
+    DynamicAPInt elem = tableau(row, col);
     if (elem == 0)
       continue;
     if (!unknownFromRow(row).restricted)
       continue;
     if (signMatchesDirection(elem, direction))
       continue;
-    MPInt constTerm = tableau(row, 1);
+    DynamicAPInt constTerm = tableau(row, 1);
 
     if (!retRow) {
       retRow = row;
@@ -1052,7 +1054,7 @@ std::optional<unsigned> Simplex::findPivotRow(std::optional<unsigned> skipRow,
       continue;
     }
 
-    MPInt diff = retConst * elem - constTerm * retElem;
+    DynamicAPInt diff = retConst * elem - constTerm * retElem;
     if ((diff == 0 && rowUnknown[row] < rowUnknown[*retRow]) ||
         (diff != 0 && !signMatchesDirection(diff, direction))) {
       retRow = row;
@@ -1103,7 +1105,7 @@ void SimplexBase::markEmpty() {
 /// We add the inequality and mark it as restricted. We then try to make its
 /// sample value non-negative. If this is not possible, the tableau has become
 /// empty and we mark it as such.
-void Simplex::addInequality(ArrayRef<MPInt> coeffs) {
+void Simplex::addInequality(ArrayRef<DynamicAPInt> coeffs) {
   unsigned conIndex = addRow(coeffs, /*makeRestricted=*/true);
   LogicalResult result = restoreRow(con[conIndex]);
   if (failed(result))
@@ -1116,10 +1118,10 @@ void Simplex::addInequality(ArrayRef<MPInt> coeffs) {
 ///
 /// We simply add two opposing inequalities, which force the expression to
 /// be zero.
-void SimplexBase::addEquality(ArrayRef<MPInt> coeffs) {
+void SimplexBase::addEquality(ArrayRef<DynamicAPInt> coeffs) {
   addInequality(coeffs);
-  SmallVector<MPInt, 8> negatedCoeffs;
-  for (const MPInt &coeff : coeffs)
+  SmallVector<DynamicAPInt, 8> negatedCoeffs;
+  for (const DynamicAPInt &coeff : coeffs)
     negatedCoeffs.emplace_back(-coeff);
   addInequality(negatedCoeffs);
 }
@@ -1295,18 +1297,18 @@ void SimplexBase::rollback(unsigned snapshot) {
 ///
 /// This constrains the remainder `coeffs - denom*q` to be in the
 /// range `[0, denom - 1]`, which fixes the integer value of the quotient `q`.
-void SimplexBase::addDivisionVariable(ArrayRef<MPInt> coeffs,
-                                      const MPInt &denom) {
+void SimplexBase::addDivisionVariable(ArrayRef<DynamicAPInt> coeffs,
+                                      const DynamicAPInt &denom) {
   assert(denom > 0 && "Denominator must be positive!");
   appendVariable();
 
-  SmallVector<MPInt, 8> ineq(coeffs.begin(), coeffs.end());
-  MPInt constTerm = ineq.back();
+  SmallVector<DynamicAPInt, 8> ineq(coeffs.begin(), coeffs.end());
+  DynamicAPInt constTerm = ineq.back();
   ineq.back() = -denom;
   ineq.push_back(constTerm);
   addInequality(ineq);
 
-  for (MPInt &coeff : ineq)
+  for (DynamicAPInt &coeff : ineq)
     coeff = -coeff;
   ineq.back() += denom - 1;
   addInequality(ineq);
@@ -1356,7 +1358,7 @@ MaybeOptimum<Fraction> Simplex::computeRowOptimum(Direction direction,
 /// Compute the optimum of the specified expression in the specified direction,
 /// or std::nullopt if it is unbounded.
 MaybeOptimum<Fraction> Simplex::computeOptimum(Direction direction,
-                                               ArrayRef<MPInt> coeffs) {
+                                               ArrayRef<DynamicAPInt> coeffs) {
   if (empty)
     return OptimumKind::Empty;
 
@@ -1466,7 +1468,7 @@ bool Simplex::isUnbounded() {
   if (empty)
     return false;
 
-  SmallVector<MPInt, 8> dir(var.size() + 1);
+  SmallVector<DynamicAPInt, 8> dir(var.size() + 1);
   for (unsigned i = 0; i < var.size(); ++i) {
     dir[i] = 1;
 
@@ -1576,14 +1578,14 @@ std::optional<SmallVector<Fraction, 8>> Simplex::getRationalSample() const {
     } else {
       // If the variable is in row position, its sample value is the
       // entry in the constant column divided by the denominator.
-      MPInt denom = tableau(u.pos, 0);
+      DynamicAPInt denom = tableau(u.pos, 0);
       sample.emplace_back(tableau(u.pos, 1), denom);
     }
   }
   return sample;
 }
 
-void LexSimplexBase::addInequality(ArrayRef<MPInt> coeffs) {
+void LexSimplexBase::addInequality(ArrayRef<DynamicAPInt> coeffs) {
   addRow(coeffs, /*makeRestricted=*/true);
 }
 
@@ -1608,7 +1610,7 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
 
     // If the variable is in row position, its sample value is the
     // entry in the constant column divided by the denominator.
-    MPInt denom = tableau(u.pos, 0);
+    DynamicAPInt denom = tableau(u.pos, 0);
     if (usingBigM)
       if (tableau(u.pos, 2) != denom)
         return OptimumKind::Unbounded;
@@ -1617,14 +1619,15 @@ MaybeOptimum<SmallVector<Fraction, 8>> LexSimplex::getRationalSample() const {
   return sample;
 }
 
-std::optional<SmallVector<MPInt, 8>> Simplex::getSamplePointIfIntegral() const {
+std::optional<SmallVector<DynamicAPInt, 8>>
+Simplex::getSamplePointIfIntegral() const {
   // If the tableau is empty, no sample point exists.
   if (empty)
     return {};
 
   // The value will always exist since the Simplex is non-empty.
   SmallVector<Fraction, 8> rationalSample = *getRationalSample();
-  SmallVector<MPInt, 8> integerSample;
+  SmallVector<DynamicAPInt, 8> integerSample;
   integerSample.reserve(var.size());
   for (const Fraction &coord : rationalSample) {
     // If the sample is non-integral, return std::nullopt.
@@ -1656,14 +1659,14 @@ class presburger::GBRSimplex {
   /// Add an equality dotProduct(dir, x - y) == 0.
   /// First pushes a snapshot for the current simplex state to the stack so
   /// that this can be rolled back later.
-  void addEqualityForDirection(ArrayRef<MPInt> dir) {
-    assert(llvm::any_of(dir, [](const MPInt &x) { return x != 0; }) &&
+  void addEqualityForDirection(ArrayRef<DynamicAPInt> dir) {
+    assert(llvm::any_of(dir, [](const DynamicAPInt &x) { return x != 0; }) &&
            "Direction passed is the zero vector!");
     snapshotStack.push_back(simplex.getSnapshot());
     simplex.addEquality(getCoeffsForDirection(dir));
   }
   /// Compute max(dotProduct(dir, x - y)).
-  Fraction computeWidth(ArrayRef<MPInt> dir) {
+  Fraction computeWidth(ArrayRef<DynamicAPInt> dir) {
     MaybeOptimum<Fraction> maybeWidth =
         simplex.computeOptimum(Direction::Up, getCoeffsForDirection(dir));
     assert(maybeWidth.isBounded() && "Width should be bounded!");
@@ -1672,9 +1675,9 @@ class presburger::GBRSimplex {
 
   /// Compute max(dotProduct(dir, x - y)) and save the dual variables for only
   /// the direction equalities to `dual`.
-  Fraction computeWidthAndDuals(ArrayRef<MPInt> dir,
-                                SmallVectorImpl<MPInt> &dual,
-                                MPInt &dualDenom) {
+  Fraction computeWidthAndDuals(ArrayRef<DynamicAPInt> dir,
+                                SmallVectorImpl<DynamicAPInt> &dual,
+                                DynamicAPInt &dualDenom) {
     // We can't just call into computeWidth or computeOptimum since we need to
     // access the state of the tableau after computing the optimum, and these
     // functions rollback the insertion of the objective function into the
@@ -1742,12 +1745,13 @@ class presburger::GBRSimplex {
   /// i.e.,   dir_1 * x_1 + dir_2 * x_2 + ... + dir_n * x_n
   ///       - dir_1 * y_1 - dir_2 * y_2 - ... - dir_n * y_n,
   /// where n is the dimension of the original polytope.
-  SmallVector<MPInt, 8> getCoeffsForDirection(ArrayRef<MPInt> dir) {
+  SmallVector<DynamicAPInt, 8>
+  getCoeffsForDirection(ArrayRef<DynamicAPInt> dir) {
     assert(2 * dir.size() == simplex.getNumVariables() &&
            "Direction vector has wrong dimensionality");
-    SmallVector<MPInt, 8> coeffs(dir.begin(), dir.end());
+    SmallVector<DynamicAPInt, 8> coeffs(dir.begin(), dir.end());
     coeffs.reserve(2 * dir.size());
-    for (const MPInt &coeff : dir)
+    for (const DynamicAPInt &coeff : dir)
       coeffs.push_back(-coeff);
     coeffs.emplace_back(0); // constant term
     return coeffs;
@@ -1824,8 +1828,8 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) {
 
   GBRSimplex gbrSimplex(*this);
   SmallVector<Fraction, 8> width;
-  SmallVector<MPInt, 8> dual;
-  MPInt dualDenom;
+  SmallVector<DynamicAPInt, 8> dual;
+  DynamicAPInt dualDenom;
 
   // Finds the value of u that minimizes width_i(b_{i+1} + u*b_i), caches the
   // duals from this computation, sets b_{i+1} to b_{i+1} + u*b_i, and returns
@@ -1848,11 +1852,11 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) {
   auto updateBasisWithUAndGetFCandidate = [&](unsigned i) -> Fraction {
     assert(i < level + dual.size() && "dual_i is not known!");
 
-    MPInt u = floorDiv(dual[i - level], dualDenom);
+    DynamicAPInt u = floorDiv(dual[i - level], dualDenom);
     basis.addToRow(i, i + 1, u);
     if (dual[i - level] % dualDenom != 0) {
-      SmallVector<MPInt, 8> candidateDual[2];
-      MPInt candidateDualDenom[2];
+      SmallVector<DynamicAPInt, 8> candidateDual[2];
+      DynamicAPInt candidateDualDenom[2];
       Fraction widthI[2];
 
       // Initially u is floor(dual) and basis reflects this.
@@ -1879,12 +1883,12 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) {
 
       // Check the value at u - 1.
       assert(gbrSimplex.computeWidth(scaleAndAddForAssert(
-                 basis.getRow(i + 1), MPInt(-1), basis.getRow(i))) >=
+                 basis.getRow(i + 1), DynamicAPInt(-1), basis.getRow(i))) >=
                  widthI[j] &&
              "Computed u value does not minimize the width!");
       // Check the value at u + 1.
       assert(gbrSimplex.computeWidth(scaleAndAddForAssert(
-                 basis.getRow(i + 1), MPInt(+1), basis.getRow(i))) >=
+                 basis.getRow(i + 1), DynamicAPInt(+1), basis.getRow(i))) >=
                  widthI[j] &&
              "Computed u value does not minimize the width!");
 
@@ -1985,7 +1989,7 @@ void Simplex::reduceBasis(IntMatrix &basis, unsigned level) {
 ///
 /// To avoid potentially arbitrarily large recursion depths leading to stack
 /// overflows, this algorithm is implemented iteratively.
-std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
+std::optional<SmallVector<DynamicAPInt, 8>> Simplex::findIntegerSample() {
   if (empty)
     return {};
 
@@ -1996,9 +2000,9 @@ std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
   // The snapshot just before constraining a direction to a value at each level.
   SmallVector<unsigned, 8> snapshotStack;
   // The maximum value in the range of the direction for each level.
-  SmallVector<MPInt, 8> upperBoundStack;
+  SmallVector<DynamicAPInt, 8> upperBoundStack;
   // The next value to try constraining the basis vector to at each level.
-  SmallVector<MPInt, 8> nextValueStack;
+  SmallVector<DynamicAPInt, 8> nextValueStack;
 
   snapshotStack.reserve(basis.getNumRows());
   upperBoundStack.reserve(basis.getNumRows());
@@ -2018,7 +2022,7 @@ std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
       // just come down a level ("recursed"). Find the lower and upper bounds.
       // If there is more than one integer point in the range, perform
       // generalized basis reduction.
-      SmallVector<MPInt, 8> basisCoeffs =
+      SmallVector<DynamicAPInt, 8> basisCoeffs =
           llvm::to_vector<8>(basis.getRow(level));
       basisCoeffs.emplace_back(0);
 
@@ -2070,7 +2074,7 @@ std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
     // to the snapshot of the starting state at this level. (in the "recursed"
     // case this has no effect)
     rollback(snapshotStack.back());
-    MPInt nextValue = nextValueStack.back();
+    DynamicAPInt nextValue = nextValueStack.back();
     ++nextValueStack.back();
     if (nextValue > upperBoundStack.back()) {
       // We have exhausted the range and found no solution. Pop the stack and
@@ -2083,8 +2087,8 @@ std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
     }
 
     // Try the next value in the range and "recurse" into the next level.
-    SmallVector<MPInt, 8> basisCoeffs(basis.getRow(level).begin(),
-                                      basis.getRow(level).end());
+    SmallVector<DynamicAPInt, 8> basisCoeffs(basis.getRow(level).begin(),
+                                             basis.getRow(level).end());
     basisCoeffs.push_back(-nextValue);
     addEquality(basisCoeffs);
     level++;
@@ -2095,16 +2099,16 @@ std::optional<SmallVector<MPInt, 8>> Simplex::findIntegerSample() {
 
 /// Compute the minimum and maximum integer values the expression can take. We
 /// compute each separately.
-std::pair<MaybeOptimum<MPInt>, MaybeOptimum<MPInt>>
-Simplex::computeIntegerBounds(ArrayRef<MPInt> coeffs) {
-  MaybeOptimum<MPInt> minRoundedUp(
+std::pair<MaybeOptimum<DynamicAPInt>, MaybeOptimum<DynamicAPInt>>
+Simplex::computeIntegerBounds(ArrayRef<DynamicAPInt> coeffs) {
+  MaybeOptimum<DynamicAPInt> minRoundedUp(
       computeOptimum(Simplex::Direction::Down, coeffs).map(ceil));
-  MaybeOptimum<MPInt> maxRoundedDown(
+  MaybeOptimum<DynamicAPInt> maxRoundedDown(
       computeOptimum(Simplex::Direction::Up, coeffs).map(floor));
   return {minRoundedUp, maxRoundedDown};
 }
 
-bool Simplex::isFlatAlong(ArrayRef<MPInt> coeffs) {
+bool Simplex::isFlatAlong(ArrayRef<DynamicAPInt> coeffs) {
   assert(!isEmpty() && "cannot check for flatness of empty simplex!");
   auto upOpt = computeOptimum(Simplex::Direction::Up, coeffs);
   auto downOpt = computeOptimum(Simplex::Direction::Down, coeffs);
@@ -2183,7 +2187,7 @@ bool Simplex::isRationalSubsetOf(const IntegerRelation &rel) {
 /// maximum satisfy it. Hence, it is a cut inequality. If both are < 0, no
 /// points of the polytope satisfy the inequality, which means it is a separate
 /// inequality.
-Simplex::IneqType Simplex::findIneqType(ArrayRef<MPInt> coeffs) {
+Simplex::IneqType Simplex::findIneqType(ArrayRef<DynamicAPInt> coeffs) {
   MaybeOptimum<Fraction> minimum = computeOptimum(Direction::Down, coeffs);
   if (minimum.isBounded() && *minimum >= Fraction(0, 1)) {
     return IneqType::Redundant;
@@ -2198,7 +2202,7 @@ Simplex::IneqType Simplex::findIneqType(ArrayRef<MPInt> coeffs) {
 
 /// Checks whether the type of the inequality with coefficients `coeffs`
 /// is Redundant.
-bool Simplex::isRedundantInequality(ArrayRef<MPInt> coeffs) {
+bool Simplex::isRedundantInequality(ArrayRef<DynamicAPInt> coeffs) {
   assert(!empty &&
          "It is not meaningful to ask about redundancy in an empty set!");
   return findIneqType(coeffs) == IneqType::Redundant;
@@ -2208,7 +2212,7 @@ bool Simplex::isRedundantInequality(ArrayRef<MPInt> coeffs) {
 /// the existing constraints. This is redundant when `coeffs` is already
 /// always zero under the existing constraints. `coeffs` is always zero
 /// when the minimum and maximum value that `coeffs` can take are both zero.
-bool Simplex::isRedundantEquality(ArrayRef<MPInt> coeffs) {
+bool Simplex::isRedundantEquality(ArrayRef<DynamicAPInt> coeffs) {
   assert(!empty &&
          "It is not meaningful to ask about redundancy in an empty set!");
   MaybeOptimum<Fraction> minimum = computeOptimum(Direction::Down, coeffs);
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..1fab4c4dcca33 100644
--- a/mlir/lib/Analysis/Presburger/Utils.cpp
+++ b/mlir/lib/Analysis/Presburger/Utils.cpp
@@ -12,7 +12,6 @@
 
 #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"
@@ -31,19 +30,20 @@
 
 using namespace mlir;
 using namespace presburger;
+using llvm::dynamicAPIntFromInt64;
 
 /// 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,
 /// they get normalized to [1,0,2] and 2. The divisor must be non-negative;
 /// it is allowed for the divisor to be zero, but nothing is done in this case.
-static void normalizeDivisionByGCD(MutableArrayRef<MPInt> dividend,
-                                   MPInt &divisor) {
+static void normalizeDivisionByGCD(MutableArrayRef<DynamicAPInt> dividend,
+                                   DynamicAPInt &divisor) {
   assert(divisor > 0 && "divisor must be non-negative!");
   if (divisor == 0 || dividend.empty())
     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);
+  DynamicAPInt gcd = llvm::gcd(abs(dividend.front()), divisor);
 
   // The reason for ignoring the constant term is as follows.
   // For a division:
@@ -53,14 +53,14 @@ 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;
   }
 
   // Normalize the dividend and the denominator.
   std::transform(dividend.begin(), dividend.end(), dividend.begin(),
-                 [gcd](MPInt &n) { return floorDiv(n, gcd); });
+                 [gcd](DynamicAPInt &n) { return floorDiv(n, gcd); });
   divisor /= gcd;
 }
 
@@ -104,7 +104,8 @@ static void normalizeDivisionByGCD(MutableArrayRef<MPInt> dividend,
 /// The final division expression is normalized by GCD.
 static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
                                 unsigned ubIneq, unsigned lbIneq,
-                                MutableArrayRef<MPInt> expr, MPInt &divisor) {
+                                MutableArrayRef<DynamicAPInt> expr,
+                                DynamicAPInt &divisor) {
 
   assert(pos <= cst.getNumVars() && "Invalid variable position");
   assert(ubIneq <= cst.getNumInequalities() &&
@@ -131,9 +132,9 @@ static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
   // Then, check if the constant term is of the proper form.
   // Due to the form of the upper/lower bound inequalities, the sum of their
   // constants is `divisor - 1 - c`. From this, we can extract c:
-  MPInt constantSum = cst.atIneq(lbIneq, cst.getNumCols() - 1) +
-                      cst.atIneq(ubIneq, cst.getNumCols() - 1);
-  MPInt c = divisor - 1 - constantSum;
+  DynamicAPInt constantSum = cst.atIneq(lbIneq, cst.getNumCols() - 1) +
+                             cst.atIneq(ubIneq, cst.getNumCols() - 1);
+  DynamicAPInt c = divisor - 1 - constantSum;
 
   // Check if `c` satisfies the condition `0 <= c <= divisor - 1`.
   // This also implictly checks that `divisor` is positive.
@@ -168,8 +169,9 @@ static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
 /// set to the denominator of the division. The final division expression is
 /// normalized by GCD.
 static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
-                                unsigned eqInd, MutableArrayRef<MPInt> expr,
-                                MPInt &divisor) {
+                                unsigned eqInd,
+                                MutableArrayRef<DynamicAPInt> expr,
+                                DynamicAPInt &divisor) {
 
   assert(pos <= cst.getNumVars() && "Invalid variable position");
   assert(eqInd <= cst.getNumEqualities() && "Invalid equality position");
@@ -178,7 +180,7 @@ static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
   // Extract divisor, the divisor can be negative and hence its sign information
   // is stored in `signDiv` to reverse the sign of dividend's coefficients.
   // Equality must involve the pos-th variable and hence `tempDiv` != 0.
-  MPInt tempDiv = cst.atEq(eqInd, pos);
+  DynamicAPInt tempDiv = cst.atEq(eqInd, pos);
   if (tempDiv == 0)
     return failure();
   int signDiv = tempDiv < 0 ? -1 : 1;
@@ -200,7 +202,7 @@ static LogicalResult getDivRepr(const IntegerRelation &cst, unsigned pos,
 // explicit representation has not been found yet, otherwise returns `true`.
 static bool checkExplicitRepresentation(const IntegerRelation &cst,
                                         ArrayRef<bool> foundRepr,
-                                        ArrayRef<MPInt> dividend,
+                                        ArrayRef<DynamicAPInt> dividend,
                                         unsigned pos) {
   // Exit to avoid circular dependencies between divisions.
   for (unsigned c = 0, e = cst.getNumVars(); c < e; ++c) {
@@ -229,11 +231,9 @@ static bool checkExplicitRepresentation(const IntegerRelation &cst,
 /// the representation could be computed, `dividend` and `denominator` are set.
 /// If the representation could not be computed, the kind attribute in
 /// `MaybeLocalRepr` is set to None.
-MaybeLocalRepr presburger::computeSingleVarRepr(const IntegerRelation &cst,
-                                                ArrayRef<bool> foundRepr,
-                                                unsigned pos,
-                                                MutableArrayRef<MPInt> dividend,
-                                                MPInt &divisor) {
+MaybeLocalRepr presburger::computeSingleVarRepr(
+    const IntegerRelation &cst, ArrayRef<bool> foundRepr, unsigned pos,
+    MutableArrayRef<DynamicAPInt> dividend, DynamicAPInt &divisor) {
   assert(pos < cst.getNumVars() && "invalid position");
   assert(foundRepr.size() == cst.getNumVars() &&
          "Size of foundRepr does not match total number of variables");
@@ -275,12 +275,12 @@ MaybeLocalRepr presburger::computeSingleVarRepr(const IntegerRelation &cst,
 MaybeLocalRepr presburger::computeSingleVarRepr(
     const IntegerRelation &cst, ArrayRef<bool> foundRepr, unsigned pos,
     SmallVector<int64_t, 8> &dividend, unsigned &divisor) {
-  SmallVector<MPInt, 8> dividendMPInt(cst.getNumCols());
-  MPInt divisorMPInt;
-  MaybeLocalRepr result =
-      computeSingleVarRepr(cst, foundRepr, pos, dividendMPInt, divisorMPInt);
-  dividend = getInt64Vec(dividendMPInt);
-  divisor = unsigned(int64_t(divisorMPInt));
+  SmallVector<DynamicAPInt, 8> dividendDynamicAPInt(cst.getNumCols());
+  DynamicAPInt divisorDynamicAPInt;
+  MaybeLocalRepr result = computeSingleVarRepr(
+      cst, foundRepr, pos, dividendDynamicAPInt, divisorDynamicAPInt);
+  dividend = getInt64Vec(dividendDynamicAPInt);
+  divisor = unsigned(int64_t(divisorDynamicAPInt));
   return result;
 }
 
@@ -318,80 +318,86 @@ void presburger::mergeLocalVars(
   divsA.removeDuplicateDivs(merge);
 }
 
-SmallVector<MPInt, 8> presburger::getDivUpperBound(ArrayRef<MPInt> dividend,
-                                                   const MPInt &divisor,
-                                                   unsigned localVarIdx) {
+SmallVector<DynamicAPInt, 8>
+presburger::getDivUpperBound(ArrayRef<DynamicAPInt> dividend,
+                             const DynamicAPInt &divisor,
+                             unsigned localVarIdx) {
   assert(divisor > 0 && "divisor must be positive!");
   assert(dividend[localVarIdx] == 0 &&
          "Local to be set to division must have zero coeff!");
-  SmallVector<MPInt, 8> ineq(dividend.begin(), dividend.end());
+  SmallVector<DynamicAPInt, 8> ineq(dividend.begin(), dividend.end());
   ineq[localVarIdx] = -divisor;
   return ineq;
 }
 
-SmallVector<MPInt, 8> presburger::getDivLowerBound(ArrayRef<MPInt> dividend,
-                                                   const MPInt &divisor,
-                                                   unsigned localVarIdx) {
+SmallVector<DynamicAPInt, 8>
+presburger::getDivLowerBound(ArrayRef<DynamicAPInt> dividend,
+                             const DynamicAPInt &divisor,
+                             unsigned localVarIdx) {
   assert(divisor > 0 && "divisor must be positive!");
   assert(dividend[localVarIdx] == 0 &&
          "Local to be set to division must have zero coeff!");
-  SmallVector<MPInt, 8> ineq(dividend.size());
+  SmallVector<DynamicAPInt, 8> ineq(dividend.size());
   std::transform(dividend.begin(), dividend.end(), ineq.begin(),
-                 std::negate<MPInt>());
+                 std::negate<DynamicAPInt>());
   ineq[localVarIdx] = divisor;
   ineq.back() += divisor - 1;
   return ineq;
 }
 
-MPInt presburger::gcdRange(ArrayRef<MPInt> range) {
-  MPInt gcd(0);
-  for (const MPInt &elem : range) {
-    gcd = presburger::gcd(gcd, abs(elem));
+DynamicAPInt presburger::gcdRange(ArrayRef<DynamicAPInt> range) {
+  DynamicAPInt gcd(0);
+  for (const DynamicAPInt &elem : range) {
+    gcd = llvm::gcd(gcd, abs(elem));
     if (gcd == 1)
       return gcd;
   }
   return gcd;
 }
 
-MPInt presburger::normalizeRange(MutableArrayRef<MPInt> range) {
-  MPInt gcd = gcdRange(range);
+DynamicAPInt presburger::normalizeRange(MutableArrayRef<DynamicAPInt> range) {
+  DynamicAPInt gcd = gcdRange(range);
   if ((gcd == 0) || (gcd == 1))
     return gcd;
-  for (MPInt &elem : range)
+  for (DynamicAPInt &elem : range)
     elem /= gcd;
   return gcd;
 }
 
-void presburger::normalizeDiv(MutableArrayRef<MPInt> num, MPInt &denom) {
+void presburger::normalizeDiv(MutableArrayRef<DynamicAPInt> num,
+                              DynamicAPInt &denom) {
   assert(denom > 0 && "denom must be positive!");
-  MPInt gcd = presburger::gcd(gcdRange(num), denom);
-  for (MPInt &coeff : num)
+  DynamicAPInt gcd = llvm::gcd(gcdRange(num), denom);
+  for (DynamicAPInt &coeff : num)
     coeff /= gcd;
   denom /= gcd;
 }
 
-SmallVector<MPInt, 8> presburger::getNegatedCoeffs(ArrayRef<MPInt> coeffs) {
-  SmallVector<MPInt, 8> negatedCoeffs;
+SmallVector<DynamicAPInt, 8>
+presburger::getNegatedCoeffs(ArrayRef<DynamicAPInt> coeffs) {
+  SmallVector<DynamicAPInt, 8> negatedCoeffs;
   negatedCoeffs.reserve(coeffs.size());
-  for (const MPInt &coeff : coeffs)
+  for (const DynamicAPInt &coeff : coeffs)
     negatedCoeffs.emplace_back(-coeff);
   return negatedCoeffs;
 }
 
-SmallVector<MPInt, 8> presburger::getComplementIneq(ArrayRef<MPInt> ineq) {
-  SmallVector<MPInt, 8> coeffs;
+SmallVector<DynamicAPInt, 8>
+presburger::getComplementIneq(ArrayRef<DynamicAPInt> ineq) {
+  SmallVector<DynamicAPInt, 8> coeffs;
   coeffs.reserve(ineq.size());
-  for (const MPInt &coeff : ineq)
+  for (const DynamicAPInt &coeff : ineq)
     coeffs.emplace_back(-coeff);
   --coeffs.back();
   return coeffs;
 }
 
-SmallVector<std::optional<MPInt>, 4>
-DivisionRepr::divValuesAt(ArrayRef<MPInt> point) const {
+SmallVector<std::optional<DynamicAPInt>, 4>
+DivisionRepr::divValuesAt(ArrayRef<DynamicAPInt> point) const {
   assert(point.size() == getNumNonDivs() && "Incorrect point size");
 
-  SmallVector<std::optional<MPInt>, 4> divValues(getNumDivs(), std::nullopt);
+  SmallVector<std::optional<DynamicAPInt>, 4> divValues(getNumDivs(),
+                                                        std::nullopt);
   bool changed = true;
   while (changed) {
     changed = false;
@@ -400,8 +406,8 @@ DivisionRepr::divValuesAt(ArrayRef<MPInt> point) const {
       if (divValues[i])
         continue;
 
-      ArrayRef<MPInt> dividend = getDividend(i);
-      MPInt divVal(0);
+      ArrayRef<DynamicAPInt> dividend = getDividend(i);
+      DynamicAPInt divVal(0);
 
       // Check if we have all the division values required for this division.
       unsigned j, f;
@@ -490,8 +496,8 @@ void DivisionRepr::normalizeDivs() {
   }
 }
 
-void DivisionRepr::insertDiv(unsigned pos, ArrayRef<MPInt> dividend,
-                             const MPInt &divisor) {
+void DivisionRepr::insertDiv(unsigned pos, ArrayRef<DynamicAPInt> dividend,
+                             const DynamicAPInt &divisor) {
   assert(pos <= getNumDivs() && "Invalid insertion position");
   assert(dividend.size() == getNumVars() + 1 && "Incorrect dividend size");
 
@@ -504,29 +510,32 @@ void DivisionRepr::insertDiv(unsigned pos, unsigned num) {
   assert(pos <= getNumDivs() && "Invalid insertion position");
   dividends.insertColumns(getDivOffset() + pos, num);
   dividends.insertRows(pos, num);
-  denoms.insert(denoms.begin() + pos, num, MPInt(0));
+  denoms.insert(denoms.begin() + pos, num, DynamicAPInt(0));
 }
 
 void DivisionRepr::print(raw_ostream &os) const {
   os << "Dividends:\n";
   dividends.print(os);
   os << "Denominators\n";
-  for (const MPInt &denom : denoms)
+  for (const DynamicAPInt &denom : denoms)
     os << denom << " ";
   os << "\n";
 }
 
 void DivisionRepr::dump() const { print(llvm::errs()); }
 
-SmallVector<MPInt, 8> presburger::getMPIntVec(ArrayRef<int64_t> range) {
-  SmallVector<MPInt, 8> result(range.size());
-  std::transform(range.begin(), range.end(), result.begin(), mpintFromInt64);
+SmallVector<DynamicAPInt, 8>
+presburger::getDynamicAPIntVec(ArrayRef<int64_t> range) {
+  SmallVector<DynamicAPInt, 8> result(range.size());
+  std::transform(range.begin(), range.end(), result.begin(),
+                 dynamicAPIntFromInt64);
   return result;
 }
 
-SmallVector<int64_t, 8> presburger::getInt64Vec(ArrayRef<MPInt> range) {
+SmallVector<int64_t, 8> presburger::getInt64Vec(ArrayRef<DynamicAPInt> range) {
   SmallVector<int64_t, 8> result(range.size());
-  std::transform(range.begin(), range.end(), result.begin(), int64FromMPInt);
+  std::transform(range.begin(), range.end(), result.begin(),
+                 int64fromDynamicAPInt);
   return result;
 }
 
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/FractionTest.cpp b/mlir/unittests/Analysis/Presburger/FractionTest.cpp
index 5fee9de1994c8..c9fad953dacd5 100644
--- a/mlir/unittests/Analysis/Presburger/FractionTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/FractionTest.cpp
@@ -8,7 +8,7 @@ using namespace presburger;
 
 TEST(FractionTest, getAsInteger) {
   Fraction f(3, 1);
-  EXPECT_EQ(f.getAsInteger(), MPInt(3));
+  EXPECT_EQ(f.getAsInteger(), DynamicAPInt(3));
 }
 
 TEST(FractionTest, nearIntegers) {
diff --git a/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp b/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
index ba035e84ff1fd..f64bb240b4ee4 100644
--- a/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/IntegerPolyhedronTest.cpp
@@ -41,8 +41,8 @@ makeSetFromConstraints(unsigned ids, ArrayRef<SmallVector<int64_t, 4>> ineqs,
   return set;
 }
 
-static void dump(ArrayRef<MPInt> vec) {
-  for (const MPInt &x : vec)
+static void dump(ArrayRef<DynamicAPInt> vec) {
+  for (const DynamicAPInt &x : vec)
     llvm::errs() << x << ' ';
   llvm::errs() << '\n';
 }
@@ -60,8 +60,8 @@ static void dump(ArrayRef<MPInt> vec) {
 /// opposite of hasSample.
 static void checkSample(bool hasSample, const IntegerPolyhedron &poly,
                         TestFunction fn = TestFunction::Sample) {
-  std::optional<SmallVector<MPInt, 8>> maybeSample;
-  MaybeOptimum<SmallVector<MPInt, 8>> maybeLexMin;
+  std::optional<SmallVector<DynamicAPInt, 8>> maybeSample;
+  MaybeOptimum<SmallVector<DynamicAPInt, 8>> maybeLexMin;
   switch (fn) {
   case TestFunction::Sample:
     maybeSample = poly.findIntegerSample();
@@ -585,10 +585,12 @@ TEST(IntegerPolyhedronTest, removeRedundantConstraintsTest) {
   // y >= 128x >= 0.
   poly5.removeRedundantConstraints();
   EXPECT_EQ(poly5.getNumInequalities(), 3u);
-  SmallVector<MPInt, 8> redundantConstraint = getMPIntVec({0, 1, 0});
+  SmallVector<DynamicAPInt, 8> redundantConstraint =
+      getDynamicAPIntVec({0, 1, 0});
   for (unsigned i = 0; i < 3; ++i) {
     // Ensure that the removed constraint was the redundant constraint [3].
-    EXPECT_NE(poly5.getInequality(i), ArrayRef<MPInt>(redundantConstraint));
+    EXPECT_NE(poly5.getInequality(i),
+              ArrayRef<DynamicAPInt>(redundantConstraint));
   }
 }
 
@@ -631,7 +633,7 @@ static void checkDivisionRepresentation(
   DivisionRepr divs = poly.getLocalReprs();
 
   // Check that the `denominators` and `expectedDenominators` match.
-  EXPECT_EQ(ArrayRef<MPInt>(getMPIntVec(expectedDenominators)),
+  EXPECT_EQ(ArrayRef<DynamicAPInt>(getDynamicAPIntVec(expectedDenominators)),
             divs.getDenoms());
 
   // Check that the `dividends` and `expectedDividends` match. If the
@@ -1166,9 +1168,9 @@ TEST(IntegerPolyhedronTest, findRationalLexMin) {
 }
 
 void expectIntegerLexMin(const IntegerPolyhedron &poly, ArrayRef<int64_t> min) {
-  MaybeOptimum<SmallVector<MPInt, 8>> lexMin = poly.findIntegerLexMin();
+  MaybeOptimum<SmallVector<DynamicAPInt, 8>> lexMin = poly.findIntegerLexMin();
   ASSERT_TRUE(lexMin.isBounded());
-  EXPECT_EQ(*lexMin, getMPIntVec(min));
+  EXPECT_EQ(*lexMin, getDynamicAPIntVec(min));
 }
 
 void expectNoIntegerLexMin(OptimumKind kind, const IntegerPolyhedron &poly) {
@@ -1463,7 +1465,7 @@ TEST(IntegerPolyhedronTest, computeVolume) {
 
 bool containsPointNoLocal(const IntegerPolyhedron &poly,
                           ArrayRef<int64_t> point) {
-  return poly.containsPointNoLocal(getMPIntVec(point)).has_value();
+  return poly.containsPointNoLocal(getDynamicAPIntVec(point)).has_value();
 }
 
 TEST(IntegerPolyhedronTest, containsPointNoLocal) {
diff --git a/mlir/unittests/Analysis/Presburger/LinearTransformTest.cpp b/mlir/unittests/Analysis/Presburger/LinearTransformTest.cpp
index 721d1fd6e2535..388ac1174dcdc 100644
--- a/mlir/unittests/Analysis/Presburger/LinearTransformTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/LinearTransformTest.cpp
@@ -23,7 +23,8 @@ void testColumnEchelonForm(const IntMatrix &m, unsigned expectedRank) {
   // In column echelon form, each row's last non-zero value can be at most one
   // column to the right of the last non-zero column among the previous rows.
   for (unsigned row = 0, nRows = m.getNumRows(); row < nRows; ++row) {
-    SmallVector<MPInt, 8> rowVec = transform.preMultiplyWithRow(m.getRow(row));
+    SmallVector<DynamicAPInt, 8> rowVec =
+        transform.preMultiplyWithRow(m.getRow(row));
     for (unsigned col = lastAllowedNonZeroCol + 1, nCols = m.getNumColumns();
          col < nCols; ++col) {
       EXPECT_EQ(rowVec[col], 0);
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/MatrixTest.cpp b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
index fa1f32970b146..cb8df8b346011 100644
--- a/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
@@ -317,7 +317,7 @@ TEST(MatrixTest, intInverse) {
 
   mat = makeIntMatrix(2, 2, {{0, 0}, {1, 2}});
 
-  MPInt det = mat.determinant(&inv);
+  DynamicAPInt det = mat.determinant(&inv);
 
   EXPECT_EQ(det, 0);
 }
diff --git a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
index 2f4fa27138914..63d0243808555 100644
--- a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
@@ -21,26 +21,26 @@ using namespace presburger;
 
 /// Convenience functions to pass literals to Simplex.
 void addInequality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
-  simplex.addInequality(getMPIntVec(coeffs));
+  simplex.addInequality(getDynamicAPIntVec(coeffs));
 }
 void addEquality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
-  simplex.addEquality(getMPIntVec(coeffs));
+  simplex.addEquality(getDynamicAPIntVec(coeffs));
 }
 bool isRedundantInequality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
-  return simplex.isRedundantInequality(getMPIntVec(coeffs));
+  return simplex.isRedundantInequality(getDynamicAPIntVec(coeffs));
 }
 bool isRedundantInequality(LexSimplex &simplex, ArrayRef<int64_t> coeffs) {
-  return simplex.isRedundantInequality(getMPIntVec(coeffs));
+  return simplex.isRedundantInequality(getDynamicAPIntVec(coeffs));
 }
 bool isRedundantEquality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
-  return simplex.isRedundantEquality(getMPIntVec(coeffs));
+  return simplex.isRedundantEquality(getDynamicAPIntVec(coeffs));
 }
 bool isSeparateInequality(LexSimplex &simplex, ArrayRef<int64_t> coeffs) {
-  return simplex.isSeparateInequality(getMPIntVec(coeffs));
+  return simplex.isSeparateInequality(getDynamicAPIntVec(coeffs));
 }
 
 Simplex::IneqType findIneqType(Simplex &simplex, ArrayRef<int64_t> coeffs) {
-  return simplex.findIneqType(getMPIntVec(coeffs));
+  return simplex.findIneqType(getDynamicAPIntVec(coeffs));
 }
 
 /// Take a snapshot, add constraints making the set empty, and rollback.
@@ -433,8 +433,8 @@ TEST(SimplexTest, pivotRedundantRegressionTest) {
   // After the rollback, the only remaining constraint is x <= -1.
   // The maximum value of x should be -1.
   simplex.rollback(snapshot);
-  MaybeOptimum<Fraction> maxX =
-      simplex.computeOptimum(Simplex::Direction::Up, getMPIntVec({1, 0, 0}));
+  MaybeOptimum<Fraction> maxX = simplex.computeOptimum(
+      Simplex::Direction::Up, getDynamicAPIntVec({1, 0, 0}));
   EXPECT_TRUE(maxX.isBounded() && *maxX == Fraction(-1, 1));
 }
 
@@ -467,9 +467,9 @@ TEST(SimplexTest, appendVariable) {
 
   EXPECT_EQ(simplex.getNumVariables(), 2u);
   EXPECT_EQ(simplex.getNumConstraints(), 2u);
-  EXPECT_EQ(simplex.computeIntegerBounds(getMPIntVec({0, 1, 0})),
-            std::make_pair(MaybeOptimum<MPInt>(MPInt(yMin)),
-                           MaybeOptimum<MPInt>(MPInt(yMax))));
+  EXPECT_EQ(simplex.computeIntegerBounds(getDynamicAPIntVec({0, 1, 0})),
+            std::make_pair(MaybeOptimum<DynamicAPInt>(DynamicAPInt(yMin)),
+                           MaybeOptimum<DynamicAPInt>(DynamicAPInt(yMax))));
 
   simplex.rollback(snapshot1);
   EXPECT_EQ(simplex.getNumVariables(), 1u);
@@ -569,10 +569,11 @@ TEST(SimplexTest, IsRationalSubsetOf) {
 
 TEST(SimplexTest, addDivisionVariable) {
   Simplex simplex(/*nVar=*/1);
-  simplex.addDivisionVariable(getMPIntVec({1, 0}), MPInt(2));
+  simplex.addDivisionVariable(getDynamicAPIntVec({1, 0}), DynamicAPInt(2));
   addInequality(simplex, {1, 0, -3}); // x >= 3.
   addInequality(simplex, {-1, 0, 9}); // x <= 9.
-  std::optional<SmallVector<MPInt, 8>> sample = simplex.findIntegerSample();
+  std::optional<SmallVector<DynamicAPInt, 8>> sample =
+      simplex.findIntegerSample();
   ASSERT_TRUE(sample.has_value());
   EXPECT_EQ((*sample)[0] / 2, (*sample)[1]);
 }
diff --git a/mlir/unittests/Analysis/Presburger/Utils.h b/mlir/unittests/Analysis/Presburger/Utils.h
index 6b00898a7e274..ef4429b5c6bc8 100644
--- a/mlir/unittests/Analysis/Presburger/Utils.h
+++ b/mlir/unittests/Analysis/Presburger/Utils.h
@@ -28,6 +28,7 @@
 
 namespace mlir {
 namespace presburger {
+using llvm::dynamicAPIntFromInt64;
 
 inline IntMatrix makeIntMatrix(unsigned numRow, unsigned numColumns,
                                ArrayRef<SmallVector<int, 8>> matrix) {
@@ -37,7 +38,7 @@ inline IntMatrix makeIntMatrix(unsigned numRow, unsigned numColumns,
     assert(matrix[i].size() == numColumns &&
            "Output expression has incorrect dimensionality!");
     for (unsigned j = 0; j < numColumns; ++j)
-      results(i, j) = MPInt(matrix[i][j]);
+      results(i, j) = DynamicAPInt(matrix[i][j]);
   }
   return results;
 }
@@ -130,8 +131,8 @@ inline void EXPECT_EQ_REPR_QUASIPOLYNOMIAL(QuasiPolynomial a,
 
 /// lhs and rhs represent non-negative integers or positive infinity. The
 /// infinity case corresponds to when the Optional is empty.
-inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
-                               std::optional<MPInt> rhs) {
+inline bool infinityOrUInt64LE(std::optional<DynamicAPInt> lhs,
+                               std::optional<DynamicAPInt> rhs) {
   // No constraint.
   if (!rhs)
     return true;
@@ -145,9 +146,9 @@ inline bool infinityOrUInt64LE(std::optional<MPInt> lhs,
 /// the true volume `trueVolume`, while also being at least as good an
 /// approximation as `resultBound`.
 inline void expectComputedVolumeIsValidOverapprox(
-    const std::optional<MPInt> &computedVolume,
-    const std::optional<MPInt> &trueVolume,
-    const std::optional<MPInt> &resultBound) {
+    const std::optional<DynamicAPInt> &computedVolume,
+    const std::optional<DynamicAPInt> &trueVolume,
+    const std::optional<DynamicAPInt> &resultBound) {
   assert(infinityOrUInt64LE(trueVolume, resultBound) &&
          "can't expect result to be less than the true volume");
   EXPECT_TRUE(infinityOrUInt64LE(trueVolume, computedVolume));
@@ -155,11 +156,12 @@ inline void expectComputedVolumeIsValidOverapprox(
 }
 
 inline void expectComputedVolumeIsValidOverapprox(
-    const std::optional<MPInt> &computedVolume,
+    const std::optional<DynamicAPInt> &computedVolume,
     std::optional<int64_t> trueVolume, std::optional<int64_t> resultBound) {
   expectComputedVolumeIsValidOverapprox(
-      computedVolume, llvm::transformOptional(trueVolume, mpintFromInt64),
-      llvm::transformOptional(resultBound, mpintFromInt64));
+      computedVolume,
+      llvm::transformOptional(trueVolume, dynamicAPIntFromInt64),
+      llvm::transformOptional(resultBound, dynamicAPIntFromInt64));
 }
 
 } // namespace presburger
diff --git a/mlir/unittests/Analysis/Presburger/UtilsTest.cpp b/mlir/unittests/Analysis/Presburger/UtilsTest.cpp
index f09a1a760ce60..d91a0f2da9cee 100644
--- a/mlir/unittests/Analysis/Presburger/UtilsTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/UtilsTest.cpp
@@ -14,9 +14,10 @@
 using namespace mlir;
 using namespace presburger;
 
-static DivisionRepr parseDivisionRepr(unsigned numVars, unsigned numDivs,
-                                      ArrayRef<ArrayRef<MPInt>> dividends,
-                                      ArrayRef<MPInt> divisors) {
+static DivisionRepr
+parseDivisionRepr(unsigned numVars, unsigned numDivs,
+                  ArrayRef<ArrayRef<DynamicAPInt>> dividends,
+                  ArrayRef<DynamicAPInt> divisors) {
   DivisionRepr repr(numVars, numDivs);
   for (unsigned i = 0, rows = dividends.size(); i < rows; ++i)
     repr.setDiv(i, dividends[i], divisors[i]);
@@ -37,12 +38,15 @@ static void checkEqual(DivisionRepr &a, DivisionRepr &b) {
 
 TEST(UtilsTest, ParseAndCompareDivisionReprTest) {
   auto merge = [](unsigned i, unsigned j) -> bool { return true; };
-  DivisionRepr a = parseDivisionRepr(1, 1, {{MPInt(1), MPInt(2)}}, {MPInt(2)}),
-               b = parseDivisionRepr(1, 1, {{MPInt(1), MPInt(2)}}, {MPInt(2)}),
-               c = parseDivisionRepr(2, 2,
-                                     {{MPInt(0), MPInt(1), MPInt(2)},
-                                      {MPInt(0), MPInt(1), MPInt(2)}},
-                                     {MPInt(2), MPInt(2)});
+  DivisionRepr a = parseDivisionRepr(1, 1, {{DynamicAPInt(1), DynamicAPInt(2)}},
+                                     {DynamicAPInt(2)}),
+               b = parseDivisionRepr(1, 1, {{DynamicAPInt(1), DynamicAPInt(2)}},
+                                     {DynamicAPInt(2)}),
+               c = parseDivisionRepr(
+                   2, 2,
+                   {{DynamicAPInt(0), DynamicAPInt(1), DynamicAPInt(2)},
+                    {DynamicAPInt(0), DynamicAPInt(1), DynamicAPInt(2)}},
+                   {DynamicAPInt(2), DynamicAPInt(2)});
   c.removeDuplicateDivs(merge);
   checkEqual(a, b);
   checkEqual(a, c);
@@ -50,16 +54,21 @@ TEST(UtilsTest, ParseAndCompareDivisionReprTest) {
 
 TEST(UtilsTest, DivisionReprNormalizeTest) {
   auto merge = [](unsigned i, unsigned j) -> bool { return true; };
-  DivisionRepr a = parseDivisionRepr(2, 1, {{MPInt(1), MPInt(2), MPInt(-1)}},
-                                     {MPInt(2)}),
-               b = parseDivisionRepr(2, 1, {{MPInt(16), MPInt(32), MPInt(-16)}},
-                                     {MPInt(32)}),
-               c = parseDivisionRepr(1, 1, {{MPInt(12), MPInt(-4)}},
-                                     {MPInt(8)}),
-               d = parseDivisionRepr(2, 2,
-                                     {{MPInt(1), MPInt(2), MPInt(-1)},
-                                      {MPInt(4), MPInt(8), MPInt(-4)}},
-                                     {MPInt(2), MPInt(8)});
+  DivisionRepr a = parseDivisionRepr(
+                   2, 1, {{DynamicAPInt(1), DynamicAPInt(2), DynamicAPInt(-1)}},
+                   {DynamicAPInt(2)}),
+               b = parseDivisionRepr(
+                   2, 1,
+                   {{DynamicAPInt(16), DynamicAPInt(32), DynamicAPInt(-16)}},
+                   {DynamicAPInt(32)}),
+               c = parseDivisionRepr(1, 1,
+                                     {{DynamicAPInt(12), DynamicAPInt(-4)}},
+                                     {DynamicAPInt(8)}),
+               d = parseDivisionRepr(
+                   2, 2,
+                   {{DynamicAPInt(1), DynamicAPInt(2), DynamicAPInt(-1)},
+                    {DynamicAPInt(4), DynamicAPInt(8), DynamicAPInt(-4)}},
+                   {DynamicAPInt(2), DynamicAPInt(8)});
   b.removeDuplicateDivs(merge);
   c.removeDuplicateDivs(merge);
   d.removeDuplicateDivs(merge);

>From e91f51a2e5ea482a508f9c7b74aa4ff2d2652932 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 10 Jun 2024 15:43:06 +0100
Subject: [PATCH 2/4] git-clang-format

---
 mlir/include/mlir/Analysis/Presburger/Matrix.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Analysis/Presburger/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h
index 61c18dfb1efbe..e232ecd5e1509 100644
--- a/mlir/include/mlir/Analysis/Presburger/Matrix.h
+++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h
@@ -254,9 +254,9 @@ class IntMatrix : public Matrix<DynamicAPInt> {
 public:
   IntMatrix(unsigned rows, unsigned columns, unsigned reservedRows = 0,
             unsigned reservedColumns = 0)
-      : Matrix<DynamicAPInt>(rows, columns, reservedRows, reservedColumns){};
+      : Matrix<DynamicAPInt>(rows, columns, reservedRows, reservedColumns) {}
 
-  IntMatrix(Matrix<DynamicAPInt> m) : Matrix<DynamicAPInt>(std::move(m)){};
+  IntMatrix(Matrix<DynamicAPInt> m) : Matrix<DynamicAPInt>(std::move(m)) {}
 
   /// Return the identity matrix of the specified dimension.
   static IntMatrix identity(unsigned dimension);

>From 3ec4cd1ffcf307d72a4f8ba73cec28fc73d20c06 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 10 Jun 2024 19:21:16 +0100
Subject: [PATCH 3/4] DynamicAPInt: address review comments

---
 llvm/lib/Support/DynamicAPInt.cpp | 2 +-
 llvm/unittests/ADT/CMakeLists.txt | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Support/DynamicAPInt.cpp b/llvm/lib/Support/DynamicAPInt.cpp
index ed4d13d9786ce..6f7eecca36db0 100644
--- a/llvm/lib/Support/DynamicAPInt.cpp
+++ b/llvm/lib/Support/DynamicAPInt.cpp
@@ -1,4 +1,4 @@
-//===- DyanmicAPInt.cpp - DynamicAPInt Implementation -----------*- C++ -*-===//
+//===- DynamicAPInt.cpp - DynamicAPInt Implementation -----------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index c4dd53bcac087..f48d840a10595 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_unittest(ADTTests
   DenseSetTest.cpp
   DepthFirstIteratorTest.cpp
   DirectedGraphTest.cpp
+  DynamicAPIntTest.cpp
   EditDistanceTest.cpp
   EnumeratedArrayTest.cpp
   EquivalenceClassesTest.cpp
@@ -53,7 +54,6 @@ add_llvm_unittest(ADTTests
   LazyAtomicPointerTest.cpp
   MappedIteratorTest.cpp
   MapVectorTest.cpp
-  DynamicAPIntTest.cpp
   PackedVectorTest.cpp
   PagedVectorTest.cpp
   PointerEmbeddedIntTest.cpp

>From 8753e71129588efedcf7989ea4bdeef6e72dcccc Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Mon, 10 Jun 2024 19:27:37 +0100
Subject: [PATCH 4/4] DynamicAPInt: fix one more nit

---
 llvm/lib/Support/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 507eef2451063..c7f8ac325a97a 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -170,6 +170,7 @@ add_llvm_component_library(LLVMSupport
   DivisionByConstantInfo.cpp
   DAGDeltaAlgorithm.cpp
   DJB.cpp
+  DynamicAPInt.cpp
   ELFAttributeParser.cpp
   ELFAttributes.cpp
   Error.cpp
@@ -204,7 +205,6 @@ add_llvm_component_library(LLVMSupport
   MemoryBuffer.cpp
   MemoryBufferRef.cpp
   MD5.cpp
-  DynamicAPInt.cpp
   MSP430Attributes.cpp
   MSP430AttributeParser.cpp
   NativeFormatting.cpp



More information about the Mlir-commits mailing list