Skip to content

Commit

Permalink
mlir/Presburger/MPInt: move into llvm/ADT (#94953)
Browse files Browse the repository at this point in the history
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 under the name DynamicAPInt.

This patch is part of a project to move the Presburger library into
LLVM.
  • Loading branch information
artagnon committed Jun 12, 2024
1 parent 0170498 commit 76030dc
Show file tree
Hide file tree
Showing 40 changed files with 1,869 additions and 1,774 deletions.
640 changes: 640 additions & 0 deletions llvm/include/llvm/ADT/DynamicAPInt.h

Large diffs are not rendered by default.

140 changes: 140 additions & 0 deletions llvm/include/llvm/ADT/SlowDynamicAPInt.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions llvm/lib/Support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ add_llvm_component_library(LLVMSupport
DivisionByConstantInfo.cpp
DAGDeltaAlgorithm.cpp
DJB.cpp
DynamicAPInt.cpp
ELFAttributeParser.cpp
ELFAttributes.cpp
Error.cpp
Expand Down Expand Up @@ -223,6 +224,7 @@ add_llvm_component_library(LLVMSupport
SHA1.cpp
SHA256.cpp
Signposts.cpp
SlowDynamicAPInt.cpp
SmallPtrSet.cpp
SmallVector.cpp
SourceMgr.cpp
Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/Support/DynamicAPInt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===- 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.
// 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
Loading

0 comments on commit 76030dc

Please sign in to comment.