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