tvm
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/registry.h>
36 #include <tvm/ir/cow.h>
37 
38 #include <string>
39 #include <type_traits>
40 #include <unordered_map>
41 #include <utility>
42 
43 namespace tvm {
44 
49 class AttrsNode : public ffi::Object {
50  public:
51  static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind = kTVMFFISEqHashKindTreeNode;
52  TVM_FFI_DECLARE_OBJECT_INFO("ir.Attrs", AttrsNode, ffi::Object);
53 };
54 
59 class Attrs : public ffi::ObjectRef {
60  public:
62 };
63 
70 class DictAttrsNode : public AttrsNode {
71  public:
73  ffi::Map<ffi::String, ffi::Any> dict;
74 
75  static void RegisterReflection() {
76  namespace rfl = ffi::reflection;
77  rfl::ObjectDef<DictAttrsNode>().def_ro("__dict__", &DictAttrsNode::dict);
78  }
79 
80  // type info
82 };
83 
102 class DictAttrs : public Attrs {
103  public:
110  explicit DictAttrs(ffi::Map<ffi::String, Any> dict = {}) {
111  ffi::ObjectPtr<DictAttrsNode> n = ffi::make_object<DictAttrsNode>();
112  n->dict = std::move(dict);
113  data_ = std::move(n);
114  }
115 
121  DictAttrs(DictAttrs&& other) noexcept : Attrs(ffi::UnsafeInit{}) {
122  data_ = std::move(other.data_);
123  other.data_ = ffi::make_object<DictAttrsNode>();
124  }
125 
131  DictAttrs& operator=(DictAttrs&& other) noexcept {
132  if (this != &other) {
133  data_ = std::move(other.data_);
134  other.data_ = ffi::make_object<DictAttrsNode>();
135  }
136  return *this;
137  }
138 
139  // Explicit copy ctor/assign defaults. Declaring the move members above
140  // would otherwise suppress the implicit copy members.
141  DictAttrs(const DictAttrs& other) = default;
142  DictAttrs& operator=(const DictAttrs& other) = default;
143 
144  // Utils for accessing attributes
164  template <typename TObjectRef>
165  ffi::Optional<TObjectRef> GetAttr(
166  const std::string& attr_key,
167  ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt)) const {
168  const DictAttrsNode* node = get();
169  auto it = node->dict.find(attr_key);
170  if (it != node->dict.end()) {
171  return (*it).second.cast<TObjectRef>();
172  } else {
173  return default_value;
174  }
175  }
176  // variant that uses TObjectRef to enable implicit conversion to default value.
177  template <typename TObjectRef>
178  ffi::Optional<TObjectRef> GetAttr(const std::string& attr_key, TObjectRef default_value) const {
179  return GetAttr<TObjectRef>(attr_key, ffi::Optional<TObjectRef>(default_value));
180  }
200  bool HasNonzeroAttr(const std::string& attr_key) const {
201  return GetAttr<int64_t>(attr_key, 0).value_or(0) != 0;
202  }
203 
204  // Inline-expand TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE here, minus
205  // the default copy/move it normally injects (we define our own move members
206  // above so the moved-from instance stays defined-but-empty).
207  explicit DictAttrs(::tvm::ffi::UnsafeInit tag) : Attrs(tag) {}
208  using __PtrType =
209  std::conditional_t<DictAttrsNode::_type_mutable, DictAttrsNode*, const DictAttrsNode*>;
210  __PtrType operator->() const { return static_cast<__PtrType>(data_.get()); }
211  __PtrType get() const { return static_cast<__PtrType>(data_.get()); }
212  static constexpr bool _type_is_nullable = false;
215 };
216 
244 template <typename TFunc>
245 inline TFunc WithAttr(TFunc input, const std::string& attr_key, Any attr_value) {
246  using TNode = typename TFunc::ContainerType;
247  static_assert(TNode::_type_final, "Can only operate on the leaf nodes");
248  TNode* node = input.CopyOnWrite();
249  // node->attrs is NOTNULLABLE by contract, but defend against a caller
250  // that left a moved-from DictAttrs in place by re-initializing here.
251  if (!node->attrs.defined()) node->attrs = DictAttrs();
252  node->attrs.CopyOnWrite()->dict.Set(attr_key, std::move(attr_value));
253  return input;
254 }
255 
266 template <typename TFunc>
267 inline TFunc WithAttrs(TFunc input, ffi::Map<ffi::String, Any> attrs) {
268  using TNode = typename TFunc::ContainerType;
269  static_assert(TNode::_type_final, "Can only operate on the leaf nodes");
270  if (attrs.empty()) return input;
271  TNode* node = input.CopyOnWrite();
272  // node->attrs is NOTNULLABLE by contract, but defend against a caller
273  // that left a moved-from DictAttrs in place by re-initializing here.
274  if (!node->attrs.defined()) node->attrs = DictAttrs();
275  auto* dict_node = node->attrs.CopyOnWrite();
276  for (const auto& [k, v] : attrs) {
277  dict_node->dict.Set(k, v);
278  }
279  return input;
280 }
281 
308 template <typename TFunc>
309 inline TFunc WithoutAttr(TFunc input, const std::string& attr_key) {
310  using TNode = typename TFunc::ContainerType;
311  static_assert(TNode::_type_final, "Can only operate on the leaf nodes");
312  TNode* node = input.CopyOnWrite();
313  // node->attrs is NOTNULLABLE by contract, but defend against a caller
314  // that left a moved-from DictAttrs in place; nothing to erase from an
315  // empty dict.
316  if (!node->attrs.defined()) {
317  node->attrs = DictAttrs();
318  return input;
319  }
320  node->attrs.CopyOnWrite()->dict.erase(attr_key);
321  return input;
322 }
323 
324 } // namespace tvm
325 #endif // TVM_IR_ATTRS_H_
Base class of all attribute class.
Definition: attrs.h:49
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind
Definition: attrs.h:51
TVM_FFI_DECLARE_OBJECT_INFO("ir.Attrs", AttrsNode, ffi::Object)
Managed reference to AttrsNode.
Definition: attrs.h:59
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(Attrs, ffi::ObjectRef, AttrsNode)
Specialized attribute type that is backed by a map. The DictAttrsNode implements the Attrs behavior,...
Definition: attrs.h:70
static void RegisterReflection()
Definition: attrs.h:75
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.DictAttrs", DictAttrsNode, AttrsNode)
ffi::Map< ffi::String, ffi::Any > dict
internal attrs map
Definition: attrs.h:73
Managed reference to DictAttrsNode.
Definition: attrs.h:102
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:200
__PtrType operator->() const
Definition: attrs.h:210
DictAttrs(::tvm::ffi::UnsafeInit tag)
Definition: attrs.h:207
DictAttrs(const DictAttrs &other)=default
std::conditional_t< DictAttrsNode::_type_mutable, DictAttrsNode *, const DictAttrsNode * > __PtrType
Definition: attrs.h:209
DictAttrs(ffi::Map< ffi::String, Any > dict={})
Construct a DictAttrs backed by DictAttrsNode.
Definition: attrs.h:110
DictAttrs(DictAttrs &&other) noexcept
Move constructor that leaves the source in a defined-but-empty state rather than null,...
Definition: attrs.h:121
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:165
DictAttrs & operator=(DictAttrs &&other) noexcept
Move assignment that leaves the source in a defined-but-empty state rather than null,...
Definition: attrs.h:131
__PtrType get() const
Definition: attrs.h:211
TVM_DEFINE_OBJECT_REF_COW_METHOD(DictAttrsNode)
static constexpr bool _type_is_nullable
Definition: attrs.h:212
ffi::Optional< TObjectRef > GetAttr(const std::string &attr_key, TObjectRef default_value) const
Definition: attrs.h:178
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: analyzer.h:40
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:267
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:245
TFunc WithoutAttr(TFunc input, const std::string &attr_key)
Copy the function or module, but removes the specified attribute.
Definition: attrs.h:309