1 //===- SlowDynamicAPInt.cpp - SlowDynamicAPInt Implementation -------------===//
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 #include "llvm/ADT/SlowDynamicAPInt.h"
10 #include "llvm/ADT/Hashing.h"
11 #include "llvm/Support/Debug.h"
12 #include "llvm/Support/raw_ostream.h"
15 using namespace detail
;
17 SlowDynamicAPInt::SlowDynamicAPInt(int64_t Val
)
18 : Val(64, Val
, /*isSigned=*/true) {}
19 SlowDynamicAPInt::SlowDynamicAPInt() : SlowDynamicAPInt(0) {}
20 SlowDynamicAPInt::SlowDynamicAPInt(const APInt
&Val
) : Val(Val
) {}
21 SlowDynamicAPInt
&SlowDynamicAPInt::operator=(int64_t Val
) {
22 return *this = SlowDynamicAPInt(Val
);
24 SlowDynamicAPInt::operator int64_t() const { return Val
.getSExtValue(); }
26 hash_code
detail::hash_value(const SlowDynamicAPInt
&X
) {
27 return hash_value(X
.Val
);
30 /// ---------------------------------------------------------------------------
31 /// Convenience operator overloads for int64_t.
32 /// ---------------------------------------------------------------------------
33 SlowDynamicAPInt
&detail::operator+=(SlowDynamicAPInt
&A
, int64_t B
) {
34 return A
+= SlowDynamicAPInt(B
);
36 SlowDynamicAPInt
&detail::operator-=(SlowDynamicAPInt
&A
, int64_t B
) {
37 return A
-= SlowDynamicAPInt(B
);
39 SlowDynamicAPInt
&detail::operator*=(SlowDynamicAPInt
&A
, int64_t B
) {
40 return A
*= SlowDynamicAPInt(B
);
42 SlowDynamicAPInt
&detail::operator/=(SlowDynamicAPInt
&A
, int64_t B
) {
43 return A
/= SlowDynamicAPInt(B
);
45 SlowDynamicAPInt
&detail::operator%=(SlowDynamicAPInt
&A
, int64_t B
) {
46 return A
%= SlowDynamicAPInt(B
);
49 bool detail::operator==(const SlowDynamicAPInt
&A
, int64_t B
) {
50 return A
== SlowDynamicAPInt(B
);
52 bool detail::operator!=(const SlowDynamicAPInt
&A
, int64_t B
) {
53 return A
!= SlowDynamicAPInt(B
);
55 bool detail::operator>(const SlowDynamicAPInt
&A
, int64_t B
) {
56 return A
> SlowDynamicAPInt(B
);
58 bool detail::operator<(const SlowDynamicAPInt
&A
, int64_t B
) {
59 return A
< SlowDynamicAPInt(B
);
61 bool detail::operator<=(const SlowDynamicAPInt
&A
, int64_t B
) {
62 return A
<= SlowDynamicAPInt(B
);
64 bool detail::operator>=(const SlowDynamicAPInt
&A
, int64_t B
) {
65 return A
>= SlowDynamicAPInt(B
);
67 SlowDynamicAPInt
detail::operator+(const SlowDynamicAPInt
&A
, int64_t B
) {
68 return A
+ SlowDynamicAPInt(B
);
70 SlowDynamicAPInt
detail::operator-(const SlowDynamicAPInt
&A
, int64_t B
) {
71 return A
- SlowDynamicAPInt(B
);
73 SlowDynamicAPInt
detail::operator*(const SlowDynamicAPInt
&A
, int64_t B
) {
74 return A
* SlowDynamicAPInt(B
);
76 SlowDynamicAPInt
detail::operator/(const SlowDynamicAPInt
&A
, int64_t B
) {
77 return A
/ SlowDynamicAPInt(B
);
79 SlowDynamicAPInt
detail::operator%(const SlowDynamicAPInt
&A
, int64_t B
) {
80 return A
% SlowDynamicAPInt(B
);
83 bool detail::operator==(int64_t A
, const SlowDynamicAPInt
&B
) {
84 return SlowDynamicAPInt(A
) == B
;
86 bool detail::operator!=(int64_t A
, const SlowDynamicAPInt
&B
) {
87 return SlowDynamicAPInt(A
) != B
;
89 bool detail::operator>(int64_t A
, const SlowDynamicAPInt
&B
) {
90 return SlowDynamicAPInt(A
) > B
;
92 bool detail::operator<(int64_t A
, const SlowDynamicAPInt
&B
) {
93 return SlowDynamicAPInt(A
) < B
;
95 bool detail::operator<=(int64_t A
, const SlowDynamicAPInt
&B
) {
96 return SlowDynamicAPInt(A
) <= B
;
98 bool detail::operator>=(int64_t A
, const SlowDynamicAPInt
&B
) {
99 return SlowDynamicAPInt(A
) >= B
;
101 SlowDynamicAPInt
detail::operator+(int64_t A
, const SlowDynamicAPInt
&B
) {
102 return SlowDynamicAPInt(A
) + B
;
104 SlowDynamicAPInt
detail::operator-(int64_t A
, const SlowDynamicAPInt
&B
) {
105 return SlowDynamicAPInt(A
) - B
;
107 SlowDynamicAPInt
detail::operator*(int64_t A
, const SlowDynamicAPInt
&B
) {
108 return SlowDynamicAPInt(A
) * B
;
110 SlowDynamicAPInt
detail::operator/(int64_t A
, const SlowDynamicAPInt
&B
) {
111 return SlowDynamicAPInt(A
) / B
;
113 SlowDynamicAPInt
detail::operator%(int64_t A
, const SlowDynamicAPInt
&B
) {
114 return SlowDynamicAPInt(A
) % B
;
117 static unsigned getMaxWidth(const APInt
&A
, const APInt
&B
) {
118 return std::max(A
.getBitWidth(), B
.getBitWidth());
121 /// ---------------------------------------------------------------------------
122 /// Comparison operators.
123 /// ---------------------------------------------------------------------------
125 // TODO: consider instead making APInt::compare available and using that.
126 bool SlowDynamicAPInt::operator==(const SlowDynamicAPInt
&O
) const {
127 unsigned Width
= getMaxWidth(Val
, O
.Val
);
128 return Val
.sext(Width
) == O
.Val
.sext(Width
);
130 bool SlowDynamicAPInt::operator!=(const SlowDynamicAPInt
&O
) const {
131 unsigned Width
= getMaxWidth(Val
, O
.Val
);
132 return Val
.sext(Width
) != O
.Val
.sext(Width
);
134 bool SlowDynamicAPInt::operator>(const SlowDynamicAPInt
&O
) const {
135 unsigned Width
= getMaxWidth(Val
, O
.Val
);
136 return Val
.sext(Width
).sgt(O
.Val
.sext(Width
));
138 bool SlowDynamicAPInt::operator<(const SlowDynamicAPInt
&O
) const {
139 unsigned Width
= getMaxWidth(Val
, O
.Val
);
140 return Val
.sext(Width
).slt(O
.Val
.sext(Width
));
142 bool SlowDynamicAPInt::operator<=(const SlowDynamicAPInt
&O
) const {
143 unsigned Width
= getMaxWidth(Val
, O
.Val
);
144 return Val
.sext(Width
).sle(O
.Val
.sext(Width
));
146 bool SlowDynamicAPInt::operator>=(const SlowDynamicAPInt
&O
) const {
147 unsigned Width
= getMaxWidth(Val
, O
.Val
);
148 return Val
.sext(Width
).sge(O
.Val
.sext(Width
));
151 /// ---------------------------------------------------------------------------
152 /// Arithmetic operators.
153 /// ---------------------------------------------------------------------------
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.
159 APInt
runOpWithExpandOnOverflow(
160 const APInt
&A
, const APInt
&B
,
161 function_ref
<APInt(const APInt
&, const APInt
&, bool &Overflow
)> Op
) {
163 unsigned Width
= getMaxWidth(A
, B
);
164 APInt Ret
= Op(A
.sext(Width
), B
.sext(Width
), Overflow
);
169 Ret
= Op(A
.sext(Width
), B
.sext(Width
), Overflow
);
170 assert(!Overflow
&& "double width should be sufficient to avoid overflow!");
174 SlowDynamicAPInt
SlowDynamicAPInt::operator+(const SlowDynamicAPInt
&O
) const {
175 return SlowDynamicAPInt(
176 runOpWithExpandOnOverflow(Val
, O
.Val
, std::mem_fn(&APInt::sadd_ov
)));
178 SlowDynamicAPInt
SlowDynamicAPInt::operator-(const SlowDynamicAPInt
&O
) const {
179 return SlowDynamicAPInt(
180 runOpWithExpandOnOverflow(Val
, O
.Val
, std::mem_fn(&APInt::ssub_ov
)));
182 SlowDynamicAPInt
SlowDynamicAPInt::operator*(const SlowDynamicAPInt
&O
) const {
183 return SlowDynamicAPInt(
184 runOpWithExpandOnOverflow(Val
, O
.Val
, std::mem_fn(&APInt::smul_ov
)));
186 SlowDynamicAPInt
SlowDynamicAPInt::operator/(const SlowDynamicAPInt
&O
) const {
187 return SlowDynamicAPInt(
188 runOpWithExpandOnOverflow(Val
, O
.Val
, std::mem_fn(&APInt::sdiv_ov
)));
190 SlowDynamicAPInt
detail::abs(const SlowDynamicAPInt
&X
) {
191 return X
>= 0 ? X
: -X
;
193 SlowDynamicAPInt
detail::ceilDiv(const SlowDynamicAPInt
&LHS
,
194 const SlowDynamicAPInt
&RHS
) {
197 unsigned Width
= getMaxWidth(LHS
.Val
, RHS
.Val
);
198 return SlowDynamicAPInt(APIntOps::RoundingSDiv(
199 LHS
.Val
.sext(Width
), RHS
.Val
.sext(Width
), APInt::Rounding::UP
));
201 SlowDynamicAPInt
detail::floorDiv(const SlowDynamicAPInt
&LHS
,
202 const SlowDynamicAPInt
&RHS
) {
205 unsigned Width
= getMaxWidth(LHS
.Val
, RHS
.Val
);
206 return SlowDynamicAPInt(APIntOps::RoundingSDiv(
207 LHS
.Val
.sext(Width
), RHS
.Val
.sext(Width
), APInt::Rounding::DOWN
));
209 // The RHS is always expected to be positive, and the result
210 /// is always non-negative.
211 SlowDynamicAPInt
detail::mod(const SlowDynamicAPInt
&LHS
,
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
;
217 SlowDynamicAPInt
detail::gcd(const SlowDynamicAPInt
&A
,
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
)));
225 /// Returns the least common multiple of A and B.
226 SlowDynamicAPInt
detail::lcm(const SlowDynamicAPInt
&A
,
227 const SlowDynamicAPInt
&B
) {
228 SlowDynamicAPInt X
= abs(A
);
229 SlowDynamicAPInt Y
= abs(B
);
230 return (X
* Y
) / gcd(X
, Y
);
233 /// This operation cannot overflow.
234 SlowDynamicAPInt
SlowDynamicAPInt::operator%(const SlowDynamicAPInt
&O
) const {
235 unsigned Width
= std::max(Val
.getBitWidth(), O
.Val
.getBitWidth());
236 return SlowDynamicAPInt(Val
.sext(Width
).srem(O
.Val
.sext(Width
)));
239 SlowDynamicAPInt
SlowDynamicAPInt::operator-() const {
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
);
245 return SlowDynamicAPInt(-Val
);
248 /// ---------------------------------------------------------------------------
249 /// Assignment operators, preincrement, predecrement.
250 /// ---------------------------------------------------------------------------
251 SlowDynamicAPInt
&SlowDynamicAPInt::operator+=(const SlowDynamicAPInt
&O
) {
255 SlowDynamicAPInt
&SlowDynamicAPInt::operator-=(const SlowDynamicAPInt
&O
) {
259 SlowDynamicAPInt
&SlowDynamicAPInt::operator*=(const SlowDynamicAPInt
&O
) {
263 SlowDynamicAPInt
&SlowDynamicAPInt::operator/=(const SlowDynamicAPInt
&O
) {
267 SlowDynamicAPInt
&SlowDynamicAPInt::operator%=(const SlowDynamicAPInt
&O
) {
271 SlowDynamicAPInt
&SlowDynamicAPInt::operator++() {
276 SlowDynamicAPInt
&SlowDynamicAPInt::operator--() {
281 /// ---------------------------------------------------------------------------
283 /// ---------------------------------------------------------------------------
284 void SlowDynamicAPInt::print(raw_ostream
&OS
) const { OS
<< Val
; }
286 void SlowDynamicAPInt::dump() const { print(dbgs()); }