28#ifndef TVM_IR_ATTRS_H_
29#define TVM_IR_ATTRS_H_
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>
41#include <unordered_map>
60class Attrs :
public ffi::ObjectRef {
62 explicit Attrs(ffi::ObjectPtr<AttrsNode> n) : ffi::ObjectRef(ffi::UnsafeInit{}) {
63 TVM_FFI_ICHECK(n !=
nullptr);
79 ffi::Map<ffi::String, ffi::Any>
dict;
82 namespace rfl = ffi::reflection;
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);
128 data_ = std::move(other.data_);
129 other.data_ = ffi::make_object<DictAttrsNode>();
138 if (
this != &other) {
139 data_ = std::move(other.data_);
140 other.data_ = ffi::make_object<DictAttrsNode>();
170 template <
typename TObjectRef>
172 const std::string& attr_key,
173 ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt))
const {
175 auto it = node->
dict.find(attr_key);
176 if (it != node->
dict.end()) {
177 return (*it).second.cast<TObjectRef>();
179 return default_value;
183 template <
typename TObjectRef>
184 ffi::Optional<TObjectRef>
GetAttr(
const std::string& attr_key, TObjectRef default_value)
const {
215 std::conditional_t<DictAttrsNode::_type_mutable, DictAttrsNode*, const DictAttrsNode*>;
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(),
263 <<
"Shallow copy must return a distinct object of type " << input->GetTypeKey();
264 input = std::move(copy).cast<TFunc>();
266 TNode* node =
const_cast<TNode*
>(input.operator->());
269 if (!node->attrs.defined()) node->attrs =
DictAttrs();
270 node->attrs.CopyOnWrite()->dict.Set(attr_key, std::move(attr_value));
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(),
298 <<
"Shallow copy must return a distinct object of type " << input->GetTypeKey();
299 input = std::move(copy).cast<TFunc>();
301 TNode* node =
const_cast<TNode*
>(input.operator->());
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);
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(),
351 <<
"Shallow copy must return a distinct object of type " << input->GetTypeKey();
352 input = std::move(copy).cast<TFunc>();
354 TNode* node =
const_cast<TNode*
>(input.operator->());
358 if (!node->attrs.defined()) {
362 node->attrs.CopyOnWrite()->dict.erase(attr_key);
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