[Mlir-commits] [mlir] 471004c - Revert "[mlir][sparse] simplification of sparse runtime support lib"
Mehdi Amini
llvmlistbot at llvm.org
Fri Sep 1 11:50:21 PDT 2023
Author: Mehdi Amini
Date: 2023-09-01T11:50:14-07:00
New Revision: 471004c5c9bbd74ccc55066fdc822b137880a405
URL: https://github.com/llvm/llvm-project/commit/471004c5c9bbd74ccc55066fdc822b137880a405
DIFF: https://github.com/llvm/llvm-project/commit/471004c5c9bbd74ccc55066fdc822b137880a405.diff
LOG: Revert "[mlir][sparse] simplification of sparse runtime support lib"
This reverts commit 14c58cf5c39a39a335893bc98493c5edc75a91b3.
The gcc7 build is broken.
Added:
mlir/include/mlir/ExecutionEngine/SparseTensor/Attributes.h
mlir/include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h
mlir/lib/ExecutionEngine/SparseTensor/PermutationRef.cpp
Modified:
mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h
mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h
mlir/include/mlir/ExecutionEngine/SparseTensor/File.h
mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt
mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
Removed:
################################################################################
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h
index af31b98c1f7025..c31337a225d918 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h
@@ -6,13 +6,23 @@
//
//===----------------------------------------------------------------------===//
//
-// A collection of "safe" arithmetic helper methods.
+// This header is not part of the public API. It is placed in the
+// includes directory only because that's required by the implementations
+// of template-classes.
+//
+// This file is part of the lightweight runtime support library for sparse
+// tensor manipulations. The functionality of the support library is meant
+// to simplify benchmarking, testing, and debugging MLIR code operating on
+// sparse tensors. However, the provided functionality is **not** part of
+// core MLIR itself.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_ARITHMETICUTILS_H
#define MLIR_EXECUTIONENGINE_SPARSETENSOR_ARITHMETICUTILS_H
+#include "mlir/ExecutionEngine/SparseTensor/Attributes.h"
+
#include <cassert>
#include <cinttypes>
#include <limits>
@@ -98,6 +108,12 @@ constexpr bool safelyGE(T t, U u) noexcept {
//
//===----------------------------------------------------------------------===//
+// TODO: we would like to be able to pass in custom error messages, to
+// improve the user experience. We should be able to use something like
+// `assert(((void)(msg ? msg : defaultMsg), cond))`; but I'm not entirely
+// sure that'll work as intended when done within a function-definition
+// rather than within a macro-definition.
+
/// A version of `static_cast<To>` which checks for overflow/underflow.
/// The implementation avoids performing runtime assertions whenever
/// the types alone are sufficient to statically prove that overflow
@@ -124,8 +140,7 @@ inline uint64_t checkedMul(uint64_t lhs, uint64_t rhs) {
// If assertions are enabled and we have the intrinsic, then use it to
// avoid the expensive division. If assertions are disabled, then don't
// bother with intrinsics (to avoid any possible slowdown vs `operator*`).
-#if !defined(NDEBUG) && defined(__has_builtin) && \
- __has_builtin(__builtin_mul_overflow)
+#if !defined(NDEBUG) && MLIR_SPARSETENSOR_HAS_BUILTIN(__builtin_mul_overflow)
uint64_t result;
bool overflowed = __builtin_mul_overflow(lhs, rhs, &result);
assert(!overflowed && "Integer overflow");
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/Attributes.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/Attributes.h
new file mode 100644
index 00000000000000..681eba60d2c90a
--- /dev/null
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Attributes.h
@@ -0,0 +1,85 @@
+//===- Attributes.h - C++ attributes for SparseTensorRuntime ----*- 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 header defines various macros for using C++ attributes whenever
+// they're supported by the compiler. These macros are the same as the
+// versions in the LLVMSupport library, but we define our own versions
+// in order to avoid introducing that dependency just for the sake of
+// these macros. (If we ever do end up depending on LLVMSupport, then
+// we should remove this header and use "llvm/Support/Compiler.h" instead.)
+//
+// This file is part of the lightweight runtime support library for sparse
+// tensor manipulations. The functionality of the support library is meant
+// to simplify benchmarking, testing, and debugging MLIR code operating on
+// sparse tensors. However, the provided functionality is **not** part of
+// core MLIR itself.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_ATTRIBUTES_H
+#define MLIR_EXECUTIONENGINE_SPARSETENSOR_ATTRIBUTES_H
+
+// A wrapper around `__has_cpp_attribute` for C++11 style attributes,
+// which are defined by ISO C++ SD-6.
+// <https://en.cppreference.com/w/cpp/experimental/feature_test>
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+// NOTE: The __cplusplus requirement should be unnecessary, but guards
+// against issues with GCC <https://bugs.llvm.org/show_bug.cgi?id=23435>.
+#define MLIR_SPARSETENSOR_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+#define MLIR_SPARSETENSOR_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+
+// A wrapper around `__has_attribute`, which is defined by GCC 5+ and Clang.
+// GCC: <https://gcc.gnu.org/gcc-5/changes.html>
+// Clang: <https://clang.llvm.org/docs/LanguageExtensions.html>
+#ifdef __has_attribute
+#define MLIR_SPARSETENSOR_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+#define MLIR_SPARSETENSOR_HAS_ATTRIBUTE(x) 0
+#endif
+
+// A wrapper around `__has_builtin`, which is defined by GCC and Clang
+// but is missing on some versions of MSVC.
+// GCC: <https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fbuiltin.html>
+// Clang: <https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin>
+#ifdef __has_builtin
+#define MLIR_SPARSETENSOR_HAS_BUILTIN(x) __has_builtin(x)
+#else
+#define MLIR_SPARSETENSOR_HAS_BUILTIN(x) 0
+#endif
+
+// An attribute for non-owning classes (like `PermutationRef`) to enable
+// lifetime warnings.
+#if MLIR_SPARSETENSOR_HAS_CPP_ATTRIBUTE(gsl::Pointer)
+#define MLIR_SPARSETENSOR_GSL_POINTER [[gsl::Pointer]]
+#else
+#define MLIR_SPARSETENSOR_GSL_POINTER
+#endif
+
+// An attribute for functions which are "pure" in the following sense:
+// * the result depends only on the function arguments
+// * pointer arguments are allowed to be read from, but not written to
+// * has no observable effects other than the return value
+//
+// This allows the compiler to avoid repeated function calls whenever
+// it can determine that the arguments are the same and that memory has
+// not changed.
+//
+// This macro is called `LLVM_READONLY` by LLVMSupport. This definition
+//
diff ers slightly from the LLVM version by using `gnu::pure` when
+// available, like Abseil's `ABSL_ATTRIBUTE_PURE_FUNCTION`.
+#if MLIR_SPARSETENSOR_HAS_CPP_ATTRIBUTE(gnu::pure)
+#define MLIR_SPARSETENSOR_PURE [[gnu::pure]]
+#elif MLIR_SPARSETENSOR_HAS_ATTRIBUTE(pure) || defined(__GNUC__)
+#define MLIR_SPARSETENSOR_PURE __attribute__((pure))
+#else
+#define MLIR_SPARSETENSOR_PURE
+#endif
+
+#endif // MLIR_EXECUTIONENGINE_SPARSETENSOR_ATTRIBUTES_H
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h
index 6b39526211c77d..e0385ffdd84f87 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h
@@ -6,10 +6,20 @@
//
//===----------------------------------------------------------------------===//
//
+// This header is not part of the public API. It is placed in the
+// includes directory only because that's required by the implementations
+// of template-classes.
+//
// This file defines an extremely lightweight API for fatal errors (not
// arising from assertions). The API does not attempt to be sophisticated
// in any way, it's just the usual "I give up" style of error reporting.
//
+// This file is part of the lightweight runtime support library for sparse
+// tensor manipulations. The functionality of the support library is meant
+// to simplify benchmarking, testing, and debugging MLIR code operating on
+// sparse tensors. However, the provided functionality is **not** part of
+// core MLIR itself.
+//
//===----------------------------------------------------------------------===//
#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_ERRORHANDLING_H
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h
index 1b6736b0cdd1d1..8d5eb48f38048e 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h
@@ -15,11 +15,18 @@
// (2) Formidable Repository of Open Sparse Tensors and Tools (FROSTT): *.tns
// http://frostt.io/tensors/file-formats.html
//
+// This file is part of the lightweight runtime support library for sparse
+// tensor manipulations. The functionality of the support library is meant
+// to simplify benchmarking, testing, and debugging MLIR code operating on
+// sparse tensors. However, the provided functionality is **not** part of
+// core MLIR itself.
+//
//===----------------------------------------------------------------------===//
#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
#define MLIR_EXECUTIONENGINE_SPARSETENSOR_FILE_H
+#include "mlir/ExecutionEngine/SparseTensor/PermutationRef.h"
#include "mlir/ExecutionEngine/SparseTensor/Storage.h"
#include <fstream>
@@ -77,6 +84,13 @@ inline V readValue(char **linePtr, bool isPattern) {
//===----------------------------------------------------------------------===//
+// TODO: benchmark whether to keep various methods inline vs moving them
+// off to the cpp file.
+
+// TODO: consider distinguishing separate classes for before vs
+// after reading the header; so as to statically avoid the need
+// to `assert(isValid())`.
+
/// This class abstracts over the information stored in file headers,
/// as well as providing the buffers and methods for parsing those headers.
class SparseTensorReader final {
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h
new file mode 100644
index 00000000000000..313470d27a38c0
--- /dev/null
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h
@@ -0,0 +1,141 @@
+//===- PermutationRef.h - Permutation reference wrapper ---------*- 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 header is not part of the public API. It is placed in the
+// includes directory only because that's required by the implementations
+// of template-classes.
+//
+// This file is part of the lightweight runtime support library for sparse
+// tensor manipulations. The functionality of the support library is meant
+// to simplify benchmarking, testing, and debugging MLIR code operating on
+// sparse tensors. However, the provided functionality is **not** part of
+// core MLIR itself.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_PERMUTATIONREF_H
+#define MLIR_EXECUTIONENGINE_SPARSETENSOR_PERMUTATIONREF_H
+
+#include "mlir/ExecutionEngine/SparseTensor/Attributes.h"
+#include "mlir/ExecutionEngine/SparseTensor/ErrorHandling.h"
+
+#include <cassert>
+#include <cinttypes>
+#include <vector>
+
+namespace mlir {
+namespace sparse_tensor {
+namespace detail {
+
+/// Checks whether the `perm` array is a permutation of `[0 .. size)`.
+MLIR_SPARSETENSOR_PURE bool isPermutation(uint64_t size, const uint64_t *perm);
+
+/// Wrapper around `isPermutation` to ensure consistent error messages.
+inline void assertIsPermutation(uint64_t size, const uint64_t *perm) {
+#ifndef NDEBUG
+ if (!isPermutation(size, perm))
+ MLIR_SPARSETENSOR_FATAL("Not a permutation of [0..%" PRIu64 ")\n", size);
+#endif
+}
+
+// TODO: To implement things like `inverse` and `compose` while preserving
+// the knowledge that `isPermutation` is true, we'll need to also have
+// an owning version of `PermutationRef`. (Though ideally we'll really
+// want to defunctionalize those methods so that we can avoid intermediate
+// arrays/copies and only materialize the data on request.)
+
+/// A non-owning class for capturing the knowledge that `isPermutation`
+/// is true, to avoid needing to assert it repeatedly.
+class MLIR_SPARSETENSOR_GSL_POINTER [[nodiscard]] PermutationRef final {
+public:
+ /// Asserts `isPermutation` and returns the witness to that being true.
+ //
+ // TODO: For now the assertive ctor is sufficient, but in principle
+ // we'll want a factory that can optionally construct the object
+ // (so callers can handle errors themselves).
+ explicit PermutationRef(uint64_t size, const uint64_t *perm)
+ : permSize(size), perm(perm) {
+ assertIsPermutation(size, perm);
+ }
+
+ uint64_t size() const { return permSize; }
+
+ const uint64_t *data() const { return perm; }
+
+ const uint64_t &operator[](uint64_t i) const {
+ assert(i < permSize && "index is out of bounds");
+ return perm[i];
+ }
+
+ /// Constructs a pushforward array of values. This method is the inverse
+ /// of `permute` in the sense that for all `p` and `xs` we have:
+ /// * `p.permute(p.pushforward(xs)) == xs`
+ /// * `p.pushforward(p.permute(xs)) == xs`
+ template <typename T>
+ inline std::vector<T> pushforward(const std::vector<T> &values) const {
+ return pushforward(values.size(), values.data());
+ }
+
+ template <typename T>
+ inline std::vector<T> pushforward(uint64_t size, const T *values) const {
+ std::vector<T> out(permSize);
+ pushforward(size, values, out.data());
+ return out;
+ }
+
+ // NOTE: This form of the method is required by `toMLIRSparseTensor`,
+ // so it can reuse the `out` buffer for each iteration of a loop.
+ template <typename T>
+ inline void pushforward(uint64_t size, const T *values, T *out) const {
+ assert(size == permSize && "size mismatch");
+ for (uint64_t i = 0; i < permSize; ++i)
+ out[perm[i]] = values[i];
+ }
+
+ // NOTE: this is only needed by `toMLIRSparseTensor`, which in
+ // turn only needs it as a vector to hand off to `newSparseTensor`.
+ // Otherwise we would want the result to be an owning-permutation,
+ // to retain the knowledge that `isPermutation` is true.
+ //
+ /// Constructs the inverse permutation. This is equivalent to calling
+ /// `pushforward` with `std::iota` for the values.
+ std::vector<uint64_t> inverse() const;
+
+ /// Constructs a permuted array of values. This method is the inverse
+ /// of `pushforward` in the sense that for all `p` and `xs` we have:
+ /// * `p.permute(p.pushforward(xs)) == xs`
+ /// * `p.pushforward(p.permute(xs)) == xs`
+ template <typename T>
+ inline std::vector<T> permute(const std::vector<T> &values) const {
+ return permute(values.size(), values.data());
+ }
+
+ template <typename T>
+ inline std::vector<T> permute(uint64_t size, const T *values) const {
+ std::vector<T> out(permSize);
+ permute(size, values, out.data());
+ return out;
+ }
+
+ template <typename T>
+ inline void permute(uint64_t size, const T *values, T *out) const {
+ assert(size == permSize && "size mismatch");
+ for (uint64_t i = 0; i < permSize; ++i)
+ out[i] = values[perm[i]];
+ }
+
+private:
+ const uint64_t permSize;
+ const uint64_t *const perm; // non-owning pointer.
+};
+
+} // namespace detail
+} // namespace sparse_tensor
+} // namespace mlir
+
+#endif // MLIR_EXECUTIONENGINE_SPARSETENSOR_PERMUTATIONREF_H
diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
index 4e995cbcf0f0f9..ff61a0d035a2f1 100644
--- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
+++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h
@@ -36,133 +36,13 @@
#include "mlir/Dialect/SparseTensor/IR/Enums.h"
#include "mlir/ExecutionEngine/Float16bits.h"
#include "mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h"
+#include "mlir/ExecutionEngine/SparseTensor/Attributes.h"
#include "mlir/ExecutionEngine/SparseTensor/COO.h"
#include "mlir/ExecutionEngine/SparseTensor/ErrorHandling.h"
-#if defined(__cplusplus) && defined(__has_cpp_attribute) && \
- __has_cpp_attribute(gsl::Pointer)
-#define MLIR_SPARSETENSOR_GSL_POINTER [[gsl::Pointer]]
-#else
-#define MLIR_SPARSETENSOR_GSL_POINTER
-#endif
-
namespace mlir {
namespace sparse_tensor {
-namespace detail {
-
-/// Checks whether the `perm` array is a permutation of `[0 .. size)`.
-inline bool isPermutation(uint64_t size, const uint64_t *perm) {
- assert(perm && "Got nullptr for permutation");
- std::vector<bool> seen(size, false);
- for (uint64_t i = 0; i < size; ++i) {
- const uint64_t j = perm[i];
- if (j >= size || seen[j])
- return false;
- seen[j] = true;
- }
- for (uint64_t i = 0; i < size; ++i)
- if (!seen[i])
- return false;
- return true;
-}
-
-/// Wrapper around `isPermutation` to ensure consistent error messages.
-inline void assertIsPermutation(uint64_t size, const uint64_t *perm) {
-#ifndef NDEBUG
- if (!isPermutation(size, perm))
- MLIR_SPARSETENSOR_FATAL("Not a permutation of [0..%" PRIu64 ")\n", size);
-#endif
-}
-
-/// A non-owning class for capturing the knowledge that `isPermutation`
-/// is true, to avoid needing to assert it repeatedly.
-class MLIR_SPARSETENSOR_GSL_POINTER [[nodiscard]] PermutationRef final {
-public:
- /// Asserts `isPermutation` and returns the witness to that being true.
- explicit PermutationRef(uint64_t size, const uint64_t *perm)
- : permSize(size), perm(perm) {
- assertIsPermutation(size, perm);
- }
-
- uint64_t size() const { return permSize; }
-
- const uint64_t *data() const { return perm; }
-
- const uint64_t &operator[](uint64_t i) const {
- assert(i < permSize && "index is out of bounds");
- return perm[i];
- }
-
- /// Constructs a pushforward array of values. This method is the inverse
- /// of `permute` in the sense that for all `p` and `xs` we have:
- /// * `p.permute(p.pushforward(xs)) == xs`
- /// * `p.pushforward(p.permute(xs)) == xs`
- template <typename T>
- inline std::vector<T> pushforward(const std::vector<T> &values) const {
- return pushforward(values.size(), values.data());
- }
-
- template <typename T>
- inline std::vector<T> pushforward(uint64_t size, const T *values) const {
- std::vector<T> out(permSize);
- pushforward(size, values, out.data());
- return out;
- }
-
- // NOTE: This form of the method is required by `toMLIRSparseTensor`,
- // so it can reuse the `out` buffer for each iteration of a loop.
- template <typename T>
- inline void pushforward(uint64_t size, const T *values, T *out) const {
- assert(size == permSize && "size mismatch");
- for (uint64_t i = 0; i < permSize; ++i)
- out[perm[i]] = values[i];
- }
-
- // NOTE: this is only needed by `toMLIRSparseTensor`, which in
- // turn only needs it as a vector to hand off to `newSparseTensor`.
- // Otherwise we would want the result to be an owning-permutation,
- // to retain the knowledge that `isPermutation` is true.
- //
- /// Constructs the inverse permutation. This is equivalent to calling
- /// `pushforward` with `std::iota` for the values.
- inline std::vector<uint64_t> inverse() const {
- std::vector<uint64_t> out(permSize);
- for (uint64_t i = 0; i < permSize; ++i)
- out[perm[i]] = i;
- return out;
- }
-
- /// Constructs a permuted array of values. This method is the inverse
- /// of `pushforward` in the sense that for all `p` and `xs` we have:
- /// * `p.permute(p.pushforward(xs)) == xs`
- /// * `p.pushforward(p.permute(xs)) == xs`
- template <typename T>
- inline std::vector<T> permute(const std::vector<T> &values) const {
- return permute(values.size(), values.data());
- }
-
- template <typename T>
- inline std::vector<T> permute(uint64_t size, const T *values) const {
- std::vector<T> out(permSize);
- permute(size, values, out.data());
- return out;
- }
-
- template <typename T>
- inline void permute(uint64_t size, const T *values, T *out) const {
- assert(size == permSize && "size mismatch");
- for (uint64_t i = 0; i < permSize; ++i)
- out[i] = values[perm[i]];
- }
-
-private:
- const uint64_t permSize;
- const uint64_t *const perm; // non-owning pointer.
-};
-
-} // namespace detail
-
//===----------------------------------------------------------------------===//
// This forward decl is sufficient to split `SparseTensorStorageBase` into
// its own header, but isn't sufficient for `SparseTensorStorage` to join it.
@@ -662,6 +542,8 @@ class SparseTensorStorage final : public SparseTensorStorageBase {
/// the previous position and smaller than `coordinates[lvl].capacity()`).
void appendPos(uint64_t lvl, uint64_t pos, uint64_t count = 1) {
ASSERT_COMPRESSED_LVL(lvl);
+ // TODO: we'd like to recover the nicer error message:
+ // "Position value is too large for the P-type"
positions[lvl].insert(positions[lvl].end(), count,
detail::checkOverflowCast<P>(pos));
}
@@ -678,6 +560,8 @@ class SparseTensorStorage final : public SparseTensorStorageBase {
void appendCrd(uint64_t lvl, uint64_t full, uint64_t crd) {
const auto dlt = getLvlType(lvl); // Avoid redundant bounds checking.
if (isCompressedDLT(dlt) || isSingletonDLT(dlt)) {
+ // TODO: we'd like to recover the nicer error message:
+ // "Coordinate value is too large for the C-type"
coordinates[lvl].push_back(detail::checkOverflowCast<C>(crd));
} else { // Dense level.
ASSERT_DENSE_DLT(dlt);
@@ -701,6 +585,8 @@ class SparseTensorStorage final : public SparseTensorStorageBase {
// entry has been initialized; thus we must be sure to check `size()`
// here, instead of `capacity()` as would be ideal.
assert(pos < coordinates[lvl].size() && "Position is out of bounds");
+ // TODO: we'd like to recover the nicer error message:
+ // "Coordinate value is too large for the C-type"
coordinates[lvl][pos] = detail::checkOverflowCast<C>(crd);
}
diff --git a/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt b/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt
index 085d83634a702a..ac04ef31423e27 100644
--- a/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt
+++ b/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt
@@ -8,6 +8,7 @@
add_mlir_library(MLIRSparseTensorRuntime
File.cpp
NNZ.cpp
+ PermutationRef.cpp
Storage.cpp
EXCLUDE_FROM_LIBMLIR
@@ -18,6 +19,8 @@ add_mlir_library(MLIRSparseTensorRuntime
)
set_property(TARGET MLIRSparseTensorRuntime PROPERTY CXX_STANDARD 17)
+# To make sure we adhere to the style guide:
+# <https://llvm.org/docs/CodingStandards.html#provide-a-virtual-method-anchor-for-classes-in-headers>
check_cxx_compiler_flag(-Wweak-vtables
COMPILER_SUPPORTS_WARNING_WEAK_VTABLES)
if(COMPILER_SUPPORTS_WARNING_WEAK_VTABLES)
diff --git a/mlir/lib/ExecutionEngine/SparseTensor/PermutationRef.cpp b/mlir/lib/ExecutionEngine/SparseTensor/PermutationRef.cpp
new file mode 100644
index 00000000000000..0230095ec8ca48
--- /dev/null
+++ b/mlir/lib/ExecutionEngine/SparseTensor/PermutationRef.cpp
@@ -0,0 +1,38 @@
+//===- PermutationRef.cpp - Permutation reference wrapper -----------------===//
+//
+// 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 "mlir/ExecutionEngine/SparseTensor/PermutationRef.h"
+
+#include <cassert>
+#include <cinttypes>
+#include <vector>
+
+bool mlir::sparse_tensor::detail::isPermutation(uint64_t size,
+ const uint64_t *perm) {
+ assert(perm && "Got nullptr for permutation");
+ // TODO: If we ever depend on LLVMSupport, then use `llvm::BitVector` instead.
+ std::vector<bool> seen(size, false);
+ for (uint64_t i = 0; i < size; ++i) {
+ const uint64_t j = perm[i];
+ if (j >= size || seen[j])
+ return false;
+ seen[j] = true;
+ }
+ for (uint64_t i = 0; i < size; ++i)
+ if (!seen[i])
+ return false;
+ return true;
+}
+
+std::vector<uint64_t>
+mlir::sparse_tensor::detail::PermutationRef::inverse() const {
+ std::vector<uint64_t> out(permSize);
+ for (uint64_t i = 0; i < permSize; ++i)
+ out[perm[i]] = i;
+ return out;
+}
diff --git a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
index d76a34564c47a4..ef68ae293e61cf 100644
--- a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
+++ b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp
@@ -54,6 +54,7 @@
#include "mlir/ExecutionEngine/SparseTensor/COO.h"
#include "mlir/ExecutionEngine/SparseTensor/ErrorHandling.h"
#include "mlir/ExecutionEngine/SparseTensor/File.h"
+#include "mlir/ExecutionEngine/SparseTensor/PermutationRef.h"
#include "mlir/ExecutionEngine/SparseTensor/Storage.h"
#include <cstring>
diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
index 630fb1988bb08d..dac68a7049b350 100644
--- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel
@@ -8519,13 +8519,16 @@ cc_library(
srcs = [
"lib/ExecutionEngine/SparseTensor/File.cpp",
"lib/ExecutionEngine/SparseTensor/NNZ.cpp",
+ "lib/ExecutionEngine/SparseTensor/PermutationRef.cpp",
"lib/ExecutionEngine/SparseTensor/Storage.cpp",
],
hdrs = [
"include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h",
+ "include/mlir/ExecutionEngine/SparseTensor/Attributes.h",
"include/mlir/ExecutionEngine/SparseTensor/COO.h",
"include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h",
"include/mlir/ExecutionEngine/SparseTensor/File.h",
+ "include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h",
"include/mlir/ExecutionEngine/SparseTensor/Storage.h",
],
includes = ["include"],
More information about the Mlir-commits
mailing list