LLVM 20.0.0git
SlowDynamicAPInt.cpp
Go to the documentation of this file.
1//===- SlowDynamicAPInt.cpp - SlowDynamicAPInt Implementation -------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/Hashing.h"
11#include "llvm/Support/Debug.h"
13
14using namespace llvm;
15using namespace detail;
16
17SlowDynamicAPInt::SlowDynamicAPInt(int64_t Val)
18 : Val(64, Val, /*isSigned=*/true) {}
22 return *this = SlowDynamicAPInt(Val);
23}
24SlowDynamicAPInt::operator int64_t() const { return Val.getSExtValue(); }
25
27 return hash_value(X.Val);
28}
29
30/// ---------------------------------------------------------------------------
31/// Convenience operator overloads for int64_t.
32/// ---------------------------------------------------------------------------
34 return A += SlowDynamicAPInt(B);
35}
37 return A -= SlowDynamicAPInt(B);
38}
40 return A *= SlowDynamicAPInt(B);
41}
43 return A /= SlowDynamicAPInt(B);
44}
46 return A %= SlowDynamicAPInt(B);
47}
48
49bool detail::operator==(const SlowDynamicAPInt &A, int64_t B) {
50 return A == SlowDynamicAPInt(B);
51}
52bool detail::operator!=(const SlowDynamicAPInt &A, int64_t B) {
53 return A != SlowDynamicAPInt(B);
54}
55bool detail::operator>(const SlowDynamicAPInt &A, int64_t B) {
56 return A > SlowDynamicAPInt(B);
57}
58bool detail::operator<(const SlowDynamicAPInt &A, int64_t B) {
59 return A < SlowDynamicAPInt(B);
60}
61bool detail::operator<=(const SlowDynamicAPInt &A, int64_t B) {
62 return A <= SlowDynamicAPInt(B);
63}
64bool detail::operator>=(const SlowDynamicAPInt &A, int64_t B) {
65 return A >= SlowDynamicAPInt(B);
66}
68 return A + SlowDynamicAPInt(B);
69}
71 return A - SlowDynamicAPInt(B);
72}
74 return A * SlowDynamicAPInt(B);
75}
77 return A / SlowDynamicAPInt(B);
78}
80 return A % SlowDynamicAPInt(B);
81}
82
83bool detail::operator==(int64_t A, const SlowDynamicAPInt &B) {
84 return SlowDynamicAPInt(A) == B;
85}
86bool detail::operator!=(int64_t A, const SlowDynamicAPInt &B) {
87 return SlowDynamicAPInt(A) != B;
88}
89bool detail::operator>(int64_t A, const SlowDynamicAPInt &B) {
90 return SlowDynamicAPInt(A) > B;
91}
92bool detail::operator<(int64_t A, const SlowDynamicAPInt &B) {
93 return SlowDynamicAPInt(A) < B;
94}
95bool detail::operator<=(int64_t A, const SlowDynamicAPInt &B) {
96 return SlowDynamicAPInt(A) <= B;
97}
98bool detail::operator>=(int64_t A, const SlowDynamicAPInt &B) {
99 return SlowDynamicAPInt(A) >= B;
100}
102 return SlowDynamicAPInt(A) + B;
103}
105 return SlowDynamicAPInt(A) - B;
106}
108 return SlowDynamicAPInt(A) * B;
109}
111 return SlowDynamicAPInt(A) / B;
112}
114 return SlowDynamicAPInt(A) % B;
115}
116
117static unsigned getMaxWidth(const APInt &A, const APInt &B) {
118 return std::max(A.getBitWidth(), B.getBitWidth());
119}
120
121/// ---------------------------------------------------------------------------
122/// Comparison operators.
123/// ---------------------------------------------------------------------------
124
125// TODO: consider instead making APInt::compare available and using that.
127 unsigned Width = getMaxWidth(Val, O.Val);
128 return Val.sext(Width) == O.Val.sext(Width);
129}
131 unsigned Width = getMaxWidth(Val, O.Val);
132 return Val.sext(Width) != O.Val.sext(Width);
133}
135 unsigned Width = getMaxWidth(Val, O.Val);
136 return Val.sext(Width).sgt(O.Val.sext(Width));
137}
139 unsigned Width = getMaxWidth(Val, O.Val);
140 return Val.sext(Width).slt(O.Val.sext(Width));
141}
143 unsigned Width = getMaxWidth(Val, O.Val);
144 return Val.sext(Width).sle(O.Val.sext(Width));
145}
147 unsigned Width = getMaxWidth(Val, O.Val);
148 return Val.sext(Width).sge(O.Val.sext(Width));
149}
150
151/// ---------------------------------------------------------------------------
152/// Arithmetic operators.
153/// ---------------------------------------------------------------------------
154
155/// Bring a and b to have the same width and then call op(a, b, overflow).
156/// If the overflow bit becomes set, resize a and b to double the width and
157/// call op(a, b, overflow), returning its result. The operation with double
158/// widths should not also overflow.
160 const APInt &A, const APInt &B,
161 function_ref<APInt(const APInt &, const APInt &, bool &Overflow)> Op) {
162 bool Overflow;
163 unsigned Width = getMaxWidth(A, B);
164 APInt Ret = Op(A.sext(Width), B.sext(Width), Overflow);
165 if (!Overflow)
166 return Ret;
167
168 Width *= 2;
169 Ret = Op(A.sext(Width), B.sext(Width), Overflow);
170 assert(!Overflow && "double width should be sufficient to avoid overflow!");
171 return Ret;
172}
173
175 return SlowDynamicAPInt(
176 runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sadd_ov)));
177}
179 return SlowDynamicAPInt(
180 runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::ssub_ov)));
181}
183 return SlowDynamicAPInt(
184 runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::smul_ov)));
185}
187 return SlowDynamicAPInt(
188 runOpWithExpandOnOverflow(Val, O.Val, std::mem_fn(&APInt::sdiv_ov)));
189}
191 return X >= 0 ? X : -X;
192}
194 const SlowDynamicAPInt &RHS) {
195 if (RHS == -1)
196 return -LHS;
197 unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
199 LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::UP));
200}
202 const SlowDynamicAPInt &RHS) {
203 if (RHS == -1)
204 return -LHS;
205 unsigned Width = getMaxWidth(LHS.Val, RHS.Val);
207 LHS.Val.sext(Width), RHS.Val.sext(Width), APInt::Rounding::DOWN));
208}
209// The RHS is always expected to be positive, and the result
210/// is always non-negative.
212 const SlowDynamicAPInt &RHS) {
213 assert(RHS >= 1 && "mod is only supported for positive divisors!");
214 return LHS % RHS < 0 ? LHS % RHS + RHS : LHS % RHS;
215}
216
218 const SlowDynamicAPInt &B) {
219 assert(A >= 0 && B >= 0 && "operands must be non-negative!");
220 unsigned Width = getMaxWidth(A.Val, B.Val);
221 return SlowDynamicAPInt(
222 APIntOps::GreatestCommonDivisor(A.Val.sext(Width), B.Val.sext(Width)));
223}
224
225/// Returns the least common multiple of A and B.
227 const SlowDynamicAPInt &B) {
230 return (X * Y) / gcd(X, Y);
231}
232
233/// This operation cannot overflow.
235 unsigned Width = std::max(Val.getBitWidth(), O.Val.getBitWidth());
236 return SlowDynamicAPInt(Val.sext(Width).srem(O.Val.sext(Width)));
237}
238
240 if (Val.isMinSignedValue()) {
241 /// Overflow only occurs when the value is the minimum possible value.
242 APInt Ret = Val.sext(2 * Val.getBitWidth());
243 return SlowDynamicAPInt(-Ret);
244 }
245 return SlowDynamicAPInt(-Val);
246}
247
248/// ---------------------------------------------------------------------------
249/// Assignment operators, preincrement, predecrement.
250/// ---------------------------------------------------------------------------
252 *this = *this + O;
253 return *this;
254}
256 *this = *this - O;
257 return *this;
258}
260 *this = *this * O;
261 return *this;
262}
264 *this = *this / O;
265 return *this;
266}
268 *this = *this % O;
269 return *this;
270}
272 *this += 1;
273 return *this;
274}
275
277 *this -= 1;
278 return *this;
279}
280
281/// ---------------------------------------------------------------------------
282/// Printing.
283/// ---------------------------------------------------------------------------
284void SlowDynamicAPInt::print(raw_ostream &OS) const { OS << Val; }
285
basic Basic Alias true
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
APInt runOpWithExpandOnOverflow(const APInt &A, const APInt &B, function_ref< APInt(const APInt &, const APInt &, bool &Overflow)> Op)
Bring a and b to have the same width and then call op(a, b, overflow).
static unsigned getMaxWidth(const APInt &A, const APInt &B)
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
bool isMinSignedValue() const
Determine if this is the smallest signed value.
Definition: APInt.h:401
bool sgt(const APInt &RHS) const
Signed greater than comparison.
Definition: APInt.h:1179
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1446
APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1898
bool sle(const APInt &RHS) const
Signed less or equal comparison.
Definition: APInt.h:1144
APInt sdiv_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1924
APInt srem(const APInt &RHS) const
Function for signed remainder operation.
Definition: APInt.cpp:1706
APInt smul_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1930
APInt sext(unsigned width) const
Sign extend to a new width.
Definition: APInt.cpp:954
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition: APInt.h:1108
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
Definition: APInt.h:1215
APInt ssub_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1911
This class represents an Operation in the Expression.
A simple class providing dynamic arbitrary-precision arithmetic.
void print(raw_ostream &OS) const
SlowDynamicAPInt operator%(const SlowDynamicAPInt &O) const
This operation cannot overflow.
SlowDynamicAPInt operator*(const SlowDynamicAPInt &O) const
SlowDynamicAPInt & operator+=(const SlowDynamicAPInt &O)
LLVM_DUMP_METHOD void dump() const
bool operator<=(const SlowDynamicAPInt &O) const
SlowDynamicAPInt & operator-=(const SlowDynamicAPInt &O)
SlowDynamicAPInt & operator*=(const SlowDynamicAPInt &O)
SlowDynamicAPInt & operator=(int64_t Val)
SlowDynamicAPInt operator-() 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)
SlowDynamicAPInt & operator%=(const SlowDynamicAPInt &O)
bool operator<(const SlowDynamicAPInt &O) const
bool operator>=(const SlowDynamicAPInt &O) const
SlowDynamicAPInt operator+(const SlowDynamicAPInt &O) const
An efficient, type-erasing, non-owning reference to a callable.
An opaque object representing a hash code.
Definition: Hashing.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM)
Return A sign-divided by B, rounded by the given rounding mode.
Definition: APInt.cpp:2750
APInt GreatestCommonDivisor(APInt A, APInt B)
Compute GCD of two unsigned APInt values.
Definition: APInt.cpp:767
SlowDynamicAPInt abs(const SlowDynamicAPInt &X)
Redeclarations of friend declarations above to make it discoverable by lookups.
bool operator>=(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt ceilDiv(const SlowDynamicAPInt &LHS, const SlowDynamicAPInt &RHS)
SlowDynamicAPInt operator/(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt operator+(const SlowDynamicAPInt &A, int64_t B)
hash_code hash_value(const IEEEFloat &Arg)
Definition: APFloat.cpp:3430
SlowDynamicAPInt operator-(const SlowDynamicAPInt &A, int64_t B)
bool operator!=(const DenseSetImpl< ValueT, MapTy, ValueInfoT > &LHS, const DenseSetImpl< ValueT, MapTy, ValueInfoT > &RHS)
Inequality comparison for DenseSet.
Definition: DenseSet.h:259
SlowDynamicAPInt gcd(const SlowDynamicAPInt &A, const SlowDynamicAPInt &B)
SlowDynamicAPInt floorDiv(const SlowDynamicAPInt &LHS, const SlowDynamicAPInt &RHS)
bool operator>(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt & operator+=(SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt operator%(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt operator*(const SlowDynamicAPInt &A, int64_t B)
bool operator<=(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt & operator/=(SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt lcm(const SlowDynamicAPInt &A, const SlowDynamicAPInt &B)
Returns the least common multiple of A and B.
bool operator==(const DenseSetImpl< ValueT, MapTy, ValueInfoT > &LHS, const DenseSetImpl< ValueT, MapTy, ValueInfoT > &RHS)
Equality comparison for DenseSet.
Definition: DenseSet.h:243
SlowDynamicAPInt mod(const SlowDynamicAPInt &LHS, const SlowDynamicAPInt &RHS)
Returns the remainder of dividing LHS by RHS.
SlowDynamicAPInt & operator*=(SlowDynamicAPInt &A, int64_t B)
bool operator<(const SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt & operator-=(SlowDynamicAPInt &A, int64_t B)
SlowDynamicAPInt & operator%=(SlowDynamicAPInt &A, int64_t B)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
DWARFExpression::Operation Op