367 lines
12 KiB
C++
367 lines
12 KiB
C++
/*
|
|
* 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/module.h
|
|
* \brief IRModule that holds the functions and type definitions.
|
|
*/
|
|
#ifndef TVM_IR_MODULE_H_
|
|
#define TVM_IR_MODULE_H_
|
|
|
|
#include <tvm/ffi/container/array.h>
|
|
#include <tvm/ffi/container/map.h>
|
|
#include <tvm/ffi/reflection/registry.h>
|
|
#include <tvm/ffi/string.h>
|
|
#include <tvm/ir/cow.h>
|
|
#include <tvm/ir/expr.h>
|
|
#include <tvm/ir/function.h>
|
|
#include <tvm/ir/global_info.h>
|
|
#include <tvm/ir/source_map.h>
|
|
#include <tvm/ir/type.h>
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace tvm {
|
|
|
|
class IRModule;
|
|
|
|
/*!
|
|
* \brief IRModule that holds functions and type definitions.
|
|
*
|
|
* IRModule is the basic unit for all IR transformations across the stack.
|
|
*
|
|
* Many operations require access to the global IRModule.
|
|
* We pass the IRModule by value in a functional style as an explicit argument,
|
|
* but we mutate the Module while optimizing programs.
|
|
* \sa IRModule
|
|
*/
|
|
class IRModuleNode : public ffi::Object {
|
|
public:
|
|
/*! \brief A map from ids to all global functions. */
|
|
ffi::Map<GlobalVar, BaseFunc> functions;
|
|
/*! \brief The source map for the module. */
|
|
SourceMap source_map;
|
|
/* \brief Additional attributes storing meta-data about the module. */
|
|
DictAttrs attrs;
|
|
/*! \brief Globally static object that are referred by the IR itself */
|
|
ffi::Map<ffi::String, ffi::Array<GlobalInfo>> global_infos;
|
|
/*!
|
|
* \brief A map from string names to global variables that
|
|
* ensures global uniqueness.
|
|
*/
|
|
ffi::Map<ffi::String, GlobalVar> global_var_map_;
|
|
|
|
/*!
|
|
* \brief Get a module attribute.
|
|
*
|
|
* \param attr_key The attribute key.
|
|
* \param default_value The default value if the key does not exist, defaults to nullptr.
|
|
*
|
|
* \return The result
|
|
*
|
|
* \tparam TObjectRef the expected object type.
|
|
* \throw Error if the key exists but the value does not match TObjectRef
|
|
*
|
|
* \code
|
|
*
|
|
* void GetAttrExample(const IRModule& mod) {
|
|
* auto value = f->GetAttr<int64_t>("AttrKey", 0);
|
|
* }
|
|
*
|
|
* \endcode
|
|
*/
|
|
template <typename TObjectRef>
|
|
ffi::Optional<TObjectRef> GetAttr(
|
|
const std::string& attr_key,
|
|
ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt)) const {
|
|
return attrs.GetAttr(attr_key, default_value);
|
|
}
|
|
// variant that uses TObjectRef to enable implicit conversion to default value.
|
|
template <typename TObjectRef>
|
|
ffi::Optional<TObjectRef> GetAttr(const std::string& attr_key, TObjectRef default_value) const {
|
|
return GetAttr<TObjectRef>(attr_key, ffi::Optional<TObjectRef>(default_value));
|
|
}
|
|
|
|
/*!
|
|
* \brief Get the metadata attributes.
|
|
* \returns The additional meta-data attributes
|
|
*/
|
|
DictAttrs GetAttrs() const { return attrs; }
|
|
|
|
/*!
|
|
* \brief Check whether the module has an non-zero integer attr.
|
|
*
|
|
* This function can be used to check whether an optional
|
|
* attribute mark(e.g. inline) exists.
|
|
*
|
|
* \param attr_key The key to the attribute.
|
|
* \return The check result.
|
|
*
|
|
* \code
|
|
*
|
|
* void HasNonzeroAttrExample(const IRModule& mod) {
|
|
* if (mod->HasNonzeroAttr(attr::kInline)) {
|
|
* // inline the function.
|
|
* }
|
|
* }
|
|
*
|
|
* \endcode
|
|
*/
|
|
bool HasNonzeroAttr(const std::string& attr_key) const { return attrs.HasNonzeroAttr(attr_key); }
|
|
|
|
IRModuleNode() : source_map() {}
|
|
|
|
static void RegisterReflection() {
|
|
namespace refl = tvm::ffi::reflection;
|
|
refl::ObjectDef<IRModuleNode>()
|
|
.def_ro("functions", &IRModuleNode::functions)
|
|
.def_ro("global_var_map_", &IRModuleNode::global_var_map_)
|
|
.def_ro("source_map", &IRModuleNode::source_map)
|
|
.def_ro("attrs", &IRModuleNode::attrs)
|
|
.def_ro("global_infos", &IRModuleNode::global_infos);
|
|
// register custom structural equal and hash.
|
|
refl::TypeAttrDef<IRModuleNode>()
|
|
.def("__s_equal__", &IRModuleNode::SEqual)
|
|
.def("__s_hash__", &IRModuleNode::SHash);
|
|
}
|
|
|
|
TVM_DLL bool SEqual(const IRModuleNode* other,
|
|
ffi::TypedFunction<bool(AnyView, AnyView, bool, AnyView)> equal) const;
|
|
TVM_DLL int64_t SHash(int64_t init_hash,
|
|
ffi::TypedFunction<int64_t(AnyView, int64_t, bool)> hash) const;
|
|
|
|
/*!
|
|
* \brief Add a function to the global environment.
|
|
* \param var The var of the global function.
|
|
* \param func The function.
|
|
* \param update Controls whether you can replace a definition in the
|
|
* environment.
|
|
*/
|
|
TVM_DLL void Add(const GlobalVar& var, const BaseFunc& func, bool update = false);
|
|
|
|
/*!
|
|
* \brief Add a function to the global environment.
|
|
* \param var The name of the global function.
|
|
* \param func The function.
|
|
*
|
|
* It does not do type inference as Add does.
|
|
*/
|
|
TVM_DLL void AddUnchecked(const GlobalVar& var, const BaseFunc& func);
|
|
|
|
/*!
|
|
* \brief Update a function in the global environment.
|
|
* \param var The name of the global function to update.
|
|
* \param func The new function.
|
|
*/
|
|
TVM_DLL void Update(const GlobalVar& var, const BaseFunc& func);
|
|
|
|
/*!
|
|
* \brief Update an array of global infos in the global environment.
|
|
* \param name The name of the global info.
|
|
* \param info The new array of global infos.
|
|
*/
|
|
TVM_DLL void UpdateGlobalInfo(const ffi::String& name, const ffi::Array<GlobalInfo>& info);
|
|
|
|
/*!
|
|
* \brief Remove a function from the global environment.
|
|
* \param var The name of the global function to update.
|
|
*/
|
|
TVM_DLL void Remove(const GlobalVar& var);
|
|
|
|
/*!
|
|
* \brief Check if the global_var_map_ contains a global variable.
|
|
* \param name The variable name.
|
|
* \returns true if contains, otherise false.
|
|
*/
|
|
TVM_DLL bool ContainGlobalVar(const ffi::String& name) const;
|
|
|
|
/*!
|
|
* \brief Lookup a global function by its variable.
|
|
* \param str The unique string specifying the global variable.
|
|
* \returns The global variable.
|
|
*/
|
|
TVM_DLL GlobalVar GetGlobalVar(const ffi::String& str) const;
|
|
|
|
/*!
|
|
* \brief Collect all global vars defined in this module, ordered by
|
|
* the global variable name.
|
|
* \returns An array of global vars
|
|
*/
|
|
TVM_DLL ffi::Array<GlobalVar> GetGlobalVars() const;
|
|
|
|
/*!
|
|
* \brief Look up a global function by its variable.
|
|
* \param var The global var to lookup.
|
|
* \returns The function named by the variable argument.
|
|
*/
|
|
TVM_DLL BaseFunc Lookup(const GlobalVar& var) const;
|
|
|
|
/*!
|
|
* \brief Look up a global function by its string name
|
|
* \param name The name of the function.
|
|
* \returns The function named by the argument.
|
|
*/
|
|
TVM_DLL BaseFunc Lookup(const ffi::String& name) const;
|
|
|
|
/*!
|
|
* \brief Update the functions inside this environment by
|
|
* functions in another environment.
|
|
* \param other The other environment.
|
|
*/
|
|
TVM_DLL void Update(const IRModule& other);
|
|
|
|
/*!
|
|
* \brief Create a shallow copy of this IRModule.
|
|
* \returns The shallow copy of the IRModule.
|
|
*/
|
|
TVM_DLL IRModule ShallowCopy();
|
|
/*!
|
|
* \brief The set of imported files.
|
|
*/
|
|
TVM_DLL std::unordered_set<ffi::String> Imports() const;
|
|
|
|
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind = kTVMFFISEqHashKindTreeNode;
|
|
|
|
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.IRModule", IRModuleNode, ffi::Object);
|
|
|
|
private:
|
|
friend class IRModule;
|
|
};
|
|
|
|
/*!
|
|
* \brief Managed reference class to IRModuleNode.
|
|
* \sa IRModuleNode
|
|
*/
|
|
class IRModule : public ffi::ObjectRef {
|
|
public:
|
|
/*!
|
|
* \brief constructor
|
|
* \param functions Functions in the module.
|
|
* \param map The module source map.
|
|
* \param attrs The module meta-data attributes.
|
|
* \param global_infos Global infos in the module.
|
|
*/
|
|
TVM_DLL explicit IRModule(ffi::Map<GlobalVar, BaseFunc> functions, SourceMap map = {},
|
|
DictAttrs attrs = DictAttrs(),
|
|
ffi::Map<ffi::String, ffi::Array<GlobalInfo>> global_infos = {});
|
|
|
|
/*! \brief default constructor */
|
|
IRModule() : IRModule(ffi::Map<GlobalVar, BaseFunc>({})) {}
|
|
/*!
|
|
* \brief constructor
|
|
* \param n The object pointer.
|
|
*/
|
|
explicit IRModule(ffi::ObjectPtr<IRModuleNode> n) : ffi::ObjectRef(n) {}
|
|
/*!
|
|
* \brief constructor with UnsafeInit
|
|
*/
|
|
explicit IRModule(ffi::UnsafeInit tag) : ffi::ObjectRef(tag) {}
|
|
/*! \return mutable pointers to the node. */
|
|
IRModuleNode* operator->() const {
|
|
auto* ptr = get_mutable();
|
|
TVM_FFI_ICHECK(ptr != nullptr);
|
|
return static_cast<IRModuleNode*>(ptr);
|
|
}
|
|
|
|
/*!
|
|
* \brief As for \p FromExprInContext, but assuming \p expr is bound to 'main' and no
|
|
* imports.
|
|
*/
|
|
TVM_DLL static IRModule FromExpr(const Expr& expr,
|
|
const ffi::Map<GlobalVar, BaseFunc>& global_funcs = {});
|
|
|
|
/*!
|
|
* \brief Create a shallow copy of an IRModule.
|
|
* \param mod The module to copy.
|
|
* \return The copied module.
|
|
*/
|
|
IRModule ShallowCopyIRModule(IRModule mod);
|
|
|
|
/*! \brief Declare the container type. */
|
|
using ContainerType = IRModuleNode;
|
|
|
|
// allow copy on write.
|
|
TVM_DEFINE_OBJECT_REF_COW_METHOD(IRModuleNode);
|
|
};
|
|
|
|
namespace attr {
|
|
|
|
// Following are attributes for IRModule only.
|
|
|
|
/*!
|
|
* \brief Name of the module
|
|
*
|
|
* Type: String
|
|
*/
|
|
constexpr const char* kModuleName = "mod_name";
|
|
|
|
/*!
|
|
* \brief All the runtime::Modules accumulated during compilation by external codegen. These
|
|
* modules must be either directly linked or captured in the final compilation artifact.
|
|
*
|
|
* Type: ffi::Array<runtime::Module>
|
|
*/
|
|
constexpr const char* kExternalMods = "external_mods";
|
|
|
|
/*!
|
|
* \brief A prefix for generating C symbols system lib creation.
|
|
*
|
|
* This prefix guides passes that creates global_symbol for internal functions
|
|
* that may have c linkage (e.g. TIR functions and some BYOC functions). It also affects
|
|
* the symbol of the fat bin blob during module export.
|
|
*
|
|
* This attribute is used to avoid symbol conflict when we
|
|
* generate and combine multiple system libs that get linked into one.
|
|
*
|
|
* Rationale: mechanisms like BYOC rely on the common global symbol
|
|
* and each external compiler also has its own mechanism of mangling.
|
|
* As a result, we cannot rely on other mechanisms on setting a global_symbol and then renaming,
|
|
* because the external compiler already agreed on the name.
|
|
*
|
|
* system_lib_prefix provides a way to hint at the passes to allow names to
|
|
* avoid name conflict at the beginning.
|
|
*
|
|
* Note that users can still directly specify global symbols that may conflict.
|
|
* It is up to the downstream toolchain to manage those external-facing functions.
|
|
*
|
|
* This does not affect non-C linkage functions it is less of an issue because
|
|
* they will be embedded into fatbin that in different symbols,
|
|
* The system lib loader can pick the right prefix for a given prefix.
|
|
*
|
|
* Having this attribute implies system lib generation linkage.
|
|
*/
|
|
constexpr const char* kSystemLibPrefix = "system_lib_prefix";
|
|
|
|
/*!
|
|
* \brief All the named runtime::Tensors accumulated during compilation by external codegen.
|
|
* Generally the associated runtime::Module will indicate it requires bindings for these names,
|
|
* and during module initialization these bindings will be recovered from a ConstLoaderModule.
|
|
*
|
|
* Type: ffi::Map<ffi::String, runtime::Tensor>
|
|
*/
|
|
constexpr const char* kConstNameToConstant = "const_name_to_constant";
|
|
|
|
} // namespace attr
|
|
} // namespace tvm
|
|
#endif // TVM_IR_MODULE_H_
|