This is an automated email from the ASF dual-hosted git repository.
tlopex 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 74f401fc1a [REFACTOR][IR] Cleanup IR naming utilities (#19781)
74f401fc1a is described below
commit 74f401fc1a1ac48728c1404b31a6f3895499a89d
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Jun 15 16:57:57 2026 -0400
[REFACTOR][IR] Cleanup IR naming utilities (#19781)
IR module cleanup benefits from using a single unique-name primitive
directly at module call sites. This PR renames NameSupply to
UniqueNameSupply and removes redundant wrappers around global variable
naming.
Main changes:
- Rename the public name supply API and header to UniqueNameSupply
- Replace GlobalVarSupply with direct iterator-seeded UniqueNameSupply
usage
- Remove obsolete access-path repr registration now covered by tvm-ffi
---
include/tvm/ir/global_var_supply.h | 128 ----------------
include/tvm/ir/name_supply.h | 169 ---------------------
include/tvm/ir/unique_name_supply.h | 143 +++++++++++++++++
include/tvm/relax/binding_rewrite.h | 4 +-
include/tvm/relax/block_builder.h | 8 +-
python/tvm/ir/supply.py | 97 ++----------
python/tvm/relax/frontend/onnx/onnx_frontend.py | 4 +-
python/tvm/runtime/__init__.py | 2 +-
python/tvm/runtime/_ffi_node_api.py | 5 +-
src/ir/access_path_repr.cc | 49 ------
src/ir/global_var_supply.cc | 111 --------------
src/ir/module.cc | 12 +-
src/ir/name_supply.cc | 108 -------------
src/ir/unique_name_supply.cc | 114 ++++++++++++++
src/relax/backend/contrib/cutlass/codegen.cc | 6 +-
src/relax/ir/binding_rewrite.cc | 4 +-
src/relax/ir/block_builder.cc | 6 +-
src/relax/ir/dataflow_expr_rewriter.cc | 2 +-
src/relax/transform/allocate_workspace.cc | 4 +-
src/relax/transform/normalize.cc | 2 +-
src/target/source/codegen_c.cc | 2 +-
src/target/source/codegen_c.h | 4 +-
src/target/source/codegen_source_base.cc | 2 +-
src/target/source/codegen_source_base.h | 6 +-
src/te/operation/create_primfunc.cc | 6 +-
src/tirx/ir/index_map.cc | 4 +-
src/tirx/transform/bind_target.cc | 7 +-
src/tirx/transform/split_host_device.cc | 9 +-
...t_name_supply.py => test_unique_name_supply.py} | 27 +++-
29 files changed, 347 insertions(+), 698 deletions(-)
diff --git a/include/tvm/ir/global_var_supply.h
b/include/tvm/ir/global_var_supply.h
deleted file mode 100644
index 2241385167..0000000000
--- a/include/tvm/ir/global_var_supply.h
+++ /dev/null
@@ -1,128 +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/ir/global_var_supply.h
- * \brief GlobalVarSupply that can be used to generate unique \class GlobalVar.
- */
-#ifndef TVM_IR_GLOBAL_VAR_SUPPLY_H_
-#define TVM_IR_GLOBAL_VAR_SUPPLY_H_
-
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/expr.h>
-#include <tvm/ir/module.h>
-#include <tvm/ir/name_supply.h>
-
-#include <string>
-#include <unordered_map>
-
-namespace tvm {
-
-/*!
- * \brief GlobalVarSupply can be used to generate unique GlobalVars.
- */
-class GlobalVarSupplyNode : public ffi::Object {
- public:
- /*!
- * \brief Empty constructor. Will use an empty NameSupply.
- */
- GlobalVarSupplyNode() : GlobalVarSupplyNode(NameSupply()) {}
-
- /*!
- * \brief Constructor.
- * \param name_supply The NameSupply to use for generating the names of
fresh GlobalVars.
- * \param name_to_var_map An optional map.
- */
- explicit GlobalVarSupplyNode(NameSupply name_supply,
- std::unordered_map<std::string, GlobalVar>
name_to_var_map = {});
-
- /*!
- * \brief Generates a unique GlobalVar from this supply.
- * \param name The name from which the name of the GlobalVar is derived.
- * \param add_prefix If set to true, then the prefix of the contained
NameSupply will be prepended
- * to the name. \return A unique GlobalVar.
- */
- GlobalVar FreshGlobal(ffi::String name, bool add_prefix = true);
-
- /*!
- * \brief Looks up for a GlobalVar with the given name in this supply.
- * If no entry is found, creates one, places it in the cache and returns it.
- * \param name The name of the GlobalVar to search for.
- * \param add_prefix If set to true, the prefix of the contained NameSupply
will be prepended to
- * the name before performing the search. \return A cached GlobalVar.
- */
- GlobalVar UniqueGlobalFor(const ffi::String& name, bool add_prefix = true);
-
- /*!
- * \brief Reserves an existing GlobalVar with this supply.
- * \param var The GlobalVar to be registered.
- * \param allow_conflict Allow conflict with other GlobalVars that have the
same name.
- */
- void ReserveGlobalVar(const GlobalVar& var, bool allow_conflict = false);
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<GlobalVarSupplyNode>();
- }
-
- /*! \brief The NameSupply used to generate unique name hints to GlobalVars.
*/
- NameSupply name_supply_;
-
- static constexpr const bool _type_mutable = true;
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.GlobalVarSupply", GlobalVarSupplyNode,
ffi::Object);
-
- private:
- std::unordered_map<std::string, GlobalVar> name_to_var_map_;
-};
-
-/*!
- * \brief Managed reference class to GlobalVarSupplyNode.
- * \sa GlobalVarSupplyNode
- */
-class GlobalVarSupply : public ffi::ObjectRef {
- public:
- /*!
- * \brief Constructor.
- * \param name_supply The NameSupply to be used when generating new
GlobalVars.
- * \param name_to_var_map An optional map.
- */
- TVM_DLL explicit GlobalVarSupply(const NameSupply& name_supply =
NameSupply(),
- std::unordered_map<std::string, GlobalVar>
name_to_var_map = {});
-
- /*!
- * \brief Constructs a supply from an array of IRModules. GlobalVars
generated by this supply are
- * guaranteed not to conflict with any GlobalVars that belong to the
modules. \param modules Array
- * of IRModules.
- */
- TVM_DLL explicit GlobalVarSupply(const ffi::Array<IRModule>& modules);
-
- /*!
- * \brief Constructs a GlobalVarSupply from an IRModule. GlobalVars
generated by this supply are
- * guaranteed not to conflict with GlobalVars that belong to the modules.
\param module The
- * IRModule.
- */
- TVM_DLL explicit GlobalVarSupply(const IRModule module);
-
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(GlobalVarSupply,
ffi::ObjectRef,
- GlobalVarSupplyNode);
-};
-
-} // namespace tvm
-
-#endif // TVM_IR_GLOBAL_VAR_SUPPLY_H_
diff --git a/include/tvm/ir/name_supply.h b/include/tvm/ir/name_supply.h
deleted file mode 100644
index 54bac2afc3..0000000000
--- a/include/tvm/ir/name_supply.h
+++ /dev/null
@@ -1,169 +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/ir/name_supply.h
- * \brief NameSupply that can be used to generate unique variable names.
- */
-#ifndef TVM_IR_NAME_SUPPLY_H_
-#define TVM_IR_NAME_SUPPLY_H_
-
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/expr.h>
-
-#include <algorithm>
-#include <cctype>
-#include <string>
-#include <unordered_map>
-#include <utility>
-
-namespace tvm {
-
-/*!
- * \brief NameSupply can be used to generate unique names.
- */
-class NameSupplyNode : public ffi::Object {
- public:
- /*!
- * \brief Empty constructor. Needed by the TVM_REGISTER_NODE_TYPE macro.
- */
- NameSupplyNode() = default;
-
- /*!
- * \brief Constructor.
- * \param prefix The prefix to be used with this NameSupply.
- * \param name_map The map used to guarantee uniqueness.
- */
- NameSupplyNode(const ffi::String& prefix, std::unordered_map<std::string,
int> name_map)
- : prefix_(prefix), name_map(std::move(name_map)) {}
-
- /*!
- * \brief Generates a unique name from this NameSupply.
- * \param name The name from which the generated name is derived.
- * \param add_prefix If set to true, then the prefix of this NameSupply will
be prepended to the
- * name.
- * \param add_underscore If set to true, add '_' between prefix and a digit.
- * \return A unique name.
- */
- ffi::String FreshName(const ffi::String& name, bool add_prefix = true,
- bool add_underscore = true);
-
- /*!
- * \brief Reserves an existing name with this NameSupply.
- * \param name The name to be reserved.
- * \param add_prefix If set to true, then the prefix of this NameSupply will
be prepended to the
- * name before reserving it. \return The name that was reserved with the
NameSupply. It can be
- * different if a prefix is added.
- */
- ffi::String ReserveName(const ffi::String& name, bool add_prefix = true);
-
- /*!
- * \brief Checks if this NameSupply already generated a name.
- * \param name The name to check.
- * \param add_prefix If set to true, then the prefix of this NameSupply will
be prepended to the
- * name before checking for it. \return True if the name has already been
generated. False
- * otherwise.
- */
- bool ContainsName(const ffi::String& name, bool add_prefix = true);
-
- // Prefix for all GlobalVar names. It can be empty.
- std::string prefix_;
-
- static constexpr const bool _type_mutable = true;
-
- static void RegisterReflection() {
- namespace refl = tvm::ffi::reflection;
- refl::ObjectDef<NameSupplyNode>();
- }
-
- TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.NameSupply", NameSupplyNode,
ffi::Object);
-
- private:
- /*! \brief Helper function to add the NameSupply prefix to the name. */
- ffi::String add_prefix_to_name(const ffi::String& name);
-
- /*!
- * \brief Function that will generate a unique name.
- * \param name The name to be used as a base.
- * \param add_underscore If set to true, add '_' between prefix and a digit.
- * \return A unique name.
- */
- std::string GetUniqueName(std::string name, bool add_underscore = true);
-
- /*! \brief A map that is used to generate unique names. */
- std::unordered_map<std::string, int> name_map;
-};
-
-/*!
- * \brief Managed reference class to NameSupplyNode.
- * \sa NameSupplyNode
- */
-class NameSupply : public ffi::ObjectRef {
- public:
- /*!
- * \brief Constructor.
- * \param prefix The prefix to be used with this NameSupply.
- * \param name_map An optional map.
- */
- TVM_DLL explicit NameSupply(const ffi::String& prefix = "",
- std::unordered_map<std::string, int> name_map =
{});
-
- /*!
- * \brief Construct NameSupply with a name map created from the given
iterator range and
- * the functor.
- *
- * The functor should return the name of the dereferenced object.
- */
- template <typename Iter, typename Lambda>
- TVM_DLL explicit NameSupply(Iter begin, Iter end, Lambda f)
- : NameSupply("", GetNameMap(begin, end, f)) {}
-
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(NameSupply, ffi::ObjectRef,
NameSupplyNode);
-
- private:
- template <typename Iter, typename Lambda>
- static std::unordered_map<std::string, int> GetNameMap(Iter begin, Iter end,
Lambda f) {
- // static_assert is more reader-friendly than SFINAE when template
specialization is not needed.
- static_assert(std::is_convertible<decltype(f(*begin)), std::string>::value,
- "Lambda f must has a signature of [?](*it) -> string {}");
- std::unordered_map<std::string, int> name_map;
- for (auto it = begin; it != end; ++it) {
- const std::string& name = f(*it);
- const size_t idx_last_first_num = std::distance(
- std::find_if(name.rbegin(), name.rend(), [](char c) { return
!std::isdigit(c); }),
- name.rend());
- // name = {O = others}{D = consecutive digits}
- // let O -> prefix;
- std::string prefix = name.substr(0, idx_last_first_num);
- TVM_FFI_ICHECK(prefix.size() > 0 && std::isalpha(prefix[0]))
- << "Invalid variable name: " << name;
- if (0 == name_map.count(prefix)) name_map[prefix] = 0;
- if (idx_last_first_num < name.size()) { // has some digits.
- // let D's nearest natural
number -> idx;
- // note: stoul("000123") = 123;
- name_map[prefix] = std::max(name_map[prefix],
std::stoi(name.substr(idx_last_first_num)));
- }
- }
- return name_map;
- }
-};
-
-} // namespace tvm
-
-#endif // TVM_IR_NAME_SUPPLY_H_
diff --git a/include/tvm/ir/unique_name_supply.h
b/include/tvm/ir/unique_name_supply.h
new file mode 100644
index 0000000000..0f79318d1d
--- /dev/null
+++ b/include/tvm/ir/unique_name_supply.h
@@ -0,0 +1,143 @@
+/*
+ * 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/ir/unique_name_supply.h
+ * \brief UniqueNameSupply that can be used to generate unique variable names.
+ */
+#ifndef TVM_IR_UNIQUE_NAME_SUPPLY_H_
+#define TVM_IR_UNIQUE_NAME_SUPPLY_H_
+
+#include <tvm/ffi/reflection/registry.h>
+#include <tvm/ir/expr.h>
+
+#include <cstdint>
+#include <string>
+#include <utility>
+
+namespace tvm {
+
+/*!
+ * \brief UniqueNameSupply can be used to generate unique names.
+ */
+class UniqueNameSupplyNode : public ffi::Object {
+ public:
+ /*!
+ * \brief Empty constructor. Needed by the TVM_REGISTER_NODE_TYPE macro.
+ */
+ UniqueNameSupplyNode() = default;
+
+ /*!
+ * \brief Constructor.
+ * \param prefix The prefix to be used with this UniqueNameSupply.
+ * \param name_map The map used to guarantee uniqueness.
+ */
+ UniqueNameSupplyNode(const ffi::String& prefix, ffi::Map<ffi::String,
int64_t> name_map)
+ : prefix_(prefix), name_map(std::move(name_map)) {}
+
+ /*!
+ * \brief Generates a unique name from this UniqueNameSupply.
+ * \param name The name from which the generated name is derived.
+ * \param add_prefix If set to true, then the prefix of this
UniqueNameSupply will be prepended to
+ * the name.
+ * \param add_underscore If set to true, add '_' between prefix and a digit.
+ * \return A unique name.
+ */
+ ffi::String FreshName(const ffi::String& name, bool add_prefix = true,
+ bool add_underscore = true);
+
+ /*!
+ * \brief Reserves an existing name with this UniqueNameSupply.
+ * \param name The name to be reserved.
+ * \param add_prefix If set to true, then the prefix of this
UniqueNameSupply will be prepended to
+ * the name before reserving it. \return The name that was reserved with the
UniqueNameSupply. It
+ * can be different if a prefix is added.
+ */
+ ffi::String ReserveName(const ffi::String& name, bool add_prefix = true);
+
+ /*!
+ * \brief Checks if this UniqueNameSupply already generated a name.
+ * \param name The name to check.
+ * \param add_prefix If set to true, then the prefix of this
UniqueNameSupply will be prepended to
+ * the name before checking for it. \return True if the name has already
been generated. False
+ * otherwise.
+ */
+ bool ContainsName(const ffi::String& name, bool add_prefix = true);
+
+ // Prefix for all GlobalVar names. It can be empty.
+ std::string prefix_;
+
+ static constexpr const bool _type_mutable = true;
+
+ static void RegisterReflection() {
+ namespace refl = tvm::ffi::reflection;
+ refl::ObjectDef<UniqueNameSupplyNode>();
+ }
+
+ TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.UniqueNameSupply",
UniqueNameSupplyNode, ffi::Object);
+
+ private:
+ /*! \brief Helper function to add the UniqueNameSupply prefix to the name. */
+ ffi::String AddPrefixToName(const ffi::String& name);
+
+ /*!
+ * \brief Function that will generate a unique name.
+ * \param name The name to be used as a base.
+ * \param add_underscore If set to true, add '_' between prefix and a digit.
+ * \return A unique name.
+ */
+ std::string GetUniqueName(std::string name, bool add_underscore = true);
+
+ /*! \brief A map that is used to generate unique names. */
+ ffi::Map<ffi::String, int64_t> name_map;
+};
+
+/*!
+ * \brief Managed reference class to UniqueNameSupplyNode.
+ * \sa UniqueNameSupplyNode
+ */
+class UniqueNameSupply : public ffi::ObjectRef {
+ public:
+ /*!
+ * \brief Constructor.
+ * \param prefix The prefix to be used with this UniqueNameSupply.
+ * \param name_map An optional map.
+ */
+ TVM_DLL explicit UniqueNameSupply(const ffi::String& prefix = "",
+ ffi::Map<ffi::String, int64_t> name_map =
{});
+
+ /*!
+ * \brief Construct UniqueNameSupply by reserving names from the given
iterator range.
+ *
+ * The functor should return the name of the dereferenced object.
+ */
+ template <typename Iter, typename Lambda>
+ TVM_DLL UniqueNameSupply(Iter begin, Iter end, Lambda f) :
UniqueNameSupply("") {
+ for (auto it = begin; it != end; ++it) {
+ this->operator->()->ReserveName(f(*it), false);
+ }
+ }
+
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(UniqueNameSupply,
ffi::ObjectRef,
+ UniqueNameSupplyNode);
+};
+
+} // namespace tvm
+
+#endif // TVM_IR_UNIQUE_NAME_SUPPLY_H_
diff --git a/include/tvm/relax/binding_rewrite.h
b/include/tvm/relax/binding_rewrite.h
index 69092726b4..740e8ed01f 100644
--- a/include/tvm/relax/binding_rewrite.h
+++ b/include/tvm/relax/binding_rewrite.h
@@ -25,7 +25,7 @@
#ifndef TVM_RELAX_BINDING_REWRITE_H_
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/relax/analysis.h>
#include <tvm/relax/expr.h>
@@ -87,7 +87,7 @@ class DataflowBlockRewriteNode : public ffi::Object {
ffi::Array<Var> fn_outputs_; //!< Variables required by
function outputs.
private:
- NameSupply name_supply_; //!< Name supply for tracking and generating
unique names.
+ UniqueNameSupply name_supply_; //!< Unique name supply for tracking and
generating unique names.
};
/*!
diff --git a/include/tvm/relax/block_builder.h
b/include/tvm/relax/block_builder.h
index 68d6fc7bfa..8413686dc9 100644
--- a/include/tvm/relax/block_builder.h
+++ b/include/tvm/relax/block_builder.h
@@ -25,7 +25,7 @@
#define TVM_RELAX_BLOCK_BUILDER_H_
#include <tvm/arith/analyzer.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/relax/expr.h>
#include <tvm/relax/utils.h>
#include <tvm/runtime/base.h>
@@ -68,11 +68,11 @@ class BlockBuilderNode : public ffi::Object {
// Global Context management
//-------------------------------
/*!
- * \brief Get the name supply for generating unique names.
+ * \brief Get the unique name supply for generating unique names.
*
- * \return The name supply.
+ * \return The unique name supply.
*/
- virtual NameSupply name_supply() = 0;
+ virtual UniqueNameSupply name_supply() = 0;
/*!
* \brief Get the context IRModule in this builder.
diff --git a/python/tvm/ir/supply.py b/python/tvm/ir/supply.py
index 183e20f257..07b91e1a86 100644
--- a/python/tvm/ir/supply.py
+++ b/python/tvm/ir/supply.py
@@ -14,18 +14,18 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-"""Suppliers that are used to guarantee uniqueness of names and GlobalVars."""
+"""Suppliers that are used to guarantee uniqueness of names."""
import tvm_ffi
-from tvm import IRModule, Object
+from tvm import Object
from . import _ffi_api
-@tvm_ffi.register_object("ir.NameSupply")
-class NameSupply(Object):
- """NameSupply that can be used to generate unique names.
+@tvm_ffi.register_object("ir.UniqueNameSupply")
+class UniqueNameSupply(Object):
+ """UniqueNameSupply that can be used to generate unique names.
Parameters
----------
@@ -33,10 +33,10 @@ class NameSupply(Object):
"""
def __init__(self, prefix=""):
- self.__init_handle_by_constructor__(_ffi_api.NameSupply, prefix)
+ self.__init_handle_by_constructor__(_ffi_api.UniqueNameSupply, prefix)
def fresh_name(self, name, add_prefix=True, add_underscore=True):
- """Generates a unique name from this NameSupply.
+ """Generates a unique name from this UniqueNameSupply.
Parameters
----------
@@ -44,15 +44,15 @@ class NameSupply(Object):
The name from which the generated name is derived.
add_prefix: bool
- If set to true, then the prefix of this NameSupply will be
prepended to the name.
+ If set to true, then the prefix of this UniqueNameSupply will be
prepended to the name.
add_underscore: bool
If set to True, adds '_' between prefix and digit.
"""
- return _ffi_api.NameSupply_FreshName(self, name, add_prefix,
add_underscore)
+ return _ffi_api.UniqueNameSupply_FreshName(self, name, add_prefix,
add_underscore)
def reserve_name(self, name, add_prefix=True):
- """Reserves an existing name with this NameSupply.
+ """Reserves an existing name with this UniqueNameSupply.
Parameters
----------
@@ -60,13 +60,13 @@ class NameSupply(Object):
The name to be reserved.
add_prefix: bool
- If set to true, then the prefix of this NameSupply will be
prepended to the name
+ If set to true, then the prefix of this UniqueNameSupply will be
prepended to the name
before reserving it.
"""
- return _ffi_api.NameSupply_ReserveName(self, name, add_prefix)
+ return _ffi_api.UniqueNameSupply_ReserveName(self, name, add_prefix)
def contains_name(self, name, add_prefix=True):
- """Checks if this NameSupply already generated a name.
+ """Checks if this UniqueNameSupply already generated a name.
Parameters
----------
@@ -74,74 +74,7 @@ class NameSupply(Object):
The name to check.
add_prefix: bool
- If set to true, then the prefix of this NameSupply will be
prepended to the name
+ If set to true, then the prefix of this UniqueNameSupply will be
prepended to the name
before checking for it.
"""
- return _ffi_api.NameSupply_ContainsName(self, name, add_prefix)
-
-
-@tvm_ffi.register_object("ir.GlobalVarSupply")
-class GlobalVarSupply(Object):
- """GlobalVarSupply that holds a mapping between names and GlobalVars.
-
- GlobalVarSupply can be used to generate new GlobalVars with a unique name.
- It also can be used to retrieve previously generated GlobalVars based on a
name.
-
- Parameters
- ----------
- value: Union[List[IRModule], IRModule, NameSupply]
- The IRModules used to build this GlobalVarSupply or a NameSupply.
- """
-
- def __init__(self, value=None):
- if value is None:
- name_supply = NameSupply("")
-
self.__init_handle_by_constructor__(_ffi_api.GlobalVarSupply_NameSupply,
name_supply)
- elif isinstance(value, NameSupply):
-
self.__init_handle_by_constructor__(_ffi_api.GlobalVarSupply_NameSupply, value)
- elif isinstance(value, list | tvm_ffi.Array):
-
self.__init_handle_by_constructor__(_ffi_api.GlobalVarSupply_IRModules, value)
- elif isinstance(value, IRModule):
-
self.__init_handle_by_constructor__(_ffi_api.GlobalVarSupply_IRModule, value)
-
- def fresh_global(self, name, add_prefix=True):
- """Generates a unique GlobalVar from this supply.
-
- Parameters
- ----------
- name: String
- The name from which the name of the GlobalVar is derived.
-
- add_prefix: bool
- If set to true, then the prefix of the contained NameSupply will
be prepended
- to the name.
- """
- return _ffi_api.GlobalVarSupply_FreshGlobal(self, name, add_prefix)
-
- def unique_global_for(self, name, add_prefix=True):
- """Looks up for a GlobalVar with the given name in this supply. If no
entry is found
- , creates one, places it in the cache and returns it.
-
- Parameters
- ----------
- name: String
- The name of the GlobalVar to search for.
-
- add_prefix: bool
- If set to true, the prefix of the contained NameSupply will be
prepended to the
- name before performing the search.
- """
- return _ffi_api.GlobalVarSupply_UniqueGlobalFor(self, name, add_prefix)
-
- def reserve_global(self, global_var, allow_conflict=False):
- """Reserves an existing GlobalVar with this supply.
-
- Parameters
- ----------
- global_var: GlobalVar
- The GlobalVar to be registered.
-
- allow_conflict: bool
- Allow conflict with other GlobalVars that have the same name
- """
- return _ffi_api.GlobalVarSupply_ReserveGlobalVar(self, global_var,
allow_conflict)
+ return _ffi_api.UniqueNameSupply_ContainsName(self, name, add_prefix)
diff --git a/python/tvm/relax/frontend/onnx/onnx_frontend.py
b/python/tvm/relax/frontend/onnx/onnx_frontend.py
index 2d1cc47377..11485659fb 100644
--- a/python/tvm/relax/frontend/onnx/onnx_frontend.py
+++ b/python/tvm/relax/frontend/onnx/onnx_frontend.py
@@ -59,7 +59,7 @@ import tvm_ffi
import tvm
from tvm import relax, tirx, topi
from tvm.ir import IRModule
-from tvm.ir.supply import NameSupply
+from tvm.ir.supply import UniqueNameSupply
from tvm.runtime import DataType, DataTypeCode
from tvm.tirx.generic import cast
from tvm.topi.utils import get_const_tuple
@@ -5359,7 +5359,7 @@ class ONNXGraphImporter:
self._input_names: list[str] = []
self._dtype = dtype_dict
self.opset: int = None
- self._name_supply = NameSupply()
+ self._name_supply = UniqueNameSupply()
self._keep_params_in_input = keep_params_in_input
self._sanitize: bool = sanitize
self.bb: relax.BlockBuilder = relax.BlockBuilder() # pylint:
disable=invalid-name
diff --git a/python/tvm/runtime/__init__.py b/python/tvm/runtime/__init__.py
index ee5f3e1dd4..c51cb05dc4 100644
--- a/python/tvm/runtime/__init__.py
+++ b/python/tvm/runtime/__init__.py
@@ -21,7 +21,7 @@ from tvm_ffi import convert, Object
from tvm_ffi._dtype import dtype as DataType, DataTypeCode
# Import _ffi_node_api for its side effect of installing AsRepr as
-# tvm_ffi.core.__object_repr__ so TVM IR objects use the rich C++ ReprPrinter.
+# tvm_ffi.core.__object_repr__.
from . import _ffi_node_api
# class exposures
diff --git a/python/tvm/runtime/_ffi_node_api.py
b/python/tvm/runtime/_ffi_node_api.py
index 18af61ec75..1c87b989b6 100644
--- a/python/tvm/runtime/_ffi_node_api.py
+++ b/python/tvm/runtime/_ffi_node_api.py
@@ -40,8 +40,5 @@ def LoadJSON(json_str):
# Exports functions registered in node namespace.
tvm_ffi.init_ffi_api("node", __name__)
-# Override the default repr function for tvm_ffi.core.Object so TVM IR
-# objects use the rich C++ ReprPrinter (registered above via init_ffi_api),
-# falling back to the runtime-only AsRepr defined in this file when libtvm.so
-# is not available.
+# Override the default repr function for tvm_ffi.core.Object.
tvm_ffi.core.__object_repr__ = AsRepr
diff --git a/src/ir/access_path_repr.cc b/src/ir/access_path_repr.cc
deleted file mode 100644
index 8225452c54..0000000000
--- a/src/ir/access_path_repr.cc
+++ /dev/null
@@ -1,49 +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 ir/access_path_repr.cc
- * \brief FFI registration for ffi-repr-based printing.
- *
- * This file:
- * - Registers node.AsRepr (for backward Python compatibility) via
ffi::ReprPrint.
- *
- * Note: __ffi_repr__ hooks for ffi::reflection::AccessPath and AccessStep are
- * registered by tvm-ffi itself (src/ffi/extra/reflection_extra.cc, landed in
- * apache/tvm-ffi#598). The duplicate registrations that previously lived here
- * were removed when bumping tvm-ffi to 59da4c0 to avoid a double-registration
- * abort at library load time.
- *
- * Note: tvm::Dump() has been removed (zero in-tree callers). Use
- * tvm::ffi::ReprPrint(any) directly from gdb instead.
- */
-#include <tvm/ffi/extra/dataclass.h>
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-
-namespace tvm {
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- // node.AsRepr: backward-compatible Python entry point.
- // Python's tvm.runtime._ffi_node_api sets __object_repr__ = AsRepr via
init_ffi_api.
- refl::GlobalDef().def("node.AsRepr",
- [](ffi::Any obj) -> ffi::String { return
ffi::ReprPrint(obj); });
-}
-} // namespace tvm
diff --git a/src/ir/global_var_supply.cc b/src/ir/global_var_supply.cc
deleted file mode 100644
index 700c3ef840..0000000000
--- a/src/ir/global_var_supply.cc
+++ /dev/null
@@ -1,111 +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 global_var_supply.cc
- * \brief GlobalVarSupply that can be used to generate unique GlobalVars.
- */
-#include "tvm/ir/global_var_supply.h"
-
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-
-#include <utility>
-
-#include "tvm/ir/expr.h"
-
-namespace tvm {
-
-TVM_FFI_STATIC_INIT_BLOCK() { GlobalVarSupplyNode::RegisterReflection(); }
-
-GlobalVarSupply::GlobalVarSupply(const NameSupply& name_supply,
- std::unordered_map<std::string, GlobalVar>
name_to_var_map) {
- auto n = ffi::make_object<GlobalVarSupplyNode>(name_supply, name_to_var_map);
- data_ = std::move(n);
-}
-
-std::string GetModuleName(const IRModule& module) {
- return
module->GetAttr<ffi::String>(tvm::attr::kModuleName).value_or("tvmgen_default");
-}
-
-GlobalVarSupply::GlobalVarSupply(const ffi::Array<IRModule>& modules) :
GlobalVarSupply() {
- if (!modules.empty()) {
- IRModule first_mod = modules.front();
- this->operator->()->name_supply_->prefix_ = GetModuleName(first_mod);
- }
- for (auto& mod : modules) {
- for (auto kv : mod->functions) {
- this->operator->()->ReserveGlobalVar(kv.first);
- }
- }
-}
-
-GlobalVarSupply::GlobalVarSupply(const IRModule module)
- : GlobalVarSupply(ffi::Array<IRModule>{module}) {}
-
-void GlobalVarSupplyNode::ReserveGlobalVar(const GlobalVar& var, bool
allow_conflict) {
- name_supply_->ReserveName(var->name_hint, false);
- if (!allow_conflict) {
- TVM_FFI_ICHECK(name_to_var_map_.count(var->name_hint) == 0)
- << "GlobalVar " << var << " conflicts by name in this supply.";
- }
- name_to_var_map_[var->name_hint] = var;
-}
-
-GlobalVarSupplyNode::GlobalVarSupplyNode(NameSupply name_supply,
- std::unordered_map<std::string,
GlobalVar> name_to_var_map)
- : name_supply_(std::move(name_supply)),
name_to_var_map_(std::move(name_to_var_map)) {}
-
-GlobalVar GlobalVarSupplyNode::UniqueGlobalFor(const ffi::String& name, bool
add_prefix) {
- ffi::String final_name = name_supply_->ReserveName(name, add_prefix);
-
- auto it = name_to_var_map_.find(final_name);
- if (it != name_to_var_map_.end()) {
- return it->second;
- } else {
- GlobalVar var = GlobalVar(final_name);
- name_to_var_map_.emplace(final_name, var);
- return var;
- }
-}
-
-GlobalVar GlobalVarSupplyNode::FreshGlobal(ffi::String name, bool add_prefix) {
- ffi::String final_name = name_supply_->FreshName(name, add_prefix);
- TVM_FFI_ICHECK(name_to_var_map_.find(final_name) == name_to_var_map_.end())
- << "GlobalVar already exists for name " << final_name;
- GlobalVar var = GlobalVar(final_name);
- name_to_var_map_.emplace(final_name, var);
- return var;
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- refl::GlobalDef()
- .def("ir.GlobalVarSupply_NameSupply",
- [](const NameSupply& name_supply) { return
GlobalVarSupply(name_supply); })
- .def("ir.GlobalVarSupply_IRModule",
- [](IRModule mod) { return GlobalVarSupply(std::move(mod)); })
- .def("ir.GlobalVarSupply_IRModules",
- [](const ffi::Array<IRModule>& mods) { return
GlobalVarSupply(mods); })
- .def_method("ir.GlobalVarSupply_FreshGlobal",
&GlobalVarSupplyNode::FreshGlobal)
- .def_method("ir.GlobalVarSupply_UniqueGlobalFor",
&GlobalVarSupplyNode::UniqueGlobalFor)
- .def_method("ir.GlobalVarSupply_ReserveGlobalVar",
&GlobalVarSupplyNode::ReserveGlobalVar);
-}
-
-} // namespace tvm
diff --git a/src/ir/module.cc b/src/ir/module.cc
index a09780d94d..156ca17c12 100644
--- a/src/ir/module.cc
+++ b/src/ir/module.cc
@@ -28,9 +28,9 @@
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ffi/rvalue_ref.h>
-#include <tvm/ir/global_var_supply.h>
#include <tvm/ir/module.h>
#include <tvm/ir/type_functor.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/target/codegen.h>
#include <algorithm>
@@ -219,13 +219,17 @@ IRModule IRModule::FromExpr(const RelaxExpr& expr,
}
}
+ UniqueNameSupply global_names(mod->functions.begin(), mod->functions.end(),
+ [](const auto& kv) { return
kv.first->name_hint; });
GlobalVar main_gv;
- auto global_var_supply = GlobalVarSupply(mod);
if (gv_name.empty()) {
// Bind function to 'main' (though rename if would clash with existing
'main').
- main_gv = global_var_supply->FreshGlobal("main", false);
+ main_gv = GlobalVar(global_names->FreshName("main", false));
+ } else if (mod->ContainGlobalVar(gv_name)) {
+ main_gv = mod->GetGlobalVar(gv_name);
} else {
- main_gv = global_var_supply->UniqueGlobalFor(gv_name, false);
+ global_names->ReserveName(gv_name, false);
+ main_gv = GlobalVar(gv_name);
}
mod->Add(main_gv, func);
return mod;
diff --git a/src/ir/name_supply.cc b/src/ir/name_supply.cc
deleted file mode 100644
index 2f7bf501e5..0000000000
--- a/src/ir/name_supply.cc
+++ /dev/null
@@ -1,108 +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 name_supply.cc
- * \brief NameSupply that can be used to generate unique variable names.
- */
-#include "tvm/ir/name_supply.h"
-
-#include <tvm/ffi/function.h>
-#include <tvm/ffi/reflection/registry.h>
-
-#include <utility>
-
-namespace tvm {
-
-NameSupply::NameSupply(const ffi::String& prefix,
std::unordered_map<std::string, int> name_map) {
- auto n = ffi::make_object<NameSupplyNode>(prefix, std::move(name_map));
- data_ = std::move(n);
-}
-
-ffi::String NameSupplyNode::ReserveName(const ffi::String& name, bool
add_prefix) {
- ffi::String final_name = name;
- if (add_prefix) {
- final_name = add_prefix_to_name(name);
- }
- name_map[final_name] = 0;
- return final_name;
-}
-
-ffi::String NameSupplyNode::FreshName(const ffi::String& name, bool add_prefix,
- bool add_underscore) {
- ffi::String unique_name = name;
- if (unique_name.empty()) {
- // Special case for empty name, set to "v".
- unique_name = "v";
- }
- if (add_prefix) {
- unique_name = add_prefix_to_name(unique_name);
- }
- unique_name = GetUniqueName(unique_name, add_underscore);
- return unique_name;
-}
-
-bool NameSupplyNode::ContainsName(const ffi::String& name, bool add_prefix) {
- ffi::String unique_name = name;
- if (add_prefix) {
- unique_name = add_prefix_to_name(name);
- }
-
- return name_map.count(unique_name);
-}
-
-ffi::String NameSupplyNode::add_prefix_to_name(const ffi::String& name) {
- if (prefix_.empty()) {
- return name;
- }
-
- std::ostringstream ss;
- ss << prefix_ << "_" << name;
- return ss.str();
-}
-
-std::string NameSupplyNode::GetUniqueName(std::string name, bool
add_underscore) {
- for (size_t i = 0; i < name.size(); ++i) {
- if (name[i] == '.') name[i] = '_';
- }
- auto it = name_map.find(name);
- if (it != name_map.end()) {
- auto new_name = name;
- while (!name_map.insert({new_name, 0}).second) {
- std::ostringstream os;
- os << name << (add_underscore ? "_" : "") << (++it->second);
- new_name = os.str();
- }
- return new_name;
- }
- name_map[name] = 0;
- return name;
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
- namespace refl = tvm::ffi::reflection;
- NameSupplyNode::RegisterReflection();
- refl::GlobalDef()
- .def("ir.NameSupply", [](ffi::String prefix) { return
NameSupply(prefix); })
- .def_method("ir.NameSupply_FreshName", &NameSupplyNode::FreshName)
- .def_method("ir.NameSupply_ReserveName", &NameSupplyNode::ReserveName)
- .def_method("ir.NameSupply_ContainsName", &NameSupplyNode::ContainsName);
-}
-
-} // namespace tvm
diff --git a/src/ir/unique_name_supply.cc b/src/ir/unique_name_supply.cc
new file mode 100644
index 0000000000..481edcac89
--- /dev/null
+++ b/src/ir/unique_name_supply.cc
@@ -0,0 +1,114 @@
+/*
+ * 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 unique_name_supply.cc
+ * \brief UniqueNameSupply that can be used to generate unique variable names.
+ */
+#include "tvm/ir/unique_name_supply.h"
+
+#include <tvm/ffi/function.h>
+#include <tvm/ffi/reflection/registry.h>
+
+#include <sstream>
+#include <utility>
+
+namespace tvm {
+
+UniqueNameSupply::UniqueNameSupply(const ffi::String& prefix,
+ ffi::Map<ffi::String, int64_t> name_map) {
+ if (!name_map.defined()) {
+ name_map = ffi::Map<ffi::String, int64_t>();
+ }
+ auto n = ffi::make_object<UniqueNameSupplyNode>(prefix, std::move(name_map));
+ data_ = std::move(n);
+}
+
+ffi::String UniqueNameSupplyNode::ReserveName(const ffi::String& name, bool
add_prefix) {
+ ffi::String final_name = name;
+ if (add_prefix) {
+ final_name = AddPrefixToName(name);
+ }
+ name_map.Set(final_name, 0);
+ return final_name;
+}
+
+ffi::String UniqueNameSupplyNode::FreshName(const ffi::String& name, bool
add_prefix,
+ bool add_underscore) {
+ ffi::String unique_name = name;
+ if (unique_name.empty()) {
+ unique_name = "v";
+ }
+ if (add_prefix) {
+ unique_name = AddPrefixToName(unique_name);
+ }
+ return GetUniqueName(unique_name, add_underscore);
+}
+
+bool UniqueNameSupplyNode::ContainsName(const ffi::String& name, bool
add_prefix) {
+ ffi::String unique_name = name;
+ if (add_prefix) {
+ unique_name = AddPrefixToName(name);
+ }
+ return name_map.count(unique_name);
+}
+
+ffi::String UniqueNameSupplyNode::AddPrefixToName(const ffi::String& name) {
+ if (prefix_.empty()) {
+ return name;
+ }
+
+ std::ostringstream ss;
+ ss << prefix_ << "_" << name;
+ return ss.str();
+}
+
+std::string UniqueNameSupplyNode::GetUniqueName(std::string name, bool
add_underscore) {
+ for (size_t i = 0; i < name.size(); ++i) {
+ if (name[i] == '.') name[i] = '_';
+ }
+ ffi::String name_key = name;
+ auto it = name_map.find(name_key);
+ if (it != name_map.end()) {
+ auto new_name = name;
+ int64_t suffix = (*it).second;
+ while (name_map.count(ffi::String(new_name))) {
+ std::ostringstream os;
+ os << name << (add_underscore ? "_" : "") << (++suffix);
+ new_name = os.str();
+ }
+ name_map.Set(name_key, suffix);
+ name_map.Set(ffi::String(new_name), 0);
+ return new_name;
+ }
+ name_map.Set(name_key, 0);
+ return name;
+}
+
+TVM_FFI_STATIC_INIT_BLOCK() {
+ namespace refl = tvm::ffi::reflection;
+ UniqueNameSupplyNode::RegisterReflection();
+ refl::GlobalDef()
+ .def("ir.UniqueNameSupply", [](ffi::String prefix) { return
UniqueNameSupply(prefix); })
+ .def_method("ir.UniqueNameSupply_FreshName",
&UniqueNameSupplyNode::FreshName)
+ .def_method("ir.UniqueNameSupply_ReserveName",
&UniqueNameSupplyNode::ReserveName)
+ .def_method("ir.UniqueNameSupply_ContainsName",
&UniqueNameSupplyNode::ContainsName);
+}
+
+} // namespace tvm
diff --git a/src/relax/backend/contrib/cutlass/codegen.cc
b/src/relax/backend/contrib/cutlass/codegen.cc
index 91840f6936..6de72397dc 100644
--- a/src/relax/backend/contrib/cutlass/codegen.cc
+++ b/src/relax/backend/contrib/cutlass/codegen.cc
@@ -25,7 +25,7 @@
#include <tvm/ffi/extra/module.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ir/module.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/relax/analysis.h>
#include <tvm/relax/attrs/nn.h>
#include <tvm/relax/type.h>
@@ -333,8 +333,8 @@ class CodegenCutlass : public
relax::MemoizedExprTranslator<OutputType>,
* name_hint.
*/
std::unordered_map<const VarNode*, std::string> var_name_map_;
- /*! \brief A name supply to generate a unique name for each parameter. */
- NameSupply name_sup_;
+ /*! \brief A unique name supply to generate a unique name for each
parameter. */
+ UniqueNameSupply name_sup_;
};
class CutlassModuleCodegen {
diff --git a/src/relax/ir/binding_rewrite.cc b/src/relax/ir/binding_rewrite.cc
index 9fad59f4e3..85fcfef1ea 100644
--- a/src/relax/ir/binding_rewrite.cc
+++ b/src/relax/ir/binding_rewrite.cc
@@ -48,8 +48,8 @@ DataflowBlockRewrite::DataflowBlockRewrite(DataflowBlock dfb,
Function root_fn)
auto p = FunctionUseDef(root_fn);
n->to_users_ = std::move(p.first);
n->fn_outputs_ = std::move(p.second);
- n->name_supply_ = NameSupply(n->to_users_.begin(), n->to_users_.end(),
- [](const auto& p) { return
p.first->name_hint(); });
+ n->name_supply_ = UniqueNameSupply(n->to_users_.begin(), n->to_users_.end(),
+ [](const auto& p) { return
p.first->name_hint(); });
data_ = std::move(n);
}
diff --git a/src/relax/ir/block_builder.cc b/src/relax/ir/block_builder.cc
index 344b09024e..f9360c6c42 100644
--- a/src/relax/ir/block_builder.cc
+++ b/src/relax/ir/block_builder.cc
@@ -70,7 +70,7 @@ class BlockBuilderImpl : public BlockBuilderNode {
//-------------------------------
// Global Context management
//-------------------------------
- NameSupply name_supply() final { return name_supply_; }
+ UniqueNameSupply name_supply() final { return name_supply_; }
IRModule GetContextIRModule() const final { return context_mod_; }
@@ -346,8 +346,8 @@ class BlockBuilderImpl : public BlockBuilderNode {
/*! \brief A binding table that maps var to value. */
std::unordered_map<Id, Expr, ffi::ObjectPtrHash, ffi::ObjectPtrEqual>
binding_table_;
- /*! \brief A name supply to get unique names for IR construction. */
- NameSupply name_supply_;
+ /*! \brief A unique name supply to get unique names for IR construction. */
+ UniqueNameSupply name_supply_;
/*! \brief The IRModule being built by the BlockBuilder. */
IRModule context_mod_;
diff --git a/src/relax/ir/dataflow_expr_rewriter.cc
b/src/relax/ir/dataflow_expr_rewriter.cc
index 9efa92bd84..625ae1e764 100644
--- a/src/relax/ir/dataflow_expr_rewriter.cc
+++ b/src/relax/ir/dataflow_expr_rewriter.cc
@@ -154,7 +154,7 @@ void RewriteSpec::Append(RewriteSpec other) {
return;
}
- NameSupply gvar_name_supply("");
+ UniqueNameSupply gvar_name_supply("");
for (const auto& [gvar, func] : new_subroutines) {
gvar_name_supply->ReserveName(gvar->name_hint);
}
diff --git a/src/relax/transform/allocate_workspace.cc
b/src/relax/transform/allocate_workspace.cc
index 718214d491..6bbe86d148 100644
--- a/src/relax/transform/allocate_workspace.cc
+++ b/src/relax/transform/allocate_workspace.cc
@@ -25,7 +25,7 @@
#include <tvm/ffi/cast.h>
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/relax/expr.h>
#include <tvm/relax/expr_functor.h>
#include <tvm/relax/transform.h>
@@ -96,7 +96,7 @@ class ExternFunctionRewriter : ExprMutator {
}
private:
- NameSupply name_sup_;
+ UniqueNameSupply name_sup_;
/*! \brief A variable that represents the workspace parameter passed from
main. */
Var workspace_var_param_;
size_t max_workspace_size_ = 0;
diff --git a/src/relax/transform/normalize.cc b/src/relax/transform/normalize.cc
index 7c8f6b3854..ac3f0611db 100644
--- a/src/relax/transform/normalize.cc
+++ b/src/relax/transform/normalize.cc
@@ -268,7 +268,7 @@ class GlobalVarNormalizer : private ExprMutator {
}
IRModule module_;
- NameSupply name_supply_;
+ UniqueNameSupply name_supply_;
ffi::Map<GlobalVar, GlobalVar> gvar_map_;
};
diff --git a/src/target/source/codegen_c.cc b/src/target/source/codegen_c.cc
index 8762c83ee4..ddedd9ee35 100644
--- a/src/target/source/codegen_c.cc
+++ b/src/target/source/codegen_c.cc
@@ -24,7 +24,7 @@
#include <tvm/arith/analyzer.h>
#include <tvm/ffi/cast.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <cctype>
#include <iomanip>
diff --git a/src/target/source/codegen_c.h b/src/target/source/codegen_c.h
index 934d1af83a..a023277ed1 100644
--- a/src/target/source/codegen_c.h
+++ b/src/target/source/codegen_c.h
@@ -357,8 +357,8 @@ class CodeGenC : public ExprFunctor<void(const PrimExpr&,
std::ostream&)>,
*/
std::unordered_map<GlobalVar, ffi::String> internal_functions_;
- /* \brief Name supply to generate unique function names */
- NameSupply func_name_supply_;
+ /* \brief Unique unique name supply to generate unique function names */
+ UniqueNameSupply func_name_supply_;
};
} // namespace codegen
diff --git a/src/target/source/codegen_source_base.cc
b/src/target/source/codegen_source_base.cc
index 5a07e3c7aa..2646a6597e 100644
--- a/src/target/source/codegen_source_base.cc
+++ b/src/target/source/codegen_source_base.cc
@@ -28,7 +28,7 @@ namespace tvm {
namespace codegen {
void CodeGenSourceBase::ClearFuncState() {
- name_supply_ = NameSupply();
+ name_supply_ = UniqueNameSupply();
ssa_assign_map_.clear();
var_idmap_.clear();
scope_mark_.clear();
diff --git a/src/target/source/codegen_source_base.h
b/src/target/source/codegen_source_base.h
index 9283944c1b..f6e58cc9ef 100644
--- a/src/target/source/codegen_source_base.h
+++ b/src/target/source/codegen_source_base.h
@@ -25,7 +25,7 @@
#ifndef TVM_TARGET_SOURCE_CODEGEN_SOURCE_BASE_H_
#define TVM_TARGET_SOURCE_CODEGEN_SOURCE_BASE_H_
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/target/codegen.h>
#include <tvm/tirx/expr.h>
#include <tvm/tirx/op.h>
@@ -123,8 +123,8 @@ class CodeGenSourceBase {
std::ostringstream fwd_decl_stream;
/*! \brief name of each variable */
std::unordered_map<const tirx::VarNode*, std::string> var_idmap_;
- /*! \brief NameSupply for allocation */
- NameSupply name_supply_;
+ /*! \brief Unique name supply for allocation */
+ UniqueNameSupply name_supply_;
/*! \brief The current indentation value */
int indent_{0};
diff --git a/src/te/operation/create_primfunc.cc
b/src/te/operation/create_primfunc.cc
index a4ce62812a..5a7223430e 100644
--- a/src/te/operation/create_primfunc.cc
+++ b/src/te/operation/create_primfunc.cc
@@ -23,7 +23,7 @@
#include <tvm/ffi/cast.h>
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/te/operation.h>
#include <tvm/tirx/analysis.h>
#include <tvm/tirx/function.h>
@@ -112,8 +112,8 @@ struct CreateFuncInfo {
ProducerToBufferTransformer transformer;
/*! \brief The buffers should be allocated at function root. */
ffi::Array<Buffer> root_alloc;
- /*! \brief The NameSupply to make block name unique. */
- NameSupply name_supply;
+ /*! \brief The unique name supply to make block name unique. */
+ UniqueNameSupply name_supply;
ffi::String FreshName(ffi::String base_name) { return
name_supply->FreshName(base_name); }
diff --git a/src/tirx/ir/index_map.cc b/src/tirx/ir/index_map.cc
index b26ccca248..cde0370f7f 100644
--- a/src/tirx/ir/index_map.cc
+++ b/src/tirx/ir/index_map.cc
@@ -26,7 +26,7 @@
#include <tvm/arith/iter_affine_map.h>
#include <tvm/ffi/cast.h>
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/name_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/tirx/index_map.h>
#include <tvm/tirx/op.h>
#include <tvm/tirx/stmt_functor.h>
@@ -347,7 +347,7 @@ IndexMap IndexMap::RenameVariables(
const std::function<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map) const {
std::unordered_set<std::string> used_names;
ffi::Map<Var, Var> var_remap;
- NameSupply name_supply;
+ UniqueNameSupply name_supply;
const IndexMapNode* n = this->get();
if (f_name_map != nullptr) {
// Collect variables with pre-defined names provided by f_name_map.
diff --git a/src/tirx/transform/bind_target.cc
b/src/tirx/transform/bind_target.cc
index 7a5627c80b..16bf740152 100644
--- a/src/tirx/transform/bind_target.cc
+++ b/src/tirx/transform/bind_target.cc
@@ -36,7 +36,7 @@
#include <tvm/ffi/cast.h>
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/global_var_supply.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/s_tir/stmt.h>
#include <tvm/s_tir/transform.h>
#include <tvm/tirx/stmt_functor.h>
@@ -261,7 +261,8 @@ IRModule BindTarget(IRModule mod, const Target& target) {
// Track duplicated functions for call replacement
ffi::Map<GlobalVar, GlobalVar> host_function_replacements;
- GlobalVarSupply gvar_supply(new_mod);
+ UniqueNameSupply global_names(new_mod->functions.begin(),
new_mod->functions.end(),
+ [](const auto& kv) { return
kv.first->name_hint; });
for (auto [gvar, func] : mod->functions) {
const auto* prim_func_node = func.as<PrimFuncNode>();
@@ -313,7 +314,7 @@ IRModule BindTarget(IRModule mod, const Target& target) {
// Create duplicate with host target for host callers
host_func = WithAttr(std::move(host_func), tvm::attr::kTarget,
target_host);
ffi::String host_func_name = gvar->name_hint + "_host";
- GlobalVar host_gvar = gvar_supply->FreshGlobal(host_func_name, false);
+ GlobalVar host_gvar =
GlobalVar(global_names->FreshName(host_func_name, false));
new_mod->Add(host_gvar, host_func);
host_function_replacements.Set(gvar, host_gvar);
diff --git a/src/tirx/transform/split_host_device.cc
b/src/tirx/transform/split_host_device.cc
index 7ec104765f..acc5e473af 100644
--- a/src/tirx/transform/split_host_device.cc
+++ b/src/tirx/transform/split_host_device.cc
@@ -24,8 +24,8 @@
#include <tvm/ffi/cast.h>
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/registry.h>
-#include <tvm/ir/global_var_supply.h>
#include <tvm/ir/transform.h>
+#include <tvm/ir/unique_name_supply.h>
#include <tvm/target/target.h>
#include <tvm/tirx/analysis.h>
#include <tvm/tirx/builtin.h>
@@ -678,7 +678,8 @@ namespace transform {
Pass SplitHostDevice() {
auto pass_func = [](IRModule mod, PassContext ctx) {
- GlobalVarSupply global_var_supply(mod);
+ UniqueNameSupply global_names(mod->functions.begin(), mod->functions.end(),
+ [](const auto& kv) { return
kv.first->name_hint; });
IRModule device_mod = IRModule(ffi::Map<GlobalVar, BaseFunc>({}));
IRModule updates = IRModule(ffi::Map<GlobalVar, BaseFunc>({}));
@@ -691,8 +692,8 @@ Pass SplitHostDevice() {
auto global_symbol =
func->GetAttr<ffi::String>(tvm::attr::kGlobalSymbol);
auto name_prefix = global_symbol.value_or(gvar->name_hint);
auto kernel_name = name_prefix + "_kernel";
- auto var_supply = [&global_var_supply, &kernel_name]() -> GlobalVar {
- return global_var_supply->FreshGlobal(kernel_name, false);
+ auto var_supply = [&global_names, &kernel_name]() -> GlobalVar {
+ return GlobalVar(global_names->FreshName(kernel_name, false));
};
func = SplitHostDevice(std::move(func), &device_mod, var_supply);
diff --git a/tests/python/ir/test_name_supply.py
b/tests/python/ir/test_unique_name_supply.py
similarity index 62%
rename from tests/python/ir/test_name_supply.py
rename to tests/python/ir/test_unique_name_supply.py
index bc3283968d..f440301e1f 100644
--- a/tests/python/ir/test_name_supply.py
+++ b/tests/python/ir/test_unique_name_supply.py
@@ -16,12 +16,17 @@
# under the License.
import tvm
import tvm.testing
-from tvm.ir.supply import NameSupply
+from tvm import relax as rx
+from tvm.ir.supply import UniqueNameSupply
+
+
+def _empty_relax_func():
+ return rx.Function([], rx.Tuple([]))
def test_fresh_name_empty_string():
"""Empty name should produce a valid variable name, not an empty string."""
- ns = NameSupply("")
+ ns = UniqueNameSupply("")
name = ns.fresh_name("", add_prefix=False)
assert name == "v"
name2 = ns.fresh_name("", add_prefix=False)
@@ -30,12 +35,28 @@ def test_fresh_name_empty_string():
def test_fresh_name_empty_string_with_prefix():
"""Empty name with prefix should produce a valid variable name."""
- ns = NameSupply("prefix")
+ ns = UniqueNameSupply("prefix")
name = ns.fresh_name("", add_prefix=True)
assert name == "prefix_v"
name2 = ns.fresh_name("", add_prefix=True)
assert name2 == "prefix_v_1"
+def test_ir_module_from_expr_freshens_main_collision():
+ main_gv = tvm.ir.GlobalVar("main")
+ mod = tvm.IRModule.from_expr(_empty_relax_func(), {main_gv:
_empty_relax_func()})
+
+ assert sorted(gvar.name_hint for gvar in mod.get_global_vars()) ==
["main", "main_1"]
+
+
+def test_ir_module_from_expr_reuses_existing_global_symbol():
+ foo_gv = tvm.ir.GlobalVar("foo")
+ func = _empty_relax_func().with_attr("global_symbol", "foo")
+ mod = tvm.IRModule.from_expr(func, {foo_gv: _empty_relax_func()})
+
+ assert mod.get_global_var("foo").same_as(foo_gv)
+ assert [gvar.name_hint for gvar in mod.get_global_vars()] == ["foo"]
+
+
if __name__ == "__main__":
tvm.testing.main()