tvm
Loading...
Searching...
No Matches
data_layout.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
25#ifndef TVM_S_TIR_DATA_LAYOUT_H_
26#define TVM_S_TIR_DATA_LAYOUT_H_
27
28#include <tvm/ffi/optional.h>
29#include <tvm/ffi/reflection/registry.h>
30#include <tvm/ir/prim/expr.h>
31#include <tvm/ir/prim/op.h>
32#include <tvm/s_tir/iter_var.h>
33
34#include <algorithm>
35#include <sstream>
36#include <string>
37#include <utility>
38#include <vector>
39
40#include "tvm/ir/expr.h"
41
42namespace tvm {
43namespace tirx {
44
45class SLayout;
46
48 public:
49 static const SLayoutAxis& Get(const char name);
50
51 // Get the singleton SLayoutAxis using itvar->var->name
52 static const SLayoutAxis& Get(const s_tir::IterVar& itvar);
53
54 // Get the singleton SLayoutAxis using name[0] (size of name must be 1).
55 static const SLayoutAxis& Get(const std::string& name);
56
57 inline bool IsPrimal() const { return name_ >= 'A' && name_ <= 'Z'; }
58 inline std::string name() const { return std::string(1, name_); }
59
60 // if current axis is primal, switch the axis to its subordinate one,
61 // else switch to the primal.
62 inline const SLayoutAxis& ToDual() const {
63 if (name_ >= 'A' && name_ <= 'Z') {
64 return SLayoutAxis::Get(name_ - 'A' + 'a');
65 } else {
66 return SLayoutAxis::Get(name_ - 'a' + 'A');
67 }
68 }
69
70 // return the primal axis. If it is already primal, return itself.
71 const SLayoutAxis& ToPrimal() const { return IsPrimal() ? *this : ToDual(); }
72
73 // return the subordinate axis. If it is already subordinate, return itself.
74 const SLayoutAxis& ToSubordinate() const { return IsPrimal() ? ToDual() : *this; }
75
76 inline bool operator==(const SLayoutAxis& rhs) const { return name_ == rhs.name_; }
77
78 friend std::ostream& operator<<(std::ostream& os, const SLayoutAxis& l) {
79 os << l.name();
80 return os;
81 }
82
83 private:
84 static const SLayoutAxis UPPER_CASE[];
85 static const SLayoutAxis LOWER_CASE[];
87 SLayoutAxis& operator=(const SLayoutAxis&);
88 explicit SLayoutAxis(const char name) : name_(name) {}
89
90 const char name_;
91};
92
103class SLayoutNode : public ffi::Object {
104 public:
106 ffi::String name;
113 ffi::Array<s_tir::IterVar> axes;
114
115 static void RegisterReflection() {
116 namespace refl = tvm::ffi::reflection;
117 refl::ObjectDef<SLayoutNode>()
118 .def_ro("name", &SLayoutNode::name)
119 .def_ro("axes", &SLayoutNode::axes);
120 }
121 TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.SLayout", SLayoutNode, ffi::Object);
122};
123
128class SLayout : public ffi::ObjectRef {
129 public:
130 explicit SLayout(const ffi::Array<s_tir::IterVar>& axes);
131
133 SLayout(const tvm::ffi::String& name) : SLayout(name.operator std::string()) {} // NOLINT(*)
134
136 SLayout(const char* name) : SLayout(std::string(name)) {} // NOLINT(*)
137
148 TVM_DLL SLayout(const std::string& name, PrimType index_ty = PrimType::Int(32)); // NOLINT(*)
149 TVM_DLL static ffi::Optional<SLayout> Create(const std::string& name,
150 PrimType index_ty = PrimType::Int(32));
151
156 SLayoutNode* operator->() { return static_cast<SLayoutNode*>(get_mutable()); }
157
162 static ffi::Optional<SLayout> Undef() { return std::nullopt; }
163
170 static s_tir::IterVar PackIterVar(ffi::Array<s_tir::IterVar> iters);
171
178 static ffi::Array<s_tir::IterVar> UnpackIterVar(s_tir::IterVar packed_iter);
179
188 ffi::Optional<SLayout> SubLayout(size_t pos, size_t len) const;
189
197 SLayout Split(const SLayoutAxis& axis, size_t target_pos, int32_t factor) const;
198
200 inline size_t ndim() const {
201 if (!defined()) return 0;
202 return operator->()->axes.size();
203 }
204
206 inline size_t ndim_primal() const {
207 if (!defined()) return 0;
208 size_t ct = 0;
209 for (auto px : operator->()->axes) {
210 auto iter_vars = UnpackIterVar(px);
211 for (auto x : iter_vars) {
212 if (SLayoutAxis::Get(x).IsPrimal()) {
213 ct++;
214 }
215 }
216 }
217 return ct;
218 }
219
225 inline ffi::Optional<SLayout> ExpandPrimal(const SLayout& dst_layout) {
226 // 1) Find the axis which are missing in the current layout. Make them the prefix.
227 std::string new_src_layout_str = "";
228 for (auto packed_axis : dst_layout->axes) {
229 auto iter_vars = UnpackIterVar(packed_axis);
230 for (auto dst_axis : iter_vars) {
231 if (SLayoutAxis::Get(dst_axis).IsPrimal()) {
232 if (!this->Contains(SLayoutAxis::Get(dst_axis))) {
233 new_src_layout_str += dst_axis->var->name;
234 }
235 }
236 }
237 }
238 // 2) Now, add the primal axis of the current layout.
239 new_src_layout_str += this->name();
240 return SLayout::Create(new_src_layout_str);
241 }
242
250 inline int32_t IndexOf(const std::string& axis) const {
251 if (!this->defined()) return -1;
252 const auto axes = operator->()->axes;
253 for (size_t i = 0; i < axes.size(); ++i) {
254 if (axes[i]->var->name == axis) return static_cast<int32_t>(i);
255 }
256 return -1;
257 }
258
266 inline int32_t IndexOf(const SLayoutAxis& axis) const { return IndexOf(axis.name()); }
267
275 inline int32_t IndexOf(const s_tir::IterVar& iter) const { return IndexOf(iter->var->name); }
276
284 int32_t FactorOf(const SLayoutAxis& axis) const;
285
291 bool Contains(const SLayoutAxis& axis) const {
292 if (!defined()) return false;
293 for (const s_tir::IterVar packed_var : operator->()->axes) {
294 auto iter_vars = UnpackIterVar(packed_var);
295 for (auto var : iter_vars) {
296 if (var->var->name == axis.name()) {
297 return true;
298 }
299 }
300 }
301 return false;
302 }
303
304 const SLayoutAxis& operator[](int32_t i) const {
305 TVM_FFI_ICHECK(defined()) << "Try to access axis from an undefined layout.";
306 int32_t index = i < 0 ? static_cast<int32_t>(ndim() + i) : i;
307 TVM_FFI_ICHECK(index >= 0 && static_cast<size_t>(index) < ndim()) << "Invalid index " << i;
308 const s_tir::IterVar axis = operator->()->axes[index];
309 return SLayoutAxis::Get(axis);
310 }
311
312 s_tir::IterVar PackedAxisAt(int32_t i) const {
313 TVM_FFI_ICHECK(defined()) << "Try to access axis from an undefined layout.";
314 int32_t index = i < 0 ? static_cast<int32_t>(ndim() + i) : i;
315 TVM_FFI_ICHECK(index >= 0 && static_cast<size_t>(index) < ndim()) << "Invalid index " << i;
316 const s_tir::IterVar axis = operator->()->axes[index];
317 return axis;
318 }
319
321 inline std::string name() const {
322 if (!defined()) return "__undef__";
323 return operator->()->name;
324 }
325
331 inline bool Equals(const SLayout& rhs) const { return name() == rhs.name(); }
332
339 friend std::ostream& operator<<(std::ostream& os, const SLayout& l) {
340 os << l.name();
341 return os;
342 }
343
345};
346
347// Internal node container SBijectiveLayout
348class SBijectiveLayoutNode : public ffi::Object {
349 public:
350 explicit SBijectiveLayoutNode(ffi::UnsafeInit tag) : src_layout(tag), dst_layout(tag) {}
351
353 : src_layout(std::move(src)), dst_layout(std::move(dst)) {}
357 ffi::Array<PrimExpr> index_forward_rule;
359 ffi::Array<PrimExpr> index_backward_rule;
361 ffi::Array<PrimExpr> shape_forward_rule;
363 ffi::Array<PrimExpr> shape_backward_rule;
364
369
370 static void RegisterReflection() {
371 namespace refl = tvm::ffi::reflection;
372 refl::ObjectDef<SBijectiveLayoutNode>()
373 .def_ro("src_layout", &SBijectiveLayoutNode::src_layout)
374 .def_ro("dst_layout", &SBijectiveLayoutNode::dst_layout)
375 .def_ro("index_forward_rule", &SBijectiveLayoutNode::index_forward_rule)
376 .def_ro("index_backward_rule", &SBijectiveLayoutNode::index_backward_rule)
377 .def_ro("shape_forward_rule", &SBijectiveLayoutNode::shape_forward_rule)
378 .def_ro("shape_backward_rule", &SBijectiveLayoutNode::shape_backward_rule);
379 }
380 TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.SBijectiveLayout", SBijectiveLayoutNode, ffi::Object);
381};
382
389class SBijectiveLayout : public ffi::ObjectRef {
390 public:
391 explicit SBijectiveLayout(ffi::UnsafeInit tag, ffi::ObjectPtr<SBijectiveLayoutNode> data)
392 : ffi::ObjectRef(tag) {
393 data_ = std::move(data);
394 }
395
401 TVM_DLL SBijectiveLayout(SLayout src_layout, SLayout dst_layout);
402 TVM_DLL static ffi::Optional<SBijectiveLayout> Create(SLayout src_layout, SLayout dst_layout);
403
404 // Given the source shape, infer the destination shape.
405 TVM_DLL ffi::Array<PrimExpr> ForwardShape(const ffi::Array<PrimExpr>& shape) const;
406 // Given the destination shape, recover the source shape.
407 TVM_DLL ffi::Array<PrimExpr> BackwardShape(const ffi::Array<PrimExpr>& dst_shape) const;
408 // Given the destination indices, infer the destination indices.
409 TVM_DLL ffi::Array<PrimExpr> ForwardIndex(const ffi::Array<PrimExpr>& index) const;
410 // Given the destination indices, recover the source indices.
411 TVM_DLL ffi::Array<PrimExpr> BackwardIndex(const ffi::Array<PrimExpr>& dst_index) const;
412
415};
416
417} // namespace tirx
418} // namespace tvm
419
420#endif // TVM_S_TIR_DATA_LAYOUT_H_
Definition base_expr.h:161
static TVM_TIRX_DLL PrimType Int(int bits, int lanes=1)
Construct a signed integer type with fixed lanes.
Iteration Variable, represents an iteration over an integer interval.
Definition iter_var.h:147
Definition data_layout.h:348
ffi::Array< PrimExpr > index_forward_rule
Describes how source axes can be mapped to the destination axes, e.g., [i0 / 16, i1,...
Definition data_layout.h:357
ffi::Array< PrimExpr > shape_forward_rule
Describes how source shapes can be mapped to the destination shapes.
Definition data_layout.h:361
static void RegisterReflection()
Definition data_layout.h:370
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.SBijectiveLayout", SBijectiveLayoutNode, ffi::Object)
SBijectiveLayoutNode(SLayout src, SLayout dst)
Definition data_layout.h:352
SLayout dst_layout
The destination layout.
Definition data_layout.h:368
SLayout src_layout
The source layout.
Definition data_layout.h:366
ffi::Array< PrimExpr > index_backward_rule
Describes how destination axes can be mapped to the source axes.
Definition data_layout.h:359
ffi::Array< PrimExpr > shape_backward_rule
Describes how destination shapes can be mapped to the source shapes.
Definition data_layout.h:363
SBijectiveLayoutNode(ffi::UnsafeInit tag)
Definition data_layout.h:350
Bijective function mapping for data layout transformation. Given two SLayout, SBijectiveLayout build ...
Definition data_layout.h:389
static ffi::Optional< SBijectiveLayout > Create(SLayout src_layout, SLayout dst_layout)
SBijectiveLayout(SLayout src_layout, SLayout dst_layout)
The constructor.
SBijectiveLayout(ffi::UnsafeInit tag, ffi::ObjectPtr< SBijectiveLayoutNode > data)
Definition data_layout.h:391
ffi::Array< PrimExpr > BackwardIndex(const ffi::Array< PrimExpr > &dst_index) const
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SBijectiveLayout, ffi::ObjectRef, SBijectiveLayoutNode)
ffi::Array< PrimExpr > BackwardShape(const ffi::Array< PrimExpr > &dst_shape) const
ffi::Array< PrimExpr > ForwardIndex(const ffi::Array< PrimExpr > &index) const
ffi::Array< PrimExpr > ForwardShape(const ffi::Array< PrimExpr > &shape) const
Definition data_layout.h:47
static const SLayoutAxis & Get(const char name)
bool IsPrimal() const
Definition data_layout.h:57
static const SLayoutAxis & Get(const s_tir::IterVar &itvar)
static const SLayoutAxis & Get(const std::string &name)
const SLayoutAxis & ToSubordinate() const
Definition data_layout.h:74
friend std::ostream & operator<<(std::ostream &os, const SLayoutAxis &l)
Definition data_layout.h:78
std::string name() const
Definition data_layout.h:58
bool operator==(const SLayoutAxis &rhs) const
Definition data_layout.h:76
const SLayoutAxis & ToDual() const
Definition data_layout.h:62
const SLayoutAxis & ToPrimal() const
Definition data_layout.h:71
SLayout is to describe how data is organized within an N-dimention tensor. It is composed of upper ca...
Definition data_layout.h:103
ffi::Array< s_tir::IterVar > axes
specify each axis of the layout, in which the variable name is the name of the axis....
Definition data_layout.h:113
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.SLayout", SLayoutNode, ffi::Object)
ffi::String name
string representation of layout, "" for scalar.
Definition data_layout.h:106
static void RegisterReflection()
Definition data_layout.h:115
Managed reference to SLayoutNode.
Definition data_layout.h:128
int32_t IndexOf(const std::string &axis) const
return the index of the input axis. If it is not found in the layout or the layout is undefined,...
Definition data_layout.h:250
friend std::ostream & operator<<(std::ostream &os, const SLayout &l)
allow output string of layout to ostream
Definition data_layout.h:339
size_t ndim() const
Definition data_layout.h:200
ffi::Optional< SLayout > ExpandPrimal(const SLayout &dst_layout)
Returns a new layout where the dims have been expanded to match the primal dimensions.
Definition data_layout.h:225
SLayout(const tvm::ffi::String &name)
construct from a string
Definition data_layout.h:133
int32_t IndexOf(const SLayoutAxis &axis) const
return the index of the input axis. If it is not found in the layout or the layout is undefined,...
Definition data_layout.h:266
static s_tir::IterVar PackIterVar(ffi::Array< s_tir::IterVar > iters)
Packs the Given Array of IterVars into a Single s_tir::IterVar. Each s_tir::IterVar in the Array shou...
s_tir::IterVar PackedAxisAt(int32_t i) const
Definition data_layout.h:312
SLayout Split(const SLayoutAxis &axis, size_t target_pos, int32_t factor) const
Split axis by size and put the sub-axis to position target_pos.
std::string name() const
Definition data_layout.h:321
bool Equals(const SLayout &rhs) const
Whether the two layouts are equal.
Definition data_layout.h:331
int32_t IndexOf(const s_tir::IterVar &iter) const
return the index of the input axis. If it is not found in the layout or the layout is undefined,...
Definition data_layout.h:275
SLayout(const char *name)
construct from a string
Definition data_layout.h:136
SLayoutNode * operator->()
access the internal node container
Definition data_layout.h:156
size_t ndim_primal() const
Definition data_layout.h:206
SLayout(const std::string &name, PrimType index_ty=PrimType::Int(32))
construct from a string.
ffi::Optional< SLayout > SubLayout(size_t pos, size_t len) const
Returns a sub-layout which is the portion of the object that starts at dimension pos and spans len di...
bool Contains(const SLayoutAxis &axis) const
Whether the layout contains an axis.
Definition data_layout.h:291
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SLayout, ffi::ObjectRef, SLayoutNode)
static ffi::Array< s_tir::IterVar > UnpackIterVar(s_tir::IterVar packed_iter)
Unpacks a Packed s_tir::IterVar into its constituents.
static ffi::Optional< SLayout > Undef()
Return an undefined layout.
Definition data_layout.h:162
const SLayoutAxis & operator[](int32_t i) const
Definition data_layout.h:304
static ffi::Optional< SLayout > Create(const std::string &name, PrimType index_ty=PrimType::Int(32))
int32_t FactorOf(const SLayoutAxis &axis) const
Get the factor size of the subordinate axis.
SLayout(const ffi::Array< s_tir::IterVar > &axes)
Base expr nodes in TVM.
TIR expressions.
Shared primitive construction and constant helpers.
Axis metadata for schedulable tensor computations.
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition attr.h:23