This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new cd88be6c0e [Target] Replace TargetTag with singleton TargetTagRegistry
(#20468)
cd88be6c0e is described below
commit cd88be6c0e8e3a24f230543d155391ea8e37c0f4
Author: Tianqi Chen <[email protected]>
AuthorDate: Sat Sep 26 12:01:13 2026 -0400
[Target] Replace TargetTag with singleton TargetTagRegistry (#20468)
Replace the TargetTag object and AttrRegistry plumbing with a
process-wide TargetTagRegistry that owns tag configurations. This gives
target tags one direct registry API while preserving existing target
construction behavior.
- Register, look up, and list tags through the C++ singleton, with
duplicate protection and explicit override.
- Keep `tvm.target.register_tag` and `list_tags` and their existing FFI
bindings.
- Remove the unused TargetTag wrapper and registration macro.
---
include/tvm/target/tag.h | 173 -------------------------------
include/tvm/target/target_tag_registry.h | 89 ++++++++++++++++
src/target/tag.cc | 85 ---------------
src/target/target.cc | 7 +-
src/target/target_tag_registry.cc | 80 ++++++++++++++
5 files changed, 173 insertions(+), 261 deletions(-)
diff --git a/include/tvm/target/tag.h b/include/tvm/target/tag.h
deleted file mode 100644
index a89e68f7ee..0000000000
--- a/include/tvm/target/tag.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/*!
- * \file tvm/target/tag.h
- * \brief Target tag registry
- */
-#ifndef TVM_TARGET_TAG_H_
-#define TVM_TARGET_TAG_H_
-
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/attr_registry_map.h>
-#include <tvm/target/target.h>
-
-#include <utility>
-
-namespace tvm {
-
-/*! \brief A target tag */
-class TargetTagNode : public ffi::Object {
- public:
- /*! \brief Name of the target */
- ffi::String name;
- /*! \brief Config map to generate the target */
- ffi::Map<ffi::String, Any> config;
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<TargetTagNode>()
- .def_ro("name", &TargetTagNode::name)
- .def_ro("config", &TargetTagNode::config);
- }
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("target.TargetTag", TargetTagNode,
ffi::Object);
-
- private:
- /*! \brief Return the index stored in attr registry */
- uint32_t AttrRegistryIndex() const { return index_; }
- /*! \brief Return the name stored in attr registry */
- ffi::String AttrRegistryName() const { return name; }
- /*! \brief Index used for internal lookup of attribute registry */
- uint32_t index_;
-
- template <typename, typename>
- friend class AttrRegistry;
- template <typename>
- friend class AttrRegistryMapContainerMap;
- friend class TargetTagRegEntry;
-};
-
-/*!
- * \brief Managed reference class to TargetTagNode
- * \sa TargetTagNode
- */
-class TargetTag : public ffi::ObjectRef {
- public:
- /*!
- * \brief Retrieve the Target given it the name of target tag
- * \param target_tag_name Name of the target tag
- * \return The Target requested
- */
- TVM_DLL static ffi::Optional<Target> Get(const ffi::String& target_tag_name);
- /*!
- * \brief List all names of the existing target tags
- * \return A dictionary that maps tag name to the concrete target it
corresponds to
- */
- TVM_DLL static ffi::Map<ffi::String, Target> ListTags();
- /*!
- * \brief Retrieve the raw config dict for a target tag
- * \param target_tag_name Name of the target tag
- * \return The config dict if the tag exists, nullopt otherwise
- */
- TVM_DLL static ffi::Optional<ffi::Map<ffi::String, Any>> GetConfig(
- const ffi::String& target_tag_name);
- /*!
- * \brief Add a tag into the registry
- * \param name Name of the tag
- * \param config The target config corresponding to the tag
- * \param override Allow overriding existing tags
- * \return Target created with the tag
- */
- TVM_DLL static Target AddTag(ffi::String name, ffi::Map<ffi::String, Any>
config, bool override);
-
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TargetTag, ffi::ObjectRef,
TargetTagNode);
-
- private:
- /*! \brief Mutable access to the container class */
- TargetTagNode* operator->() { return
static_cast<TargetTagNode*>(data_.get()); }
- friend class TargetTagRegEntry;
-};
-
-class TargetTagRegEntry {
- public:
- /*!
- * \brief Set the config dict corresponding to the target tag
- * \param config The config dict for target creation
- */
- inline TargetTagRegEntry& set_config(ffi::Map<ffi::String, Any> config);
- /*!
- * \brief Add a key-value pair to the config dict
- * \param key The attribute name
- * \param value The attribute value
- */
- inline TargetTagRegEntry& with_config(ffi::String key, Any value);
- /*! \brief Set name of the TargetTag to be the same as registry if it is
empty */
- inline TargetTagRegEntry& set_name();
- /*!
- * \brief Register or get a new entry.
- * \param target_tag_name The name of the TargetTag.
- * \return the corresponding entry.
- */
- TVM_DLL static TargetTagRegEntry& RegisterOrGet(const ffi::String&
target_tag_name);
-
- private:
- TargetTag tag_;
- ffi::String name;
-
- /*! \brief private constructor */
- explicit TargetTagRegEntry(uint32_t reg_index) :
tag_(ffi::make_object<TargetTagNode>()) {
- tag_->index_ = reg_index;
- }
- template <typename, typename>
- friend class AttrRegistry;
- friend class TargetTag;
-};
-
-inline TargetTagRegEntry& TargetTagRegEntry::set_config(ffi::Map<ffi::String,
Any> config) {
- tag_->config = std::move(config);
- return *this;
-}
-
-inline TargetTagRegEntry& TargetTagRegEntry::with_config(ffi::String key,
ffi::Any value) {
- tag_->config.Set(key, value);
- return *this;
-}
-
-inline TargetTagRegEntry& TargetTagRegEntry::set_name() {
- if (tag_->name.empty()) {
- tag_->name = name;
- }
- return *this;
-}
-
-#define TVM_TARGET_TAG_REGISTER_VAR_DEF \
- [[maybe_unused]] static ::tvm::TargetTagRegEntry& __make_##TargetTag
-
-/*!
- * \def TVM_REGISTER_TARGET_TAG
- * \brief Register a new target tag, or set attribute of the corresponding
target tag.
- * \param TargetTagName The name of target tag
- */
-#define TVM_REGISTER_TARGET_TAG(TargetTagName) \
- TVM_FFI_STR_CONCAT(TVM_TARGET_TAG_REGISTER_VAR_DEF, __COUNTER__) = \
- ::tvm::TargetTagRegEntry::RegisterOrGet(TargetTagName).set_name()
-
-} // namespace tvm
-
-#endif // TVM_TARGET_TAG_H_
diff --git a/include/tvm/target/target_tag_registry.h
b/include/tvm/target/target_tag_registry.h
new file mode 100644
index 0000000000..c6b6ae15cb
--- /dev/null
+++ b/include/tvm/target/target_tag_registry.h
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*!
+ * \file tvm/target/target_tag_registry.h
+ * \brief Process-wide target tag registry.
+ */
+#ifndef TVM_TARGET_TARGET_TAG_REGISTRY_H_
+#define TVM_TARGET_TARGET_TAG_REGISTRY_H_
+
+#include <tvm/ffi/container/dict.h>
+#include <tvm/target/target.h>
+
+namespace tvm {
+
+/*!
+ * \brief Registry of target configurations keyed by tag name.
+ *
+ * Register a tag during static initialization, then resolve it through Target:
+ * \code
+ * TVM_FFI_STATIC_INIT_BLOCK() {
+ * TargetTagRegistry::Global()->AddTag(
+ * "my_cpu", {{"kind", ffi::String("llvm")}}, false);
+ * }
+ * \endcode
+ */
+class TargetTagRegistry {
+ public:
+ using Config = ffi::Map<ffi::String, ffi::Any>;
+
+ /*! \brief Return the process-wide registry. */
+ TVM_DLL static TargetTagRegistry* Global();
+
+ /*!
+ * \brief Construct the target registered under a name.
+ * \param name The tag name to look up.
+ * \return The constructed target, or nullopt if the name is unknown.
+ */
+ TVM_DLL ffi::Optional<Target> Get(const ffi::String& name) const;
+
+ /*!
+ * \brief Return a tag's stored configuration without constructing a target.
+ * \param name The tag name to look up.
+ * \return The configuration, or nullopt if the name is unknown.
+ */
+ TVM_DLL ffi::Optional<Config> GetConfig(const ffi::String& name) const;
+
+ /*!
+ * \brief List all registered names and their constructed targets.
+ * \return A map from tag names to targets; empty if no tags are registered.
+ */
+ TVM_DLL ffi::Map<ffi::String, Target> ListTags() const;
+
+ /*!
+ * \brief Register a target configuration under a tag name.
+ * \param name The tag name to register.
+ * \param config The target configuration, including its kind.
+ * \param override Whether to replace an existing registration; otherwise a
duplicate is rejected.
+ * \return The target constructed from config.
+ */
+ TVM_DLL Target AddTag(ffi::String name, Config config, bool override);
+
+ private:
+ TargetTagRegistry() = default;
+ TargetTagRegistry(const TargetTagRegistry&) = delete;
+ TargetTagRegistry& operator=(const TargetTagRegistry&) = delete;
+
+ ffi::Dict<ffi::String, Config> configs_;
+};
+
+} // namespace tvm
+
+#endif // TVM_TARGET_TARGET_TAG_REGISTRY_H_
diff --git a/src/target/tag.cc b/src/target/tag.cc
deleted file mode 100644
index 74fa65b0e6..0000000000
--- a/src/target/tag.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/*!
- * \file src/target/target_tag.cc
- * \brief Target tag registry
- */
-
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/expr.h>
-#include <tvm/target/tag.h>
-#include <tvm/target/target.h>
-
-#include "../ir/attr_registry.h"
-
-namespace tvm {
-
-TVM_FFI_STATIC_INIT_BLOCK() { TargetTagNode::RegisterReflection(); }
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef()
- .def("target.TargetTagListTags", TargetTag::ListTags)
- .def("target.TargetTagAddTag", TargetTag::AddTag);
-}
-
-/********** Registry-related code **********/
-
-using TargetTagRegistry = AttrRegistry<TargetTagRegEntry, TargetTag>;
-
-TargetTagRegEntry& TargetTagRegEntry::RegisterOrGet(const ffi::String&
target_tag_name) {
- return TargetTagRegistry::Global()->RegisterOrGet(target_tag_name);
-}
-
-ffi::Optional<Target> TargetTag::Get(const ffi::String& target_tag_name) {
- const TargetTagRegEntry* reg =
TargetTagRegistry::Global()->Get(target_tag_name);
- if (reg == nullptr) {
- return std::nullopt;
- }
- return Target(reg->tag_->config);
-}
-
-ffi::Optional<ffi::Map<ffi::String, ffi::Any>> TargetTag::GetConfig(
- const ffi::String& target_tag_name) {
- const TargetTagRegEntry* reg =
TargetTagRegistry::Global()->Get(target_tag_name);
- if (reg == nullptr) {
- return std::nullopt;
- }
- return reg->tag_->config;
-}
-
-ffi::Map<ffi::String, Target> TargetTag::ListTags() {
- ffi::Map<ffi::String, Target> result;
- for (const ffi::String& tag : TargetTagRegistry::Global()->ListAllNames()) {
- result.Set(tag, TargetTag::Get(tag).value());
- }
- return result;
-}
-
-Target TargetTag::AddTag(ffi::String name, ffi::Map<ffi::String, ffi::Any>
config, bool override) {
- TargetTagRegEntry& tag = TargetTagRegEntry::RegisterOrGet(name).set_name();
- TVM_FFI_ICHECK(override || tag.tag_->config.empty())
- << "Tag \"" << name << "\" has been previously defined as: " <<
tag.tag_->config;
- tag.set_config(config);
- return Target(config);
-}
-
-} // namespace tvm
diff --git a/src/target/target.cc b/src/target/target.cc
index b36ba6efb2..138ce256e1 100644
--- a/src/target/target.cc
+++ b/src/target/target.cc
@@ -27,9 +27,9 @@
#include <tvm/ir/transform.h>
#include <tvm/runtime/device_api.h>
#include <tvm/runtime/logging.h>
-#include <tvm/target/tag.h>
#include <tvm/target/target.h>
#include <tvm/target/target_kind.h>
+#include <tvm/target/target_tag_registry.h>
#include <algorithm>
#include <sstream>
@@ -255,7 +255,8 @@ void TargetInternal::ConstructorDispatcher(ffi::PackedArgs
args, ffi::Any* rv) {
ffi::ObjectPtr<TargetNode> TargetInternal::FromString(
const ffi::String& tag_or_config_or_target_str) {
- if (ffi::Optional<Target> target =
TargetTag::Get(tag_or_config_or_target_str)) {
+ if (ffi::Optional<Target> target =
+ TargetTagRegistry::Global()->Get(tag_or_config_or_target_str)) {
Target value = target.value();
return
ffi::details::ObjectUnsafe::ObjectPtrFromObjectRef<TargetNode>(value);
}
@@ -300,7 +301,7 @@ ffi::ObjectPtr<TargetNode>
TargetInternal::FromConfig(ffi::Map<ffi::String, ffi:
auto tag_name = config[kTag].try_cast<ffi::String>();
TVM_FFI_ICHECK(tag_name.has_value())
<< "Expect type of field \"tag\" is String, but get type: " <<
config[kTag].GetTypeKey();
- auto tag_config = TargetTag::GetConfig(tag_name.value());
+ auto tag_config = TargetTagRegistry::Global()->GetConfig(tag_name.value());
TVM_FFI_ICHECK(tag_config.has_value()) << "Unknown target tag: " <<
tag_name.value();
// Start from the tag's base config, then apply user overrides
ffi::Map<ffi::String, ffi::Any> merged = tag_config.value();
diff --git a/src/target/target_tag_registry.cc
b/src/target/target_tag_registry.cc
new file mode 100644
index 0000000000..8609bb7382
--- /dev/null
+++ b/src/target/target_tag_registry.cc
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*!
+ * \file src/target/target_tag_registry.cc
+ * \brief Process-wide target tag registry.
+ */
+
+#include <tvm/ffi/function.h>
+#include <tvm/ffi/reflection/registry.h>
+#include <tvm/target/target_tag_registry.h>
+
+#include <utility>
+
+namespace tvm {
+
+TargetTagRegistry* TargetTagRegistry::Global() {
+ static TargetTagRegistry registry;
+ return ®istry;
+}
+
+ffi::Optional<Target> TargetTagRegistry::Get(const ffi::String& name) const {
+ if (auto config = GetConfig(name)) {
+ return Target(config.value());
+ }
+ return std::nullopt;
+}
+
+ffi::Optional<TargetTagRegistry::Config> TargetTagRegistry::GetConfig(
+ const ffi::String& name) const {
+ if (auto config = configs_.Get(name)) {
+ return config.value();
+ }
+ return std::nullopt;
+}
+
+ffi::Map<ffi::String, Target> TargetTagRegistry::ListTags() const {
+ ffi::Map<ffi::String, Target> result;
+ for (const auto& kv : configs_) {
+ result.Set(kv.first, Target(kv.second));
+ }
+ return result;
+}
+
+Target TargetTagRegistry::AddTag(ffi::String name, Config config, bool
override) {
+ auto previous = configs_.Get(name);
+ TVM_FFI_ICHECK(override || !previous.has_value())
+ << "Tag \"" << name << "\" has been previously defined as: " <<
previous.value();
+ Target target(config);
+ configs_.Set(name, std::move(config));
+ return target;
+}
+
+TVM_FFI_STATIC_INIT_BLOCK() {
+ namespace refl = tvm::ffi::reflection;
+ refl::GlobalDef()
+ .def("target.TargetTagListTags", []() { return
TargetTagRegistry::Global()->ListTags(); })
+ .def("target.TargetTagAddTag", [](ffi::String name,
TargetTagRegistry::Config config,
+ bool override) {
+ return TargetTagRegistry::Global()->AddTag(std::move(name),
std::move(config), override);
+ });
+}
+
+} // namespace tvm