MLIR 24.0.0git
SparseTensor.h
Go to the documentation of this file.
1//===- SparseTensor.h - Sparse tensor dialect -------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSOR_H_
10#define MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSOR_H_
11
16
17#include "llvm/ADT/bit.h"
18
19//===----------------------------------------------------------------------===//
20//
21// Type aliases to help code be more self-documenting. Unfortunately
22// these are not type-checked, so they only provide documentation rather
23// than doing anything to prevent mixups.
24//
25//===----------------------------------------------------------------------===//
26
27namespace mlir {
28namespace sparse_tensor {
29
30/// The type of dimension identifiers and dimension-ranks.
31using Dimension = uint64_t;
32
33/// The type of level identifiers and level-ranks.
34using Level = uint64_t;
35
36/// The type for individual components of a compile-time shape,
37/// including the value `ShapedType::kDynamic` (for shapes).
38using Size = int64_t;
39
40/// A simple structure that encodes a range of levels in the sparse tensors
41/// that forms a COO segment.
42struct COOSegment {
43 std::pair<Level, Level> lvlRange; // [low, high)
44 bool isSoA;
45
46 bool isAoS() const { return !isSoA; }
47 bool isSegmentStart(Level l) const { return l == lvlRange.first; }
48 bool inSegment(Level l) const {
49 return l >= lvlRange.first && l < lvlRange.second;
50 }
51};
52
53/// A simple wrapper to encode a bitset of (at most 64) levels, currently used
54/// by `sparse_tensor.iterate` operation for the set of levels on which the
55/// coordinates should be loaded.
56class I64BitSet {
57 uint64_t storage = 0;
58
59public:
60 using const_set_bits_iterator = llvm::const_set_bits_iterator_impl<I64BitSet>;
62 return const_set_bits_iterator(*this);
63 }
65 return const_set_bits_iterator(*this, -1);
66 }
68 return make_range(begin(), end());
69 }
70
71 I64BitSet() = default;
72 explicit I64BitSet(uint64_t bits) : storage(bits) {}
73 operator uint64_t() const { return storage; }
74
75 I64BitSet &set(unsigned i) {
76 assert(i < 64);
77 storage |= static_cast<uint64_t>(0x01u) << i;
78 return *this;
79 }
80
82 storage |= static_cast<uint64_t>(lhs);
83 return *this;
84 }
85
86 I64BitSet &lshift(unsigned offset) {
87 storage = storage << offset;
88 return *this;
89 }
90
91 bool isSubSetOf(const I64BitSet p) const {
92 I64BitSet tmp = *this;
93 tmp |= p;
94 return tmp == p;
95 }
96
97 // Needed by `llvm::const_set_bits_iterator_impl`.
98 int find_first() const { return min(); }
99 int find_next(unsigned prev) const {
100 if (prev >= max() - 1)
101 return -1;
102
103 uint64_t b = storage >> (prev + static_cast<int64_t>(1));
104 assert(b != 0);
105
106 return llvm::countr_zero(b) + prev + static_cast<int64_t>(1);
107 }
108
109 bool operator[](unsigned i) const {
110 assert(i < 64);
111 return (storage & (static_cast<int64_t>(1) << i)) != 0;
112 }
113 unsigned min() const {
114 unsigned m = llvm::countr_zero(storage);
115 return m == 64 ? -1 : m;
116 }
117 unsigned max() const { return llvm::bit_width(storage); }
118 unsigned count() const { return llvm::popcount(storage); }
119 bool empty() const { return storage == 0; }
120};
121
122} // namespace sparse_tensor
123} // namespace mlir
124
125//===----------------------------------------------------------------------===//
126// TableGen-defined classes
127//===----------------------------------------------------------------------===//
128
129#define GET_ATTRDEF_CLASSES
130#include "mlir/Dialect/SparseTensor/IR/SparseTensorAttrEnums.h.inc"
131
132#define GET_ATTRDEF_CLASSES
133#include "mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.h.inc"
134
135#define GET_TYPEDEF_CLASSES
136#include "mlir/Dialect/SparseTensor/IR/SparseTensorTypes.h.inc"
137
138#define GET_OP_CLASSES
139#include "mlir/Dialect/SparseTensor/IR/SparseTensorOps.h.inc"
140
141#include "mlir/Dialect/SparseTensor/IR/SparseTensorOpsDialect.h.inc"
142
143//===----------------------------------------------------------------------===//
144// Additional convenience methods.
145//===----------------------------------------------------------------------===//
146
147namespace mlir {
148namespace sparse_tensor {
149
150/// Convenience method to abbreviate casting `getType()`.
151template <typename T>
152inline RankedTensorType getRankedTensorType(T &&t) {
153 assert(static_cast<bool>(t) && "getRankedTensorType got null argument");
154 return dyn_cast<RankedTensorType>(std::forward<T>(t).getType());
155}
156
157/// Convenience method to abbreviate casting `getType()`.
158template <typename T>
159inline MemRefType getMemRefType(T &&t) {
160 assert(static_cast<bool>(t) && "getMemRefType got null argument");
161 return cast<MemRefType>(std::forward<T>(t).getType());
162}
163
164/// Convenience method to get a sparse encoding attribute from a type.
165/// Returns null-attribute for any type without an encoding.
166SparseTensorEncodingAttr getSparseTensorEncoding(Type type);
167
168/// Returns true iff the type range has any sparse tensor type.
169inline bool hasAnySparseType(TypeRange types) {
170 return llvm::any_of(types, [](Type type) {
171 return getSparseTensorEncoding(type) != nullptr;
172 });
173}
174
175/// Returns true iff MLIR operand has any sparse operand.
177 return hasAnySparseType(op->getOperands().getTypes());
178}
179
180/// Returns true iff MLIR operand has any sparse result.
182 return hasAnySparseType(op->getResults().getTypes());
183}
184
185/// Returns true iff MLIR operand has any sparse operand or result.
189
190/// Returns true iff MLIR operation has any sparse tensor with non-identity
191/// dim2lvl maps.
193
194//
195// Inference.
196//
197
198/// Given the dimToLvl map, infers the lvlToDim map, or returns
199/// empty Affine map when inference fails.
200AffineMap inferLvlToDim(AffineMap dimToLvl, MLIRContext *context);
201
202/// Returns the lvlToDim map for the given dimToLvl map specific
203/// to the block sparse cases.
204/// Asserts on failure (so only use when known to succeed).
206
207/// Given the dimToLvl map, returns the block sizes in a vector.
208/// For instance, a 2x3 block will return [2, 3]. Unblocked dimension i
209/// will return 0, and i floordiv 1, i mod 1 will return 1. Therefore,
210/// the example below will return [0, 1].
211/// map = ( i, j ) ->
212/// ( i : dense,
213/// j floordiv 1 : compressed,
214/// j mod 1 : dense
215/// )
216/// Only valid block sparsity will be accepted.
218
219/// Given the dimToLvl map, returns if it's block sparsity.
220bool isBlockSparsity(AffineMap dimToLvl);
221
222//
223// Reordering.
224//
225
226/// Convenience method to translate the given level to the corresponding
227/// dimension.
228/// Requires: `enc` has a permuted dim2lvl map and `0 <= l < lvlRank`.
229Dimension toDim(SparseTensorEncodingAttr enc, Level l);
230
231/// Convenience method to translate the given dimension to the corresponding
232/// level.
233/// Requires: `enc` has a permuted dim2lvl map and `0 <= d < dimRank`.
234Level toLvl(SparseTensorEncodingAttr enc, Dimension d);
235
236} // namespace sparse_tensor
237} // namespace mlir
238
239#endif // MLIR_DIALECT_SPARSETENSOR_IR_SPARSETENSOR_H_
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
Definition AffineMap.h:46
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:71
type_range getTypes() const
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition Operation.h:405
result_range getResults()
Definition Operation.h:442
type_range getTypes() const
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:40
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
I64BitSet & lshift(unsigned offset)
iterator_range< const_set_bits_iterator > bits() const
bool isSubSetOf(const I64BitSet p) const
I64BitSet & set(unsigned i)
const_set_bits_iterator begin() const
int find_next(unsigned prev) const
I64BitSet & operator|=(I64BitSet lhs)
bool operator[](unsigned i) const
const_set_bits_iterator end() const
llvm::const_set_bits_iterator_impl< I64BitSet > const_set_bits_iterator
bool hasAnySparseOperandOrResult(Operation *op)
Returns true iff MLIR operand has any sparse operand or result.
uint64_t Dimension
The type of dimension identifiers and dimension-ranks.
Dimension toDim(SparseTensorEncodingAttr enc, Level l)
Convenience method to translate the given level to the corresponding dimension.
RankedTensorType getRankedTensorType(T &&t)
Convenience method to abbreviate casting getType().
uint64_t Level
The type of level identifiers and level-ranks.
AffineMap inferLvlToDim(AffineMap dimToLvl, MLIRContext *context)
Given the dimToLvl map, infers the lvlToDim map, or returns empty Affine map when inference fails.
SparseTensorEncodingAttr getSparseTensorEncoding(Type type)
Convenience method to get a sparse encoding attribute from a type.
MemRefType getMemRefType(T &&t)
Convenience method to abbreviate casting getType().
bool hasAnySparseType(TypeRange types)
Returns true iff the type range has any sparse tensor type.
Level toLvl(SparseTensorEncodingAttr enc, Dimension d)
Convenience method to translate the given dimension to the corresponding level.
bool isBlockSparsity(AffineMap dimToLvl)
Given the dimToLvl map, returns if it's block sparsity.
int64_t Size
The type for individual components of a compile-time shape, including the value ShapedType::kDynamic ...
bool hasAnyNonIdentityOperandsOrResults(Operation *op)
Returns true iff MLIR operation has any sparse tensor with non-identity dim2lvl maps.
bool hasAnySparseResult(Operation *op)
Returns true iff MLIR operand has any sparse result.
bool hasAnySparseOperand(Operation *op)
Returns true iff MLIR operand has any sparse operand.
SmallVector< unsigned > getBlockSize(AffineMap dimToLvl)
Given the dimToLvl map, returns the block sizes in a vector.
AffineMap inverseBlockSparsity(AffineMap dimToLvl, MLIRContext *context)
Returns the lvlToDim map for the given dimToLvl map specific to the block sparse cases.
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Definition Utils.cpp:311
A simple structure that encodes a range of levels in the sparse tensors that forms a COO segment.
bool inSegment(Level l) const
bool isSegmentStart(Level l) const
std::pair< Level, Level > lvlRange