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 &registry;
+}
+
+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

Reply via email to