[Mlir-commits] [llvm] [mlir] mlir/Presburger/MPInt: move into LLVM/ADT (PR #94953)
Thorsten Schütt
llvmlistbot at llvm.org
Mon Jun 10 06:21:09 PDT 2024
================
@@ -0,0 +1,644 @@
+//===- MPInt.h - MPInt 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 is optimized for small-values
+// by providing fast-paths for the cases when the value stored fits in 64-bits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_MPINT_H
+#define LLVM_ADT_MPINT_H
+
+#include "llvm/ADT/SlowMPInt.h"
+#include "llvm/Support/raw_ostream.h"
+#include <numeric>
+
+namespace llvm {
+namespace detail {
+/// ---------------------------------------------------------------------------
+/// Some helpers from MLIR/MathExtras.
+/// ---------------------------------------------------------------------------
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t ceilDiv(int64_t Numerator,
+ int64_t Denominator) {
+ assert(Denominator);
+ if (!Numerator)
+ return 0;
+ // C's integer division rounds towards 0.
+ int64_t X = (Denominator > 0) ? -1 : 1;
+ bool SameSign = (Numerator > 0) == (Denominator > 0);
+ return SameSign ? ((Numerator + X) / Denominator) + 1
+ : -(-Numerator / Denominator);
+}
+
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t floorDiv(int64_t Numerator,
+ int64_t Denominator) {
+ assert(Denominator);
+ if (!Numerator)
+ return 0;
+ // C's integer division rounds towards 0.
+ int64_t X = (Denominator > 0) ? -1 : 1;
+ bool SameSign = (Numerator > 0) == (Denominator > 0);
+ return SameSign ? Numerator / Denominator
+ : -((-Numerator + X) / Denominator) - 1;
+}
+
+/// Returns the remainder of the Euclidean division of LHS by RHS. Result is
+/// always non-negative.
+LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t mod(int64_t Numerator,
+ int64_t Denominator) {
+ assert(Denominator >= 1);
+ return Numerator % Denominator < 0 ? Numerator % Denominator + Denominator
+ : Numerator % Denominator;
+}
+
+/// If builtin intrinsics for overflow-checked arithmetic are available,
+/// use them. Otherwise, call through to LLVM's overflow-checked arithmetic
+/// functionality. Those functions also have such macro-gated uses of intrinsics
+/// but they are not always_inlined, which is important for us to achieve
+/// high-performance; calling the functions directly would result in a slowdown
+/// of 1.15x.
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool addOverflow(int64_t X, int64_t Y,
+ int64_t &Result) {
+#if __has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow(X, Y, &Result);
+#else
+ return AddOverflow(X, Y, Result);
+#endif
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool subOverflow(int64_t X, int64_t Y,
+ int64_t &Result) {
+#if __has_builtin(__builtin_sub_overflow)
+ return __builtin_sub_overflow(X, Y, &Result);
+#else
+ return SubOverflow(X, Y, Result);
+#endif
+}
+LLVM_ATTRIBUTE_ALWAYS_INLINE bool mulOverflow(int64_t X, int64_t Y,
+ int64_t &Result) {
+#if __has_builtin(__builtin_mul_overflow)
+ return __builtin_mul_overflow(X, Y, &Result);
+#else
+ return MulOverflow(X, Y, Result);
+#endif
+}
+} // namespace detail
+
+/// This class provides support for multi-precision arithmetic.
+///
+/// Unlike APInt, this extends the precision as necessary to prevent overflows
+/// and supports operations between objects with differing internal precisions.
+///
+/// This is optimized for small-values by providing fast-paths for the cases
+/// when the value stored fits in 64-bits. We annotate all fastpaths by using
+/// the LLVM_LIKELY/LLVM_UNLIKELY annotations. Removing these would result in
+/// a 1.2x performance slowdown.
+///
+/// We always_inline all operations; removing these results in a 1.5x
+/// performance slowdown.
+///
+/// When holdsLarge is true, a SlowMPInt is held in the union. If it is false,
+/// the int64_t is held. Using std::variant instead would lead to significantly
+/// worse performance.
+class MPInt {
+private:
+ union {
----------------
tschuett wrote:
Could this be a `std::variant` instead?
https://github.com/llvm/llvm-project/pull/94953
More information about the Mlir-commits
mailing list