diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/ArithmeticUtils.h @@ -6,23 +6,13 @@ // //===----------------------------------------------------------------------===// // -// 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. +// A collection of "safe" arithmetic helper methods. // //===----------------------------------------------------------------------===// #ifndef MLIR_EXECUTIONENGINE_SPARSETENSOR_ARITHMETICUTILS_H #define MLIR_EXECUTIONENGINE_SPARSETENSOR_ARITHMETICUTILS_H -#include "mlir/ExecutionEngine/SparseTensor/Attributes.h" - #include #include #include @@ -108,12 +98,6 @@ // //===----------------------------------------------------------------------===// -// 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` which checks for overflow/underflow. /// The implementation avoids performing runtime assertions whenever /// the types alone are sufficient to statically prove that overflow @@ -140,7 +124,8 @@ // 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) && MLIR_SPARSETENSOR_HAS_BUILTIN(__builtin_mul_overflow) +#if !defined(NDEBUG) && defined(__has_builtin) && \ + __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 deleted file mode 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Attributes.h +++ /dev/null @@ -1,85 +0,0 @@ -//===- 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. -// -#if defined(__cplusplus) && defined(__has_cpp_attribute) -// NOTE: The __cplusplus requirement should be unnecessary, but guards -// against issues with GCC . -#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: -// Clang: -#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: -// Clang: -#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 -// differs 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 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/ErrorHandling.h @@ -6,20 +6,10 @@ // //===----------------------------------------------------------------------===// // -// 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 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h @@ -15,18 +15,11 @@ // (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 @@ -84,13 +77,6 @@ //===----------------------------------------------------------------------===// -// 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 deleted file mode 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/PermutationRef.h +++ /dev/null @@ -1,141 +0,0 @@ -//===- 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 -#include -#include - -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 - inline std::vector pushforward(const std::vector &values) const { - return pushforward(values.size(), values.data()); - } - - template - inline std::vector pushforward(uint64_t size, const T *values) const { - std::vector 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 - 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 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 - inline std::vector permute(const std::vector &values) const { - return permute(values.size(), values.data()); - } - - template - inline std::vector permute(uint64_t size, const T *values) const { - std::vector out(permSize); - permute(size, values, out.data()); - return out; - } - - template - 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 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h @@ -36,13 +36,133 @@ #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 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 + inline std::vector pushforward(const std::vector &values) const { + return pushforward(values.size(), values.data()); + } + + template + inline std::vector pushforward(uint64_t size, const T *values) const { + std::vector 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 + 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 inverse() const { + std::vector 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 + inline std::vector permute(const std::vector &values) const { + return permute(values.size(), values.data()); + } + + template + inline std::vector permute(uint64_t size, const T *values) const { + std::vector out(permSize); + permute(size, values, out.data()); + return out; + } + + template + 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. @@ -542,8 +662,6 @@ /// 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

(pos)); } @@ -560,8 +678,6 @@ 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(crd)); } else { // Dense level. ASSERT_DENSE_DLT(dlt); @@ -585,8 +701,6 @@ // 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(crd); } diff --git a/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt b/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt --- a/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt +++ b/mlir/lib/ExecutionEngine/SparseTensor/CMakeLists.txt @@ -8,7 +8,6 @@ add_mlir_library(MLIRSparseTensorRuntime File.cpp NNZ.cpp - PermutationRef.cpp Storage.cpp EXCLUDE_FROM_LIBMLIR @@ -19,8 +18,6 @@ ) set_property(TARGET MLIRSparseTensorRuntime PROPERTY CXX_STANDARD 17) -# To make sure we adhere to the style guide: -# 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 deleted file mode 100644 --- a/mlir/lib/ExecutionEngine/SparseTensor/PermutationRef.cpp +++ /dev/null @@ -1,38 +0,0 @@ -//===- 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 -#include -#include - -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 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 -mlir::sparse_tensor::detail::PermutationRef::inverse() const { - std::vector 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 --- a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp +++ b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp @@ -54,7 +54,6 @@ #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 diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -8519,16 +8519,13 @@ 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"],