aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-07-27 23:34:35 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-12-01 12:32:12 +0000
commitfbc266465ed3585efdbd8e9ebf71e97ce7e8b464 (patch)
tree7560c2cbec09e542e5f2e2100ffc16ca742b1075 /contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp
parentac8517f04c0fe31968ed43e36608ad02d72d3597 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp b/contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp
new file mode 100644
index 000000000000..7964a3d59daf
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Support/SlowDynamicAPInt.cpp
@@ -0,0 +1,286 @@
+//===- SlowDynamicAPInt.cpp - SlowDynamicAPInt 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.
+/// ---------------------------------------------------------------------------
+void SlowDynamicAPInt::print(raw_ostream &OS) const { OS << Val; }
+
+void SlowDynamicAPInt::dump() const { print(dbgs()); }