1//===- DynamicAPInt.h - DynamicAPInt Class ----------------------*- C++ -*-===//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//===----------------------------------------------------------------------===//
9// This is a simple class to represent arbitrary precision signed integers.
10// Unlike APInt, one does not have to specify a fixed maximum size, and the
11// integer can take on any arbitrary values. This is optimized for small-values
12// by providing fast-paths for the cases when the value stored fits in 64-bits.
14//===----------------------------------------------------------------------===//
16#ifndef LLVM_ADT_DYNAMICAPINT_H
17#define LLVM_ADT_DYNAMICAPINT_H
29/// This class provides support for dynamic arbitrary-precision arithmetic.
31/// Unlike APInt, this extends the precision as necessary to prevent overflows
32/// and supports operations between objects with differing internal precisions.
34/// This is optimized for small-values by providing fast-paths for the cases
35/// when the value stored fits in 64-bits. We annotate all fastpaths by using
36/// the LLVM_LIKELY/LLVM_UNLIKELY annotations. Removing these would result in
37/// a 1.2x performance slowdown.
39/// We always_inline all operations; removing these results in a 1.5x
40/// performance slowdown.
42/// When isLarge returns true, a SlowMPInt is held in the union. If isSmall
43/// returns true, the int64_t is held. We don't have a separate field for
44/// indicating this, and instead "steal" memory from ValLarge when it is not in
45/// use because we know that the memory layout of APInt is such that BitWidth
46/// doesn't overlap with ValSmall (see static_assert_layout). Using std::variant
47/// instead would lead to significantly worse performance.
56 ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
61 initLarge(
const detail::SlowDynamicAPInt &O) {
63 // The data in memory could be in an arbitrary state, not necessarily
64 // corresponding to any valid state of ValLarge; we cannot call any member
65 // functions, e.g. the assignment operator on it, as they may access the
66 // invalid internal state. We instead construct a new object using
68 new (&
ValLarge) detail::SlowDynamicAPInt(O);
70 // In this case, we need to use the assignment operator, because if we use
71 // placement-new as above we would lose track of allocated memory
78 const detail::SlowDynamicAPInt &Val)
86 /// Get the stored value. For getSmall/Large,
87 /// the stored value should be small/large.
90 "getSmall should only be called when the value stored is small!");
95 "getSmall should only be called when the value stored is small!");
101 "getLarge should only be called when the value stored is large!");
106 "getLarge should only be called when the value stored is large!");
109 explicit operator detail::SlowDynamicAPInt()
const {
111 return detail::SlowDynamicAPInt(getSmall());
131 ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
137 initLarge(O.ValLarge);
141 initSmall(O.ValSmall);
144 initLarge(O.ValLarge);
154 return static_cast<int64_t
>(getLarge());
177 // Divide by a number that is known to be positive.
178 // This is slightly more efficient because it saves an overflow check.
186 // The operands must be non-negative for gcd.
191 /// ---------------------------------------------------------------------------
192 /// Convenience operator overloads for int64_t.
193 /// ---------------------------------------------------------------------------
230#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
240/// Redeclarations of friend declaration above to
241/// make it discoverable by lookups.
244/// This just calls through to the operator int64_t, but it's useful when a
245/// function pointer is required. (Although this is marked inline, it is still
246/// possible to obtain and use a function pointer to this.)
254// The RHS is always expected to be positive, and the result
255/// is always non-negative.
257 const DynamicAPInt &
RHS);
259/// We define the operations here in the header to facilitate inlining.
261/// ---------------------------------------------------------------------------
262/// Comparison operators.
263/// ---------------------------------------------------------------------------
267 return getSmall() == O.getSmall();
273 return getSmall() != O.getSmall();
279 return getSmall() > O.getSmall();
285 return getSmall() < O.getSmall();
291 return getSmall() <= O.getSmall();
297 return getSmall() >= O.getSmall();
301/// ---------------------------------------------------------------------------
302/// Arithmetic operators.
303/// ---------------------------------------------------------------------------
309 bool Overflow =
AddOverflow(getSmall(), O.getSmall(), Result.getSmall());
322 bool Overflow =
SubOverflow(getSmall(), O.getSmall(), Result.getSmall());
335 bool Overflow =
MulOverflow(getSmall(), O.getSmall(), Result.getSmall());
345// Division overflows only occur when negating the minimal possible value.
358 // Division overflows only occur when negating the minimal possible value.
368 return DynamicAPInt(
X >= 0 ?
X : -
X);
370// Division overflows only occur when negating the minimal possible value.
372 const DynamicAPInt &
RHS) {
383 const DynamicAPInt &
RHS) {
393// The RHS is always expected to be positive, and the result
394/// is always non-negative.
396 const DynamicAPInt &
RHS) {
398 return DynamicAPInt(
mod(
LHS.getSmall(),
RHS.getSmall()));
404 const DynamicAPInt &
B) {
405 assert(
A >= 0 &&
B >= 0 &&
"operands must be non-negative!");
407 return DynamicAPInt(std::gcd(
A.getSmall(),
B.getSmall()));
412/// Returns the least common multiple of A and B.
414 const DynamicAPInt &
B) {
415 DynamicAPInt
X =
abs(
A);
416 DynamicAPInt
Y =
abs(
B);
420/// This operation cannot overflow.
431 if (
LLVM_LIKELY(getSmall() != std::numeric_limits<int64_t>::min()))
438/// ---------------------------------------------------------------------------
439/// Assignment operators, preincrement, predecrement.
440/// ---------------------------------------------------------------------------
444 int64_t Result = getSmall();
445 bool Overflow =
AddOverflow(getSmall(), O.getSmall(), Result);
450 // Note: this return is not strictly required but
451 // removing it leads to a performance regression.
461 int64_t Result = getSmall();
462 bool Overflow =
SubOverflow(getSmall(), O.getSmall(), Result);
467 // Note: this return is not strictly required but
468 // removing it leads to a performance regression.
478 int64_t Result = getSmall();
479 bool Overflow =
MulOverflow(getSmall(), O.getSmall(), Result);
484 // Note: this return is not strictly required but
485 // removing it leads to a performance regression.
495 // Division overflows only occur when negating the minimal possible value.
497 return *
this = -*
this;
498 getSmall() /= O.getSmall();
505// Division overflows only occur when the divisor is -1.
510 getSmall() /= O.getSmall();
519 return *
this = *
this % O;
528/// ----------------------------------------------------------------------------
529/// Convenience operator overloads for int64_t.
530/// ----------------------------------------------------------------------------
553 return A + DynamicAPInt(
B);
557 return A - DynamicAPInt(
B);
561 return A * DynamicAPInt(
B);
565 return A / DynamicAPInt(
B);
569 return A % DynamicAPInt(
B);
572 const DynamicAPInt &
B) {
573 return DynamicAPInt(
A) +
B;
576 const DynamicAPInt &
B) {
577 return DynamicAPInt(
A) -
B;
580 const DynamicAPInt &
B) {
581 return DynamicAPInt(
A) *
B;
584 const DynamicAPInt &
B) {
585 return DynamicAPInt(
A) /
B;
588 const DynamicAPInt &
B) {
589 return DynamicAPInt(
A) %
B;
592/// We provide special implementations of the comparison operators rather than
593/// calling through as above, as this would result in a 1.2x slowdown.
596 return A.getSmall() ==
B;
597 return A.getLarge() ==
B;
601 return A.getSmall() !=
B;
602 return A.getLarge() !=
B;
606 return A.getSmall() >
B;
607 return A.getLarge() >
B;
611 return A.getSmall() <
B;
612 return A.getLarge() <
B;
616 return A.getSmall() <=
B;
617 return A.getLarge() <=
B;
621 return A.getSmall() >=
B;
622 return A.getLarge() >=
B;
626 return A ==
B.getSmall();
627 return A ==
B.getLarge();
631 return A !=
B.getSmall();
632 return A !=
B.getLarge();
636 return A >
B.getSmall();
637 return A >
B.getLarge();
641 return A <
B.getSmall();
642 return A <
B.getLarge();
646 return A <=
B.getSmall();
647 return A <=
B.getLarge();
651 return A >=
B.getSmall();
652 return A >=
B.getLarge();
656#endif // LLVM_ADT_DYNAMICAPINT_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE
LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do so, mark a method "always...
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
#define LLVM_LIKELY(EXPR)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Class for arbitrary precision integers.
unsigned getBitWidth() const
Return the number of bits in the APInt.
int64_t getSExtValue() const
Get sign extended value.
This class provides support for dynamic arbitrary-precision arithmetic.
LLVM_ABI raw_ostream & print(raw_ostream &OS) const
DynamicAPInt & operator%=(const DynamicAPInt &O)
friend DynamicAPInt ceilDiv(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
DynamicAPInt & operator--()
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator=(const DynamicAPInt &O)
friend DynamicAPInt abs(const DynamicAPInt &X)
DynamicAPInt & operator/=(const DynamicAPInt &O)
friend DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B)
friend DynamicAPInt lcm(const DynamicAPInt &A, const DynamicAPInt &B)
Returns the least common multiple of A and B.
DynamicAPInt operator/(const DynamicAPInt &O) const
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt()
DynamicAPInt operator%(const DynamicAPInt &O) const
This operation cannot overflow.
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator=(int X)
detail::SlowDynamicAPInt ValLarge
DynamicAPInt & operator*=(const DynamicAPInt &O)
bool operator==(const DynamicAPInt &O) const
We define the operations here in the header to facilitate inlining.
LLVM_ABI void static_assert_layout()
DynamicAPInt divByPositive(const DynamicAPInt &O) const
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt(const DynamicAPInt &O)
bool operator<=(const DynamicAPInt &O) const
LLVM_ABI friend hash_code hash_value(const DynamicAPInt &x)
Redeclarations of friend declaration above to make it discoverable by lookups.
DynamicAPInt operator-() const
bool operator<(const DynamicAPInt &O) const
bool operator>=(const DynamicAPInt &O) const
LLVM_DUMP_METHOD void dump() const
DynamicAPInt & operator+=(const DynamicAPInt &O)
DynamicAPInt operator+(const DynamicAPInt &O) const
DynamicAPInt & operator-=(const DynamicAPInt &O)
DynamicAPInt & operator++()
DynamicAPInt operator*(const DynamicAPInt &O) const
bool operator!=(const DynamicAPInt &O) const
friend DynamicAPInt mod(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
is always non-negative.
LLVM_ATTRIBUTE_ALWAYS_INLINE ~DynamicAPInt()
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt(const APInt &Val)
friend DynamicAPInt floorDiv(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt(int64_t Val)
DynamicAPInt & divByPositiveInPlace(const DynamicAPInt &O)
bool operator>(const DynamicAPInt &O) const
A simple class providing dynamic arbitrary-precision arithmetic.
An opaque object representing a hash code.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B)
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
constexpr bool divideSignedWouldOverflow(U Numerator, V Denominator)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt mod(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
is always non-negative.
hash_code hash_value(const FixedPointSemantics &Val)
APInt operator*(APInt a, uint64_t RHS)
APFloat abs(APFloat X)
Returns the absolute value of the argument.
constexpr T divideFloorSigned(U Numerator, V Denominator)
Returns the integer floor(Numerator / Denominator).
bool operator!=(uint64_t V1, const APInt &V2)
bool operator>=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator-=(DynamicAPInt &A, int64_t B)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt floorDiv(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator%(const DynamicAPInt &A, int64_t B)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator*=(DynamicAPInt &A, int64_t B)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator/=(DynamicAPInt &A, int64_t B)
bool operator>(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt ceilDiv(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
static int64_t int64fromDynamicAPInt(const DynamicAPInt &X)
This just calls through to the operator int64_t, but it's useful when a function pointer is required.
constexpr T divideCeilSigned(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt lcm(const DynamicAPInt &A, const DynamicAPInt &B)
Returns the least common multiple of A and B.
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt dynamicAPIntFromInt64(int64_t X)
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
APInt operator+(APInt a, const APInt &b)
std::enable_if_t< std::is_signed_v< T >, T > SubOverflow(T X, T Y, T &Result)
Subtract two signed integers, computing the two's complement truncated result, returning true if an o...
bool operator<=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator%=(DynamicAPInt &A, int64_t B)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt operator/(const DynamicAPInt &A, int64_t B)