tvm
Loading...
Searching...
No Matches
attrs.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 */
28#ifndef TVM_IR_ATTRS_H_
29#define TVM_IR_ATTRS_H_
30
31#include <tvm/ffi/container/map.h>
32#include <tvm/ffi/extra/structural_equal.h>
33#include <tvm/ffi/extra/structural_hash.h>
34#include <tvm/ffi/function.h>
35#include <tvm/ffi/reflection/accessor.h>
36#include <tvm/ffi/reflection/registry.h>
37#include <tvm/ir/cow.h>
38
39#include <string>
40#include <type_traits>
41#include <unordered_map>
42#include <utility>
43
44namespace tvm {
45
50class AttrsNode : public ffi::Object {
51 public:
52 static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind = kTVMFFISEqHashKindTreeNode;
53 TVM_FFI_DECLARE_OBJECT_INFO("ir.Attrs", AttrsNode, ffi::Object);
54};
55
60class Attrs : public ffi::ObjectRef {
61 public:
62 explicit Attrs(ffi::ObjectPtr<AttrsNode> n) : ffi::ObjectRef(ffi::UnsafeInit{}) {
63 TVM_FFI_ICHECK(n != nullptr);
64 data_ = std::move(n);
65 }
66
68};
69
76class DictAttrsNode : public AttrsNode {
77 public:
79 ffi::Map<ffi::String, ffi::Any> dict;
80
81 static void RegisterReflection() {
82 namespace rfl = ffi::reflection;
83 rfl::ObjectDef<DictAttrsNode>().def_ro("__dict__", &DictAttrsNode::dict);
84 }
85
86 // type info
88};
89
108class DictAttrs : public Attrs {
109 public:
116 explicit DictAttrs(ffi::Map<ffi::String, Any> dict = {}) : Attrs(ffi::UnsafeInit{}) {
117 ffi::ObjectPtr<DictAttrsNode> n = ffi::make_object<DictAttrsNode>();
118 n->dict = std::move(dict);
119 data_ = std::move(n);
120 }
121
127 DictAttrs(DictAttrs&& other) noexcept : Attrs(ffi::UnsafeInit{}) {
128 data_ = std::move(other.data_);
129 other.data_ = ffi::make_object<DictAttrsNode>();
130 }
131
137 DictAttrs& operator=(DictAttrs&& other) noexcept {
138 if (this != &other) {
139 data_ = std::move(other.data_);
140 other.data_ = ffi::make_object<DictAttrsNode>();
141 }
142 return *this;
143 }
144
145 // Explicit copy ctor/assign defaults. Declaring the move members above
146 // would otherwise suppress the implicit copy members.
147 DictAttrs(const DictAttrs& other) = default;
148 DictAttrs& operator=(const DictAttrs& other) = default;
149
150 // Utils for accessing attributes
170 template <typename TObjectRef>
171 ffi::Optional<TObjectRef> GetAttr(
172 const std::string& attr_key,
173 ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt)) const {
174 const DictAttrsNode* node = get();
175 auto it = node->dict.find(attr_key);
176 if (it != node->dict.end()) {
177 return (*it).second.cast<TObjectRef>();
178 } else {
179 return default_value;
180 }
181 }
182 // variant that uses TObjectRef to enable implicit conversion to default value.
183 template <typename TObjectRef>
184 ffi::Optional<TObjectRef> GetAttr(const std::string& attr_key, TObjectRef default_value) const {
185 return GetAttr<TObjectRef>(attr_key, ffi::Optional<TObjectRef>(default_value));
186 }
206 bool HasNonzeroAttr(const std::string& attr_key) const {
207 return GetAttr<int64_t>(attr_key, 0).value_or(0) != 0;
208 }
209
210 // Inline-expand TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE here, minus
211 // the default copy/move it normally injects (we define our own move members
212 // above so the moved-from instance stays defined-but-empty).
213 explicit DictAttrs(::tvm::ffi::UnsafeInit tag) : Attrs(tag) {}
214 using __PtrType =
215 std::conditional_t<DictAttrsNode::_type_mutable, DictAttrsNode*, const DictAttrsNode*>;
216 __PtrType operator->() const { return static_cast<__PtrType>(data_.get()); }
217 __PtrType get() const { return static_cast<__PtrType>(data_.get()); }
218 static constexpr bool _type_is_nullable = false;
221};
222
251template <typename TFunc>
252inline TFunc WithAttr(TFunc input, const std::string& attr_key, Any attr_value) {
253 using TNode = typename TFunc::ContainerType;
254 if (!input.unique()) {
255 static ffi::reflection::TypeAttrColumn shallow_copy(ffi::reflection::type_attr::kShallowCopy);
256 ffi::AnyView copy_func = shallow_copy[input->type_index()];
257 TVM_FFI_CHECK(copy_func.type_index() == ffi::TypeIndex::kTVMFFIFunction, TypeError)
258 << "Type " << input->GetTypeKey()
259 << " must register an ffi.Function for __ffi_shallow_copy__";
260 Any copy = copy_func.cast<ffi::Function>()(input);
261 TVM_FFI_CHECK(copy.type_index() == input->type_index() && copy.as<ffi::Object>() != input.get(),
262 TypeError)
263 << "Shallow copy must return a distinct object of type " << input->GetTypeKey();
264 input = std::move(copy).cast<TFunc>();
265 }
266 TNode* node = const_cast<TNode*>(input.operator->());
267 // node->attrs is NOTNULLABLE by contract, but defend against a caller
268 // that left a moved-from DictAttrs in place by re-initializing here.
269 if (!node->attrs.defined()) node->attrs = DictAttrs();
270 node->attrs.CopyOnWrite()->dict.Set(attr_key, std::move(attr_value));
271 return input;
272}
273
285template <typename TFunc>
286inline TFunc WithAttrs(TFunc input, ffi::Map<ffi::String, Any> attrs) {
287 using TNode = typename TFunc::ContainerType;
288 if (attrs.empty()) return input;
289 if (!input.unique()) {
290 static ffi::reflection::TypeAttrColumn shallow_copy(ffi::reflection::type_attr::kShallowCopy);
291 ffi::AnyView copy_func = shallow_copy[input->type_index()];
292 TVM_FFI_CHECK(copy_func.type_index() == ffi::TypeIndex::kTVMFFIFunction, TypeError)
293 << "Type " << input->GetTypeKey()
294 << " must register an ffi.Function for __ffi_shallow_copy__";
295 Any copy = copy_func.cast<ffi::Function>()(input);
296 TVM_FFI_CHECK(copy.type_index() == input->type_index() && copy.as<ffi::Object>() != input.get(),
297 TypeError)
298 << "Shallow copy must return a distinct object of type " << input->GetTypeKey();
299 input = std::move(copy).cast<TFunc>();
300 }
301 TNode* node = const_cast<TNode*>(input.operator->());
302 // node->attrs is NOTNULLABLE by contract, but defend against a caller
303 // that left a moved-from DictAttrs in place by re-initializing here.
304 if (!node->attrs.defined()) node->attrs = DictAttrs();
305 auto* dict_node = node->attrs.CopyOnWrite();
306 for (const auto& [k, v] : attrs) {
307 dict_node->dict.Set(k, v);
308 }
309 return input;
310}
311
339template <typename TFunc>
340inline TFunc WithoutAttr(TFunc input, const std::string& attr_key) {
341 using TNode = typename TFunc::ContainerType;
342 if (!input.unique()) {
343 static ffi::reflection::TypeAttrColumn shallow_copy(ffi::reflection::type_attr::kShallowCopy);
344 ffi::AnyView copy_func = shallow_copy[input->type_index()];
345 TVM_FFI_CHECK(copy_func.type_index() == ffi::TypeIndex::kTVMFFIFunction, TypeError)
346 << "Type " << input->GetTypeKey()
347 << " must register an ffi.Function for __ffi_shallow_copy__";
348 Any copy = copy_func.cast<ffi::Function>()(input);
349 TVM_FFI_CHECK(copy.type_index() == input->type_index() && copy.as<ffi::Object>() != input.get(),
350 TypeError)
351 << "Shallow copy must return a distinct object of type " << input->GetTypeKey();
352 input = std::move(copy).cast<TFunc>();
353 }
354 TNode* node = const_cast<TNode*>(input.operator->());
355 // node->attrs is NOTNULLABLE by contract, but defend against a caller
356 // that left a moved-from DictAttrs in place; nothing to erase from an
357 // empty dict.
358 if (!node->attrs.defined()) {
359 node->attrs = DictAttrs();
360 return input;
361 }
362 node->attrs.CopyOnWrite()->dict.erase(attr_key);
363 return input;
364}
365
366} // namespace tvm
367#endif // TVM_IR_ATTRS_H_
Base class of all attribute class.
Definition attrs.h:50
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind
Definition attrs.h:52
TVM_FFI_DECLARE_OBJECT_INFO("ir.Attrs", AttrsNode, ffi::Object)
Managed reference to AttrsNode.
Definition attrs.h:60
Attrs(ffi::ObjectPtr< AttrsNode > n)
Definition attrs.h:62
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(Attrs, ffi::ObjectRef, AttrsNode)
Specialized attribute type that is backed by a map. The DictAttrsNode implements the Attrs behavior,...
Definition attrs.h:76
static void RegisterReflection()
Definition attrs.h:81
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.DictAttrs", DictAttrsNode, AttrsNode)
ffi::Map< ffi::String, ffi::Any > dict
internal attrs map
Definition attrs.h:79
Managed reference to DictAttrsNode.
Definition attrs.h:108
ffi::Optional< TObjectRef > GetAttr(const std::string &attr_key, ffi::Optional< TObjectRef > default_value=ffi::Optional< TObjectRef >(std::nullopt)) const
Get a function attribute.
Definition attrs.h:171
DictAttrs & operator=(const DictAttrs &other)=default
bool HasNonzeroAttr(const std::string &attr_key) const
Check whether the function has an non-zero integer attr.
Definition attrs.h:206
__PtrType operator->() const
Definition attrs.h:216
DictAttrs(::tvm::ffi::UnsafeInit tag)
Definition attrs.h:213
DictAttrs(const DictAttrs &other)=default
std::conditional_t< DictAttrsNode::_type_mutable, DictAttrsNode *, const DictAttrsNode * > __PtrType
Definition attrs.h:215
ffi::Optional< TObjectRef > GetAttr(const std::string &attr_key, TObjectRef default_value) const
Definition attrs.h:184
DictAttrs(ffi::Map< ffi::String, Any > dict={})
Construct a DictAttrs backed by DictAttrsNode.
Definition attrs.h:116
DictAttrs(DictAttrs &&other) noexcept
Move constructor that leaves the source in a defined-but-empty state rather than null,...
Definition attrs.h:127
DictAttrs & operator=(DictAttrs &&other) noexcept
Move assignment that leaves the source in a defined-but-empty state rather than null,...
Definition attrs.h:137
__PtrType get() const
Definition attrs.h:217
TVM_DEFINE_OBJECT_REF_COW_METHOD(DictAttrsNode)
static constexpr bool _type_is_nullable
Definition attrs.h:218
Copy-on-write helper macro for IR ffi::ObjectRef types.
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition attr.h:23
TFunc WithAttrs(TFunc input, ffi::Map< ffi::String, Any > attrs)
Copy the function or module, but overrides the attributes with the entries from attrs.
Definition attrs.h:286
TFunc WithAttr(TFunc input, const std::string &attr_key, Any attr_value)
Copy the function or module, but overrides the attribute value key with the value.
Definition attrs.h:252
TFunc WithoutAttr(TFunc input, const std::string &attr_key)
Copy the function or module, but removes the specified attribute.
Definition attrs.h:340