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-tirx.git
The following commit(s) were added to refs/heads/main by this push:
new fdd60d0e [REFACTOR] Export public APIs through FFI-compatible
boundaries (#7)
fdd60d0e is described below
commit fdd60d0e46eb84f9db924a108a4867edb0941e2c
Author: Tianqi Chen <[email protected]>
AuthorDate: Tue Oct 20 21:00:42 2026 -0400
[REFACTOR] Export public APIs through FFI-compatible boundaries (#7)
Public C++ callers could not link several out-of-line compiler APIs
under hidden visibility. Export those APIs and inline the axis
predicates and sequential-pass pointer accessor. Layout operations use
exported nonvirtual reference-wrapper methods with explicit FFI type
dispatch; layout and document nodes remain data-only and need no C++
vtables.
Use FFI strings, owning callbacks, tuples and optionals across exported
signatures. Native symbolic-analysis maps and recovery callbacks retain
their existing interfaces, and registration-only hooks remain in their
owning implementation files. Header-defined native pass adapters
preserve mutable callables and move ownership. C++ consumers must
rebuild for the changed DLL signatures and use the layout
reference-wrapper methods.
---
include/tvm/codegen/codegen.h | 10 ++++----
include/tvm/ir/transform.h | 40 ++++++++++++++++++++++--------
include/tvm/runtime/logging.h | 10 +++++++-
include/tvm/script/ir_builder/frame.h | 23 +++++++++--------
include/tvm/script/ir_builder/ir.h | 39 +++++++++++++++--------------
include/tvm/script/printer/config.h | 4 +--
include/tvm/script/printer/printer.h | 2 +-
include/tvm/sym/analyzer.h | 15 +++++------
include/tvm/target/target.h | 10 ++++----
include/tvm/tirx/index_map.h | 27 ++++++++++++--------
include/tvm/tirx/layout.h | 21 +++++++++++-----
include/tvm/tirx/script/ir_builder/frame.h | 3 +--
include/tvm/tirx/script/ir_builder/ir.h | 16 ++++++------
include/tvm/tirx/stmt_functor.h | 4 +--
include/tvm/tirx/tile/context.h | 12 ++++-----
include/tvm/tirx/transform.h | 29 ++++++++++++++++++----
include/tvm/tirx/type.h | 2 +-
src/codegen/module_export.cc | 8 +++---
src/ir/transform.cc | 34 +++++++++++--------------
src/runtime/logging.cc | 10 --------
src/script/printer/printer.cc | 8 +++---
src/sym/const_int_bound.cc | 6 ++++-
src/target/target.cc | 6 ++---
src/tirx/ir/index_map.cc | 26 +++++++++----------
src/tirx/ir/layout/axis_registry.cc | 12 ---------
src/tirx/ir/stmt_functor.cc | 6 ++---
src/tirx/ir/transform.cc | 28 ++++++++++-----------
src/tirx/ir/type.cc | 2 +-
28 files changed, 226 insertions(+), 187 deletions(-)
diff --git a/include/tvm/codegen/codegen.h b/include/tvm/codegen/codegen.h
index a7f465c4..02f61ccf 100644
--- a/include/tvm/codegen/codegen.h
+++ b/include/tvm/codegen/codegen.h
@@ -54,8 +54,8 @@ TVM_TIRX_DLL ffi::Module Build(IRModule mod, Target target);
* \param c_symbol_prefix Optional symbol prefix of the blob symbol.
* \return cstr The C string representation of the file.
*/
-TVM_TIRX_DLL std::string PackImportsToC(const ffi::Module& m, bool system_lib,
- const std::string& c_symbol_prefix =
"");
+TVM_TIRX_DLL ffi::String PackImportsToC(const ffi::Module& m, bool system_lib,
+ const ffi::String& c_symbol_prefix =
"");
/*!
* \brief Pack imported device libraries into an object file using LLVM.
@@ -70,9 +70,9 @@ TVM_TIRX_DLL std::string PackImportsToC(const ffi::Module& m,
bool system_lib,
* \param c_symbol_prefix Optional blob symbol prefix, valid only for system
libraries.
*/
TVM_TIRX_DLL void PackImportsToObjectFile(const ffi::Module& mod, bool
system_lib,
- const std::string&
llvm_target_string,
- const std::string& file_name,
- const std::string& c_symbol_prefix =
"");
+ const ffi::String&
llvm_target_string,
+ const ffi::String& file_name,
+ const ffi::String& c_symbol_prefix =
"");
namespace attr {
inline constexpr ffi::reflection::AttrKey<bool> kParallelStridePattern{
diff --git a/include/tvm/ir/transform.h b/include/tvm/ir/transform.h
index 0d7763e6..c515e95a 100644
--- a/include/tvm/ir/transform.h
+++ b/include/tvm/ir/transform.h
@@ -32,6 +32,7 @@
#include <tvm/ffi/function.h>
#include <tvm/ffi/reflection/creator.h>
#include <tvm/ffi/reflection/registry.h>
+#include <tvm/ffi/rvalue_ref.h>
#include <tvm/ffi/string.h>
#include <tvm/ir/module.h>
#include <tvm/ir/with_context.h>
@@ -196,8 +197,9 @@ class PassContext : public ffi::ObjectRef {
// The exit of a pass context scope.
TVM_TIRX_DLL void ExitWithScope();
// Register configuration key value type.
- TVM_TIRX_DLL static void RegisterConfigOption(const char* key, ffi::String
value_type_str,
-
std::function<ffi::Any(ffi::Any)> legalization);
+ TVM_TIRX_DLL static void RegisterConfigOption(
+ const char* key, ffi::String value_type_str,
+ ffi::TypedFunction<ffi::Any(ffi::Any)> legalization);
// Classes to get the Python `with` like syntax.
friend class Internal;
@@ -324,7 +326,7 @@ class Pass : public ffi::ObjectRef {
*
* \return The transformed module.
*/
- IRModule operator()(IRModule mod, const PassContext& pass_ctx) const;
+ TVM_TIRX_DLL IRModule operator()(IRModule mod, const PassContext& pass_ctx)
const;
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(Pass, ffi::ObjectRef, PassObj);
@@ -374,7 +376,7 @@ class SequentialObj : public PassObj {
*
* \return Return the updated module.
*/
- IRModule operator()(IRModule mod, const PassContext& pass_ctx) const final;
+ TVM_TIRX_DLL IRModule operator()(IRModule mod, const PassContext& pass_ctx)
const final;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.Sequential", SequentialObj,
PassObj);
};
@@ -400,21 +402,39 @@ class Sequential : public Pass {
explicit Sequential(ffi::UnsafeInit tag) : Pass(tag) {}
- const SequentialObj* operator->() const;
+ const SequentialObj* operator->() const { return static_cast<const
SequentialObj*>(get()); }
using ContainerType = SequentialObj;
};
-/*
- * \brief Create a module pass.
+/*!
+ * \brief Create a module pass from an owning FFI callback.
*
- * \param pass_func The packed function that contains the optimization.
+ * \param pass_func The callback that transforms the module.
* \param opt_level The optimization level of the module pass.
* \param name The name of the module pass.
+ * \return The created module pass.
+ */
+TVM_TIRX_DLL Pass
+CreateModulePass(ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>,
PassContext)> pass_func,
+ int opt_level, ffi::String name);
+
+/*!
+ * \brief Create a module pass from a native C++ callback.
*
+ * \param pass_func The callback that transforms the module.
+ * \param opt_level The optimization level of the module pass.
+ * \param name The name of the module pass.
* \return The created module pass.
*/
-TVM_TIRX_DLL Pass CreateModulePass(std::function<IRModule(IRModule,
PassContext)> pass_func,
- int opt_level, ffi::String name);
+inline Pass CreateModulePass(std::function<IRModule(IRModule, PassContext)>
pass_func,
+ int opt_level, ffi::String name) {
+ ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>, PassContext)> callback
=
+ [pass_func = std::move(pass_func)](ffi::RValueRef<IRModule> mod,
+ PassContext ctx) -> IRModule {
+ return pass_func(*std::move(mod), std::move(ctx));
+ };
+ return CreateModulePass(std::move(callback), opt_level, std::move(name));
+}
/*!
* \brief A special trace pass that prints the header and IR to LOG(INFO).
diff --git a/include/tvm/runtime/logging.h b/include/tvm/runtime/logging.h
index 68718acc..ad61d761 100644
--- a/include/tvm/runtime/logging.h
+++ b/include/tvm/runtime/logging.h
@@ -304,7 +304,15 @@ class VLogContext {
}
}
- std::string str() const;
+ std::string str() const {
+ std::stringstream result;
+ for (const auto* entry : context_stack_) {
+ TVM_FFI_ICHECK_NOTNULL(entry);
+ result << entry->str();
+ result << ": ";
+ }
+ return result.str();
+ }
private:
std::vector<std::stringstream*> context_stack_;
diff --git a/include/tvm/script/ir_builder/frame.h
b/include/tvm/script/ir_builder/frame.h
index 7e7b2158..cb078bf1 100644
--- a/include/tvm/script/ir_builder/frame.h
+++ b/include/tvm/script/ir_builder/frame.h
@@ -68,7 +68,7 @@ class IRModuleFrameObj : public IRBuilderFrameObj {
IRBuilderFrameObj);
public:
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -160,9 +160,10 @@ class ForFrameObj : public StmtFrameObj {
public:
/*! \brief Apply source target names before entry, preserving variable
identity. */
- void SetNames(ffi::Optional<ffi::Variant<ffi::String,
ffi::Array<ffi::String>>> names);
+ TVM_TIRX_DLL void SetNames(
+ ffi::Optional<ffi::Variant<ffi::String, ffi::Array<ffi::String>>> names);
/*! \brief Construct the loop nest with this frame's stored source location.
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -213,7 +214,7 @@ class AssertFrameObj : public StmtFrameObj {
* \brief The method called when exiting RAII scope.
* \sa tvm::support::With
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -259,7 +260,7 @@ class RegionFrameObj : public StmtFrameObj {
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("script.ir_builder.RegionFrame",
RegionFrameObj, StmtFrameObj);
/*! \brief Construct the region and add it to the enclosing builder frame. */
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*! \brief Managed reference to RegionFrameObj. */
@@ -297,7 +298,7 @@ class WhileFrameObj : public StmtFrameObj {
* \brief The method called when exiting RAII scope.
* \sa tvm::support::With
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -346,7 +347,7 @@ class IfFrameObj : public StmtFrameObj {
* \brief The method called when exiting RAII scope.
* \sa tvm::support::With
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -380,12 +381,12 @@ class ThenFrameObj : public StmtFrameObj {
* \brief The method called when entering RAII scope.
* \sa tvm::support::With
*/
- void EnterWithScope() final;
+ TVM_TIRX_DLL void EnterWithScope() final;
/*!
* \brief The method called when exiting RAII scope.
* \sa tvm::support::With
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
@@ -419,12 +420,12 @@ class ElseFrameObj : public StmtFrameObj {
* \brief The method called when entering RAII scope.
* \sa tvm::support::With
*/
- void EnterWithScope() final;
+ TVM_TIRX_DLL void EnterWithScope() final;
/*!
* \brief The method called when exiting RAII scope.
* \sa tvm::support::With
*/
- void ExitWithScope() final;
+ TVM_TIRX_DLL void ExitWithScope() final;
};
/*!
diff --git a/include/tvm/script/ir_builder/ir.h
b/include/tvm/script/ir_builder/ir.h
index dec738f7..924c82d8 100644
--- a/include/tvm/script/ir_builder/ir.h
+++ b/include/tvm/script/ir_builder/ir.h
@@ -70,10 +70,10 @@ TVM_TIRX_DLL void DefFunction(const ffi::String& func_name,
const BaseFunc& func
* \param annotations The optional annotations of the For statement.
* \return The ForFrame.
*/
-ForFrame For(ForKind kind, PrimExpr start, PrimExpr stop,
- ffi::Optional<PrimExpr> step = std::nullopt,
- ffi::Optional<PrimType> dtype = std::nullopt,
- ffi::Optional<ffi::Map<ffi::String, Any>> annotations =
std::nullopt);
+TVM_TIRX_DLL ForFrame For(ForKind kind, PrimExpr start, PrimExpr stop,
+ ffi::Optional<PrimExpr> step = std::nullopt,
+ ffi::Optional<PrimType> dtype = std::nullopt,
+ ffi::Optional<ffi::Map<ffi::String, Any>>
annotations = std::nullopt);
/*!
* \brief The grid For statement.
@@ -82,8 +82,9 @@ ForFrame For(ForKind kind, PrimExpr start, PrimExpr stop,
* each loop var takes the dtype of its own extent.
* \return The ForFrame.
*/
-ForFrame Grid(ffi::Array<ffi::Variant<PrimExpr, ffi::Tuple<PrimExpr,
PrimExpr>>> extents,
- ffi::Optional<PrimType> dtype = std::nullopt);
+TVM_TIRX_DLL ForFrame
+Grid(ffi::Array<ffi::Variant<PrimExpr, ffi::Tuple<PrimExpr, PrimExpr>>>
extents,
+ ffi::Optional<PrimType> dtype = std::nullopt);
/*!
* \brief The assertion statement.
@@ -92,53 +93,53 @@ ForFrame Grid(ffi::Array<ffi::Variant<PrimExpr,
ffi::Tuple<PrimExpr, PrimExpr>>>
* \param message_parts The error message parts (stored as separate fragments
in the IR).
* \return The AssertFrame.
*/
-AssertFrame Assert(PrimExpr condition, ffi::String error_kind,
- ffi::Array<ffi::String> message_parts);
+TVM_TIRX_DLL AssertFrame Assert(PrimExpr condition, ffi::String error_kind,
+ ffi::Array<ffi::String> message_parts);
/*!
* \brief Create a while loop.
* \param condition The termination condition of the loop.
* \return The result WhileFrame.
*/
-WhileFrame While(PrimExpr condition);
+TVM_TIRX_DLL WhileFrame While(PrimExpr condition);
/*!
* \brief Create a return statement.
* \param value The value to return.
* \return The same statement that was added to the parent frame.
*/
-tvm::Stmt Return(Expr value);
+TVM_TIRX_DLL tvm::Stmt Return(Expr value);
/*!
* \brief Create a break statement.
* \return The same statement that was added to the parent frame.
*/
-tvm::Stmt Break();
+TVM_TIRX_DLL tvm::Stmt Break();
/*!
* \brief Create a continue statement.
* \return The same statement that was added to the parent frame.
*/
-tvm::Stmt Continue();
+TVM_TIRX_DLL tvm::Stmt Continue();
/*!
* \brief Create an if statement.
* \param condition The condition of if statement.
* \return The result IfFrame.
*/
-IfFrame If(PrimExpr condition);
+TVM_TIRX_DLL IfFrame If(PrimExpr condition);
/*!
* \brief Create a then.
* \return The result ThenFrame.
*/
-ThenFrame Then();
+TVM_TIRX_DLL ThenFrame Then();
/*!
* \brief Create an else.
* \return The result ElseFrame.
*/
-ElseFrame Else();
+TVM_TIRX_DLL ElseFrame Else();
/*!
* \brief Construct a result-free region with lexical body parameters.
@@ -147,16 +148,16 @@ ElseFrame Else();
* \param body_params Existing body parameters, or omitted to generate them
from the operation.
* \param attrs Additional operation attributes.
*/
-RegionFrame Region(Op op, ffi::Array<Expr> args,
- ffi::Optional<ffi::Array<Var>> body_params = std::nullopt,
- DictAttrs attrs = DictAttrs());
+TVM_TIRX_DLL RegionFrame Region(Op op, ffi::Array<Expr> args,
+ ffi::Optional<ffi::Array<Var>> body_params =
std::nullopt,
+ DictAttrs attrs = DictAttrs());
/*!
* \brief Evaluate the input expression.
* \param value The input expression to evaluate.
* \return The same statement that was added to the parent frame.
*/
-tvm::Stmt Evaluate(Expr value);
+TVM_TIRX_DLL tvm::Stmt Evaluate(Expr value);
} // namespace ir
} // namespace ir_builder
diff --git a/include/tvm/script/printer/config.h
b/include/tvm/script/printer/config.h
index 440ca25b..7e80f1cc 100644
--- a/include/tvm/script/printer/config.h
+++ b/include/tvm/script/printer/config.h
@@ -108,7 +108,7 @@ class PrinterConfigObj : public ffi::Object {
.def_ro("extra_config", &PrinterConfigObj::extra_config);
}
- ffi::Array<ffi::String> GetBuiltinKeywords();
+ TVM_TIRX_DLL ffi::Array<ffi::String> GetBuiltinKeywords();
static constexpr const bool _type_mutable = true;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("script.PrinterConfig", PrinterConfigObj,
ffi::Object);
@@ -129,7 +129,7 @@ class TVM_TIRX_DLL PrinterConfig : public ffi::ObjectRef {
* address string. Defined in src/script/printer/script_printer.cc so that
* <tvm/runtime/logging.h> is not pulled into this public header.
*/
-TVM_TIRX_DLL std::string RedirectedReprPrinterMethod(const ffi::ObjectRef&
obj);
+TVM_TIRX_DLL ffi::String RedirectedReprPrinterMethod(const ffi::ObjectRef&
obj);
} // namespace tvm
#endif // TVM_SCRIPT_PRINTER_CONFIG_H_
diff --git a/include/tvm/script/printer/printer.h
b/include/tvm/script/printer/printer.h
index b9f76d16..6aef9a47 100644
--- a/include/tvm/script/printer/printer.h
+++ b/include/tvm/script/printer/printer.h
@@ -38,7 +38,7 @@ namespace tvm {
* \param config Optional translation and rendering configuration.
* \return The rendered script or fallback representation.
*/
-TVM_TIRX_DLL std::string Script(const ffi::ObjectRef& node,
+TVM_TIRX_DLL ffi::String Script(const ffi::ObjectRef& node,
const ffi::Optional<PrinterConfig>& config =
std::nullopt);
namespace script {
diff --git a/include/tvm/sym/analyzer.h b/include/tvm/sym/analyzer.h
index ce90fcbb..b889061c 100644
--- a/include/tvm/sym/analyzer.h
+++ b/include/tvm/sym/analyzer.h
@@ -494,7 +494,7 @@ class IntSetAnalyzer {
*/
TVM_TIRX_DLL void Bind(const Var& var, const Range& new_range, bool
allow_override = false);
- std::function<void()> EnterConstraint(const PrimExpr& constraint);
+ TVM_TIRX_DLL std::function<void()> EnterConstraint(const PrimExpr&
constraint);
private:
friend class AnalyzerObj;
@@ -548,7 +548,8 @@ class Z3Prover {
* \param is_assume Whether the constraint comes from an assumption.
* \return an exit function that must be called to cleanup the constraint
can be nullptr.
*/
- std::function<void()> EnterConstraint(const PrimExpr& constraint, bool
is_assume = false);
+ TVM_TIRX_DLL std::function<void()> EnterConstraint(const PrimExpr&
constraint,
+ bool is_assume = false);
/*!
* \brief Get the SMTLIB2 representation of the current context.
@@ -556,28 +557,28 @@ class Z3Prover {
* \param expr The optional expression to check.
* \return The SMTLIB2 string.
*/
- ffi::String GetSMTLIB2(const ffi::Optional<PrimExpr> expr);
+ TVM_TIRX_DLL ffi::String GetSMTLIB2(const ffi::Optional<PrimExpr> expr);
/*!
* \brief Get statistics about Z3 prover.
*
* \return The statistics string.
*/
- ffi::String GetStats();
+ TVM_TIRX_DLL ffi::String GetStats();
/*!
* \brief Set timeout in milliseconds for Z3 prover.
*
* \param timeout_ms The timeout in milliseconds.
*/
- void SetTimeoutMs(unsigned timeout_ms);
+ TVM_TIRX_DLL void SetTimeoutMs(unsigned timeout_ms);
/*!
* \brief Set resource limitation for Z3 prover.
*
* \param rlimit the resource limitation.
*/
- void SetRLimit(unsigned rlimit);
+ TVM_TIRX_DLL void SetRLimit(unsigned rlimit);
/*!
* \brief Get the Z3 model for the given expression if satisfiable.
@@ -585,7 +586,7 @@ class Z3Prover {
* \param expr The expression to get the model for.
* \return The model as a string.
*/
- ffi::String GetModel(const PrimExpr& expr);
+ TVM_TIRX_DLL ffi::String GetModel(const PrimExpr& expr);
/*!
* \brief Count the number of integer values that satisfy the current
constraints.
diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h
index d1a2fe99..5e9300f0 100644
--- a/include/tvm/target/target.h
+++ b/include/tvm/target/target.h
@@ -61,7 +61,7 @@ class TargetObj : public ffi::Object {
* \brief The JSON string representation of the target
* \return JSON string of the target configuration (e.g. {"kind": "llvm",
"mcpu": "cortex-a53"})
*/
- TVM_TIRX_DLL const std::string& str() const;
+ TVM_TIRX_DLL ffi::String str() const;
/*! \return Export target to JSON-like configuration */
TVM_TIRX_DLL ffi::Map<ffi::String, ffi::Any> ToConfig() const;
/*! \return The ffi::Optional<Target> typed target host of the TargetObj */
@@ -77,7 +77,7 @@ class TargetObj : public ffi::Object {
* \return True if the target's `TargetObj::keys` contains the
* specified key, False otherwise.
*/
- TVM_TIRX_DLL bool HasKey(const std::string& query_key) const;
+ TVM_TIRX_DLL bool HasKey(const ffi::String& query_key) const;
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
@@ -139,7 +139,7 @@ class TargetObj : public ffi::Object {
private:
/*! \brief Internal string repr. */
- mutable std::string str_repr_;
+ mutable ffi::String str_repr_;
friend class TargetInternal;
};
@@ -181,10 +181,10 @@ class Target : public ffi::ObjectRef {
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(Target, ffi::ObjectRef,
TargetObj);
- static Target WithHost(const Target& target, const ffi::Optional<Target>&
host);
+ TVM_TIRX_DLL static Target WithHost(const Target& target, const
ffi::Optional<Target>& host);
/*! \return The target with the host stripped out */
- Target WithoutHost() const;
+ TVM_TIRX_DLL Target WithoutHost() const;
private:
// enable with syntax.
diff --git a/include/tvm/tirx/index_map.h b/include/tvm/tirx/index_map.h
index b4e73824..115458f2 100644
--- a/include/tvm/tirx/index_map.h
+++ b/include/tvm/tirx/index_map.h
@@ -27,6 +27,7 @@
#define TVM_TIRX_INDEX_MAP_H_
#include <tvm/ffi/container/array.h>
+#include <tvm/ffi/container/tuple.h>
#include <tvm/ir/expr.h>
#include <tvm/runtime/tensor.h>
@@ -97,7 +98,7 @@ class IndexMapNode : public ffi::Object {
* \returns The indices in the output space. Contains one value for
* each expression in `final_indices`.
*/
- ffi::Array<PrimExpr> MapIndices(const ffi::Array<PrimExpr>& indices) const;
+ TVM_TIRX_DLL ffi::Array<PrimExpr> MapIndices(const ffi::Array<PrimExpr>&
indices) const;
/*!
* \brief Map indices to the output space using an existing analyzer.
*
@@ -122,7 +123,7 @@ class IndexMapNode : public ffi::Object {
* \returns The ranges in the output space. Contains one value for
* each expression in `final_indices`.
*/
- ffi::Array<Range> MapRanges(const ffi::Array<Range>& ranges) const;
+ TVM_TIRX_DLL ffi::Array<Range> MapRanges(const ffi::Array<Range>& ranges)
const;
/*! \brief Map a memory range to the output space using an existing analyzer.
*
* If contiguous memory locations in the input space are not
@@ -136,7 +137,8 @@ class IndexMapNode : public ffi::Object {
* \returns The ranges in the output space. Contains one value for
* each expression in `final_indices`.
*/
- ffi::Array<Range> MapRanges(const ffi::Array<Range>& ranges, const
sym::Analyzer& analyzer) const;
+ TVM_TIRX_DLL ffi::Array<Range> MapRanges(const ffi::Array<Range>& ranges,
+ const sym::Analyzer& analyzer)
const;
/*! \brief Map a tensor shape to the output space using a fresh analyzer.
*
@@ -145,7 +147,7 @@ class IndexMapNode : public ffi::Object {
* \returns The tensor shape in the output space. Contains one
* value for each expression in `final_indices`.
*/
- ffi::Array<PrimExpr> MapShape(const ffi::Array<PrimExpr>& shape) const;
+ TVM_TIRX_DLL ffi::Array<PrimExpr> MapShape(const ffi::Array<PrimExpr>&
shape) const;
/*! \brief Map a tensor shape to the output space using an existing analyzer.
*
* \param shape The tensor shape in the input space. Should contain
@@ -163,7 +165,7 @@ class IndexMapNode : public ffi::Object {
*
* \returns The transformed Tensor.
*/
- ffi::Tensor MapTensor(ffi::Tensor arr_src) const;
+ TVM_TIRX_DLL ffi::Tensor MapTensor(ffi::Tensor arr_src) const;
/*!
* \brief Convert to string representation in Python.
@@ -171,7 +173,8 @@ class IndexMapNode : public ffi::Object {
* \return The stringified lambda expression in Python.
*/
TVM_TIRX_DLL ffi::String ToPythonString(
- const std::function<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map = nullptr) const;
+ const ffi::TypedFunction<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map =
+ nullptr) const;
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
@@ -218,7 +221,7 @@ class IndexMap : public ffi::ObjectRef {
* assumed to be correct and bijective, and is returned.
* \param initial_ranges The ranges of the input indices.
*/
- IndexMap Inverse(ffi::Array<Range> initial_ranges) const;
+ TVM_TIRX_DLL IndexMap Inverse(ffi::Array<Range> initial_ranges) const;
/*! \brief Generate the inverse mapping using an existing analyzer.
*
* The range of the input indices is required in order to ensure
@@ -241,8 +244,9 @@ class IndexMap : public ffi::ObjectRef {
* \param f_name_map The optional name map to rename the variables.
* \return The renamed index map.
*/
- TVM_TIRX_DLL IndexMap RenameVariables(
- const std::function<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map = nullptr) const;
+ TVM_TIRX_DLL IndexMap
+ RenameVariables(const ffi::TypedFunction<ffi::Optional<ffi::String>(const
Var& var)>& f_name_map =
+ nullptr) const;
/*! \brief Generate the inverse mapping using a fresh analyzer.
*
@@ -254,7 +258,8 @@ class IndexMap : public ffi::ObjectRef {
* \return The inverted index map, along with the predicate for
* which the inverse maps to a valid range.
*/
- std::pair<IndexMap, PrimExpr> NonSurjectiveInverse(ffi::Array<Range>
initial_ranges) const;
+ TVM_TIRX_DLL ffi::Tuple<IndexMap, PrimExpr> NonSurjectiveInverse(
+ ffi::Array<Range> initial_ranges) const;
/*! \brief Generate the inverse mapping using an existing analyzer.
*
* Determine the inverse, where the output range may contain
@@ -267,7 +272,7 @@ class IndexMap : public ffi::ObjectRef {
* \return The inverted index map, along with the predicate for
* which the inverse maps to a valid range.
*/
- TVM_TIRX_DLL std::pair<IndexMap, PrimExpr> NonSurjectiveInverse(
+ TVM_TIRX_DLL ffi::Tuple<IndexMap, PrimExpr> NonSurjectiveInverse(
ffi::Array<Range> initial_ranges, const sym::Analyzer& analyzer) const;
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IndexMap, ffi::ObjectRef,
IndexMapNode);
diff --git a/include/tvm/tirx/layout.h b/include/tvm/tirx/layout.h
index 7c2527ce..1085dd90 100644
--- a/include/tvm/tirx/layout.h
+++ b/include/tvm/tirx/layout.h
@@ -85,22 +85,31 @@ using FAxisFuser =
ffi::TypedFunction<ffi::Optional<Iter>(Target, ThreadScope, T
class AxisNode : public ffi::EnumObj {
public:
/*! \brief Check if the axis is a thread axis. */
- bool IsThreadAxis() const;
+ bool IsThreadAxis() const {
+ static ffi::reflection::TypeAttrColumn
state_column(ffi::type_attr::kEnumState);
+ static ffi::EnumState state =
+
ffi::Any(state_column[_GetOrAllocRuntimeTypeIndex()]).as_or_throw<ffi::EnumState>();
+ auto column = state->attrs.Get("thread");
+ auto thread = column ? column->Get(ffi::GetRef<ffi::ObjectRef>(this)) :
std::nullopt;
+ TVM_FFI_ICHECK(thread.has_value())
+ << "Axis '" << _str_index << "' has no thread classification";
+ return thread->cast<bool>();
+ }
/*! \brief Check if the axis is a memory axis. */
- bool IsMemoryAxis() const;
+ bool IsMemoryAxis() const { return !IsThreadAxis(); }
/*! \brief The backend owning this axis, if any. */
- ffi::Optional<ffi::String> GetBackend() const;
+ TVM_TIRX_DLL ffi::Optional<ffi::String> GetBackend() const;
/*! \brief Get the scope of the (thread) axis. */
- ffi::Optional<ThreadScope> GetScope() const;
+ TVM_TIRX_DLL ffi::Optional<ThreadScope> GetScope() const;
/*! \brief Get the subscope of the (thread) axis. */
- ffi::Optional<ThreadScope> GetSubscope() const;
+ TVM_TIRX_DLL ffi::Optional<ThreadScope> GetSubscope() const;
/*! \brief Get the fuser of the (thread) axis. */
- ffi::Optional<FAxisFuser> GetFuser() const;
+ TVM_TIRX_DLL ffi::Optional<FAxisFuser> GetFuser() const;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("tirx.Axis", AxisNode, ffi::EnumObj);
};
diff --git a/include/tvm/tirx/script/ir_builder/frame.h
b/include/tvm/tirx/script/ir_builder/frame.h
index bbef2c86..01427e4e 100644
--- a/include/tvm/tirx/script/ir_builder/frame.h
+++ b/include/tvm/tirx/script/ir_builder/frame.h
@@ -29,7 +29,6 @@
#include <tvm/tirx/stmt.h>
#include <tvm/tirx/tile/thread_scope.h>
-#include <functional>
#include <utility>
namespace tvm {
@@ -86,7 +85,7 @@ class TVM_TIRX_DLL FunctionFrameObj : public ir::StmtFrameObj
{
void ExitWithScope() final;
/*! \brief Register validation for an extension-owned function attribute. */
- using AttrValidator = std::function<void(const FunctionFrameObj*, const
ffi::Any&)>;
+ using AttrValidator = ffi::TypedFunction<void(const FunctionFrameObj*, const
ffi::Any&)>;
static void RegisterAttrValidator(ffi::String key, AttrValidator validator);
void ValidateAttrs() const;
diff --git a/include/tvm/tirx/script/ir_builder/ir.h
b/include/tvm/tirx/script/ir_builder/ir.h
index d7000095..c16c189f 100644
--- a/include/tvm/tirx/script/ir_builder/ir.h
+++ b/include/tvm/tirx/script/ir_builder/ir.h
@@ -49,8 +49,8 @@ using tvm::tirx::ThreadScope;
* \brief The primitive function statement.
* \return The FunctionFrame.
*/
-FunctionFrame Function(bool is_private = false, bool persistent = false,
- bool is_declaration = false);
+TVM_TIRX_DLL FunctionFrame Function(bool is_private = false, bool persistent =
false,
+ bool is_declaration = false);
/*!
* \brief The Function variable arguments adding function.
@@ -58,7 +58,7 @@ FunctionFrame Function(bool is_private = false, bool
persistent = false,
* \param var The variable argument.
* \return The variable.
*/
-Var Arg(ffi::String name, Var var);
+TVM_TIRX_DLL Var Arg(ffi::String name, Var var);
/*!
* \brief The Function tensor arguments adding function.
@@ -66,26 +66,26 @@ Var Arg(ffi::String name, Var var);
* \param tensor The tensor argument.
* \return The tensor.
*/
-TensorVar Arg(ffi::String name, TensorVar tensor);
+TVM_TIRX_DLL TensorVar Arg(ffi::String name, TensorVar tensor);
/*!
* \brief The Function naming statement.
* \param name The name of the Function.
*/
-void FuncName(ffi::String name);
+TVM_TIRX_DLL void FuncName(ffi::String name);
/*!
* \brief The Function annotation statement.
* \param attrs The annotations of the Function.
*/
-void FuncAttrs(ffi::Map<ffi::String, ffi::Any> attrs);
+TVM_TIRX_DLL void FuncAttrs(ffi::Map<ffi::String, ffi::Any> attrs);
/*!
* \brief The Function return type statement.
* \param ret_type The return type of the Function.
* \return The return type.
*/
-Type FuncRet(Type ret_type);
+TVM_TIRX_DLL Type FuncRet(Type ret_type);
/*!
* \brief Store data in a tensor destination.
@@ -94,7 +94,7 @@ Type FuncRet(Type ret_type);
* \param value The value to be stored.
* \return The same statement that was added to the parent frame.
*/
-tvm::Stmt TensorStore(Expr dest, ffi::Array<PrimExpr> indices, PrimExpr value);
+TVM_TIRX_DLL tvm::Stmt TensorStore(Expr dest, ffi::Array<PrimExpr> indices,
PrimExpr value);
/*!
* \brief Create a TIR var that represents a pointer
diff --git a/include/tvm/tirx/stmt_functor.h b/include/tvm/tirx/stmt_functor.h
index bf7d59c2..d532e8fc 100644
--- a/include/tvm/tirx/stmt_functor.h
+++ b/include/tvm/tirx/stmt_functor.h
@@ -294,7 +294,7 @@ class TVM_TIRX_DLL StmtExprMutator : public
tvm::ExprMutator {
* \return The result.
*/
TVM_TIRX_DLL Stmt SubstituteWithDataTypeLegalization(
- Stmt stmt, std::function<ffi::Optional<PrimExpr>(const Var&)> vmap);
+ Stmt stmt, ffi::TypedFunction<ffi::Optional<PrimExpr>(const Var&)> vmap);
/*!
* \brief Substitute the var specified by vmap and legalize data types after
substitution.
@@ -306,7 +306,7 @@ TVM_TIRX_DLL Stmt SubstituteWithDataTypeLegalization(
* \return The result.
*/
TVM_TIRX_DLL PrimExpr SubstituteWithDataTypeLegalization(
- PrimExpr expr, std::function<ffi::Optional<PrimExpr>(const Var&)> vmap);
+ PrimExpr expr, ffi::TypedFunction<ffi::Optional<PrimExpr>(const Var&)>
vmap);
/*!
* \brief Check if the statement contains the specified node type.
diff --git a/include/tvm/tirx/tile/context.h b/include/tvm/tirx/tile/context.h
index dc44797f..97bff8b4 100644
--- a/include/tvm/tirx/tile/context.h
+++ b/include/tvm/tirx/tile/context.h
@@ -104,20 +104,20 @@ class DispatchContextObj : public ffi::Object {
}
/*! \brief Add a tensor to be allocated in the kernel. */
- void AddAllocTensor(TensorVar tensor, ffi::Array<PrimExpr> allocated_addr =
{},
- ffi::Map<ffi::String, ffi::Any> annotations = {});
+ TVM_TIRX_DLL void AddAllocTensor(TensorVar tensor, ffi::Array<PrimExpr>
allocated_addr = {},
+ ffi::Map<ffi::String, ffi::Any> annotations
= {});
/*! \brief Add an initialization statement to be inserted. */
- void AddInitStmt(Stmt stmt, bool host = false);
+ TVM_TIRX_DLL void AddInitStmt(Stmt stmt, bool host = false);
/*! \brief Add a statement to be inserted after a tensor's definition. */
- void AddPostTensorDefStmt(TensorVar tensor, Stmt stmt);
+ TVM_TIRX_DLL void AddPostTensorDefStmt(TensorVar tensor, Stmt stmt);
/*! \brief Set a value in the shared state cache. */
- void SharedStateSet(ffi::String key, ffi::ObjectRef value);
+ TVM_TIRX_DLL void SharedStateSet(ffi::String key, ffi::ObjectRef value);
/*! \brief Get a value from the shared state cache. */
- ffi::Optional<ffi::ObjectRef> SharedStateGet(ffi::String key);
+ TVM_TIRX_DLL ffi::Optional<ffi::ObjectRef> SharedStateGet(ffi::String key);
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("tirx.DispatchContext",
DispatchContextObj, ffi::Object);
};
diff --git a/include/tvm/tirx/transform.h b/include/tvm/tirx/transform.h
index 1fe81fee..cca75c53 100644
--- a/include/tvm/tirx/transform.h
+++ b/include/tvm/tirx/transform.h
@@ -49,19 +49,38 @@ using tvm::transform::Sequential;
/*! \brief Wrap a function body in a device scope region. */
TVM_TIRX_DLL Pass DecorateDeviceScope();
-/*
- * \brief Create a function pass that optimizes Functions.
+/*!
+ * \brief Create a function pass from an owning FFI callback.
*
- * \param pass_func The packed function that contains the optimization.
+ * \param pass_func The callback that transforms each function, returning
std::nullopt to remove it.
* \param opt_level The optimization level of the function pass.
* \param name The name of the function pass.
- *
* \return The created function pass.
*/
TVM_TIRX_DLL Pass CreateFunctionPass(
- std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func,
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ pass_func,
int opt_level, ffi::String name);
+/*!
+ * \brief Create a function pass from a native C++ callback.
+ *
+ * \param pass_func The callback that transforms each function, returning
std::nullopt to remove it.
+ * \param opt_level The optimization level of the function pass.
+ * \param name The name of the function pass.
+ * \return The created function pass.
+ */
+inline Pass CreateFunctionPass(
+ std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func,
+ int opt_level, ffi::String name) {
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ callback = [pass_func = std::move(pass_func)](ffi::RValueRef<Function>
func, IRModule mod,
+ PassContext ctx) ->
ffi::Optional<Function> {
+ return pass_func(*std::move(func), std::move(mod), std::move(ctx));
+ };
+ return CreateFunctionPass(std::move(callback), opt_level, std::move(name));
+}
+
/*!
* \brief Lower vectorization loops.
*
diff --git a/include/tvm/tirx/type.h b/include/tvm/tirx/type.h
index 1cd7a1e3..ddcc10f9 100644
--- a/include/tvm/tirx/type.h
+++ b/include/tvm/tirx/type.h
@@ -111,7 +111,7 @@ class TensorTypeNode : public TypeNode {
TVM_TIRX_DLL bool IsScalar(bool alloc_or_decl = true) const;
/*! \brief Return the constant element count, or nullopt for symbolic
extents or overflow. */
- TVM_TIRX_DLL std::optional<int64_t> ConstantAllocationSize() const;
+ TVM_TIRX_DLL ffi::Optional<int64_t> ConstantAllocationSize() const;
/*! \brief Determine the offset in the tensor of the given index.
*
diff --git a/src/codegen/module_export.cc b/src/codegen/module_export.cc
index 098afbf4..a500cd22 100644
--- a/src/codegen/module_export.cc
+++ b/src/codegen/module_export.cc
@@ -269,8 +269,8 @@ std::string PackImportsToBytes(const ffi::Module& mod) {
} // namespace
-std::string PackImportsToC(const ffi::Module& mod, bool system_lib,
- const std::string& c_symbol_prefix) {
+ffi::String PackImportsToC(const ffi::Module& mod, bool system_lib,
+ const ffi::String& c_symbol_prefix) {
if (c_symbol_prefix.length() != 0) {
TVM_FFI_ICHECK(system_lib)
<< "c_symbol_prefix advanced option should be used in conjuction with
system-lib";
@@ -314,8 +314,8 @@ std::string PackImportsToC(const ffi::Module& mod, bool
system_lib,
}
void PackImportsToObjectFile(const ffi::Module& mod, bool system_lib,
- const std::string& llvm_target_string, const
std::string& file_name,
- const std::string& c_symbol_prefix) {
+ const ffi::String& llvm_target_string, const
ffi::String& file_name,
+ const ffi::String& c_symbol_prefix) {
if (c_symbol_prefix.length() != 0) {
TVM_FFI_ICHECK(system_lib)
<< "c_symbol_prefix advanced option should be used in conjuction with
system-lib";
diff --git a/src/ir/transform.cc b/src/ir/transform.cc
index 96773b29..80a7cda7 100644
--- a/src/ir/transform.cc
+++ b/src/ir/transform.cc
@@ -107,7 +107,7 @@ bool PassContext::PassEnabled(const PassInfo& info) const {
class PassConfigManager {
public:
void Register(std::string key, ffi::String value_type_str,
- std::function<ffi::Any(ffi::Any)> legalization) {
+ ffi::TypedFunction<ffi::Any(ffi::Any)> legalization) {
TVM_FFI_ICHECK_EQ(key2vtype_.count(key), 0U);
ValueTypeInfo info;
info.type_str = value_type_str;
@@ -135,7 +135,7 @@ class PassConfigManager {
TVM_FFI_CHECK(value != nullptr, AttributeError) << key << " is None";
- TVM_FFI_CHECK(info.legalization, AttributeError)
+ TVM_FFI_CHECK(info.legalization != nullptr, AttributeError)
<< "Config option \'" << key << "\' was defined without a
legalization function.";
auto legalized = info.legalization(value);
if (!legalized.same_as(value)) {
@@ -165,14 +165,14 @@ class PassConfigManager {
private:
struct ValueTypeInfo {
std::string type_str;
- std::function<ffi::Any(ffi::Any)> legalization;
+ ffi::TypedFunction<ffi::Any(ffi::Any)> legalization;
};
std::unordered_map<std::string, ValueTypeInfo> key2vtype_;
};
void PassContext::RegisterConfigOption(const char* key, ffi::String
value_type_str,
- std::function<ffi::Any(ffi::Any)>
legalization) {
+ ffi::TypedFunction<ffi::Any(ffi::Any)>
legalization) {
PassConfigManager::Global()->Register(key, value_type_str, legalization);
}
@@ -430,7 +430,7 @@ class ModulePassObj : public PassObj {
* implement the algorithm in the `pass_func` and let it run on a module. It
* will then remove the dead code including the unused functions in the
module.
*/
- std::function<IRModule(IRModule, PassContext)> pass_func;
+ ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>, PassContext)>
pass_func;
explicit ModulePassObj(PassInfo pass_info) : pass_info(std::move(pass_info))
{}
explicit ModulePassObj(ffi::UnsafeInit tag) : pass_info(tag) {}
@@ -459,7 +459,8 @@ class ModulePassObj : public PassObj {
class ModulePass : public Pass {
public:
- ModulePass(std::function<IRModule(IRModule, PassContext)> pass_func,
PassInfo pass_info);
+ ModulePass(ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>,
PassContext)> pass_func,
+ PassInfo pass_info);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(ModulePass, Pass,
ModulePassObj);
};
@@ -471,7 +472,9 @@ PassInfo::PassInfo(int opt_level, ffi::String name) {
data_ = std::move(pass_info);
}
-ModulePass::ModulePass(std::function<IRModule(IRModule, PassContext)>
pass_func, PassInfo pass_info)
+ModulePass::ModulePass(
+ ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>, PassContext)>
pass_func,
+ PassInfo pass_info)
: Pass(ffi::UnsafeInit{}) {
auto n = ffi::make_object<ModulePassObj>(std::move(pass_info));
n->pass_func = std::move(pass_func);
@@ -491,7 +494,7 @@ IRModule ModulePassObj::operator()(IRModule mod, const
PassContext& pass_ctx) co
// TVMScript-rendered location.
IRModule input_mod = mod;
try {
- mod = pass_func(std::move(mod), pass_ctx);
+ mod = pass_func(ffi::RValueRef<IRModule>(std::move(mod)), pass_ctx);
} catch (ffi::Error& err) {
throw EnrichPassErrorWithContext(err, input_mod, pass_info->name);
}
@@ -513,10 +516,6 @@ Sequential::Sequential(tvm::ffi::Array<Pass> passes,
ffi::String name) : Pass(ff
data_ = std::move(n);
}
-const SequentialObj* Sequential::operator->() const {
- return static_cast<const SequentialObj*>(get());
-}
-
IRModule SequentialObj::operator()(IRModule mod, const PassContext& pass_ctx)
const {
for (const Pass& pass : passes) {
VLOG(0) << "Running pass " << pass->Info()->name;
@@ -532,8 +531,8 @@ IRModule SequentialObj::operator()(IRModule mod, const
PassContext& pass_ctx) co
return mod;
}
-Pass CreateModulePass(std::function<IRModule(IRModule, PassContext)>
pass_func, int opt_level,
- ffi::String name) {
+Pass CreateModulePass(ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>,
PassContext)> pass_func,
+ int opt_level, ffi::String name) {
PassInfo pass_info = PassInfo(opt_level, name);
return ModulePass(std::move(pass_func), pass_info);
}
@@ -563,12 +562,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
refl::GlobalDef()
.def("transform.MakeModulePass",
[](ffi::TypedFunction<IRModule(ffi::RValueRef<IRModule>,
PassContext)> pass_func,
- PassInfo pass_info) {
- auto wrapped_pass_func = [pass_func](IRModule mod, PassContext
ctx) {
- return pass_func(ffi::RValueRef<IRModule>(std::move(mod)), ctx);
- };
- return ModulePass(wrapped_pass_func, pass_info);
- })
+ PassInfo pass_info) { return ModulePass(std::move(pass_func),
pass_info); })
.def("transform.RunPass",
[](Pass pass, ffi::RValueRef<IRModule> mod) { return
pass(*std::move(mod)); });
}
diff --git a/src/runtime/logging.cc b/src/runtime/logging.cc
index 388902ee..847d9b12 100644
--- a/src/runtime/logging.cc
+++ b/src/runtime/logging.cc
@@ -136,16 +136,6 @@ LogFatal::Entry& LogFatal::GetEntry() {
return result;
}
-std::string VLogContext::str() const {
- std::stringstream result;
- for (const auto* entry : context_stack_) {
- TVM_FFI_ICHECK_NOTNULL(entry);
- result << entry->str();
- result << ": ";
- }
- return result.str();
-}
-
} // namespace detail
} // namespace runtime
} // namespace tvm
diff --git a/src/script/printer/printer.cc b/src/script/printer/printer.cc
index 58d8f52a..833b35ea 100644
--- a/src/script/printer/printer.cc
+++ b/src/script/printer/printer.cc
@@ -457,7 +457,7 @@ std::string RenderFallbackWithInvisiblePathInfo(const
ffi::String& script,
} // namespace
-std::string Script(const ffi::ObjectRef& node, const
ffi::Optional<PrinterConfig>& cfg) {
+ffi::String Script(const ffi::ObjectRef& node, const
ffi::Optional<PrinterConfig>& cfg) {
PrinterConfig config = cfg.value_or(PrinterConfig());
static ffi::reflection::TypeAttrColumn translate(
tvm::script::printer::type_attr::kDocTranslate.name);
@@ -467,15 +467,15 @@ std::string Script(const ffi::ObjectRef& node, const
ffi::Optional<PrinterConfig
!node.as<TypeNode>())) {
return RenderFallbackWithInvisiblePathInfo(ffi::ReprPrint(ffi::Any(node)),
config);
}
- return std::string(script::printer::RenderScript(node, config));
+ return script::printer::RenderScript(node, config);
}
-std::string RedirectedReprPrinterMethod(const ffi::ObjectRef& obj) {
+ffi::String RedirectedReprPrinterMethod(const ffi::ObjectRef& obj) {
try {
PrinterConfig config;
config->extra_config.Set("ir.comment_imports", true);
// Call translation directly so an unsupported type cannot recurse through
ffi repr.
- return std::string(script::printer::RenderScript(obj, config));
+ return script::printer::RenderScript(obj, config);
} catch (const tvm::ffi::Error& e) {
LOG(WARNING) << "TVMScript printer falls back to the basic address printer
with the error:\n"
<< e.what();
diff --git a/src/sym/const_int_bound.cc b/src/sym/const_int_bound.cc
index ff335127..1ce9aa17 100644
--- a/src/sym/const_int_bound.cc
+++ b/src/sym/const_int_bound.cc
@@ -878,9 +878,13 @@ ConstIntBound ConstIntBoundAnalyzer::operator()(const
PrimExpr& expr) const {
}
ConstIntBound ConstIntBoundAnalyzer::operator()(const PrimExpr& expr,
BoundMapType* bound) {
+ struct RestoreMemo {
+ Impl* impl;
+ BoundMapType* previous;
+ ~RestoreMemo() { impl->bound_ = previous; }
+ } restore{impl_.get(), impl_->bound_};
impl_->bound_ = bound;
Entry ret = impl_->Dispatch(expr);
- impl_->bound_ = nullptr;
return ConstIntBound(ret.min_value, ret.max_value);
}
diff --git a/src/target/target.cc b/src/target/target.cc
index e0fcabfa..56dee045 100644
--- a/src/target/target.cc
+++ b/src/target/target.cc
@@ -93,9 +93,9 @@ static TargetKind GetTargetKind(const ffi::String& name) {
return kind.value();
}
-const std::string& TargetObj::str() const {
+ffi::String TargetObj::str() const {
if (str_repr_.empty()) {
- str_repr_ = std::string(ffi::json::Stringify(ToConfig()));
+ str_repr_ = ffi::json::Stringify(ToConfig());
}
return str_repr_;
}
@@ -176,7 +176,7 @@ int TargetObj::GetTargetDeviceType() const {
return kind->default_device_type;
}
-bool TargetObj::HasKey(const std::string& query_key) const {
+bool TargetObj::HasKey(const ffi::String& query_key) const {
return std::any_of(keys.begin(), keys.end(),
[&query_key](const auto& key) { return key == query_key;
});
}
diff --git a/src/tirx/ir/index_map.cc b/src/tirx/ir/index_map.cc
index fcbeac6e..b28003ff 100644
--- a/src/tirx/ir/index_map.cc
+++ b/src/tirx/ir/index_map.cc
@@ -67,10 +67,10 @@ IndexMap IndexMap::FromFunc(int ndim,
return IndexMap(initial_indices, func(callback_indices),
std::move(inverse_index_map));
}
-std::pair<IndexMap, PrimExpr> IndexMapInverseImpl(const IndexMap& self,
- const ffi::Array<Range>&
initial_ranges,
- sym::IterMapLevel
check_level,
- sym::AnalyzerObj* analyzer) {
+ffi::Tuple<IndexMap, PrimExpr> IndexMapInverseImpl(const IndexMap& self,
+ const ffi::Array<Range>&
initial_ranges,
+ sym::IterMapLevel
check_level,
+ sym::AnalyzerObj* analyzer)
{
TVM_FFI_ICHECK(analyzer != nullptr);
sym::Analyzer analyzer_ref = ffi::GetRef<sym::Analyzer>(analyzer);
if (self->inverse_index_map.has_value()) {
@@ -78,7 +78,7 @@ std::pair<IndexMap, PrimExpr> IndexMapInverseImpl(const
IndexMap& self,
// case, the user-defined inverse is assumed to be correct and
// bijective.
PrimExpr padding_predicate = IntImm::Bool(false);
- return {self->inverse_index_map.value().as_or_throw<IndexMap>(),
padding_predicate};
+ return ffi::Tuple(self->inverse_index_map.value().as_or_throw<IndexMap>(),
padding_predicate);
}
// Dummy variables to represent the inverse's inputs.
@@ -158,17 +158,17 @@ std::pair<IndexMap, PrimExpr> IndexMapInverseImpl(const
IndexMap& self,
padding_predicate = output_var_analyzer->Simplify(padding_predicate, 10);
}
- return {IndexMap(output_vars, inverse_exprs), padding_predicate};
+ return ffi::Tuple(IndexMap(output_vars, inverse_exprs), padding_predicate);
}
-std::pair<IndexMap, PrimExpr> IndexMap::NonSurjectiveInverse(
+ffi::Tuple<IndexMap, PrimExpr> IndexMap::NonSurjectiveInverse(
ffi::Array<Range> initial_ranges) const {
sym::Analyzer analyzer;
return NonSurjectiveInverse(initial_ranges, analyzer);
}
-std::pair<IndexMap, PrimExpr> IndexMap::NonSurjectiveInverse(ffi::Array<Range>
initial_ranges,
- const
sym::Analyzer& analyzer) const {
+ffi::Tuple<IndexMap, PrimExpr>
IndexMap::NonSurjectiveInverse(ffi::Array<Range> initial_ranges,
+ const
sym::Analyzer& analyzer) const {
return IndexMapInverseImpl(*this, initial_ranges,
sym::IterMapLevel::NoCheck, analyzer.get());
}
@@ -205,7 +205,7 @@ ffi::Array<PrimExpr> IndexMapNode::MapIndices(const
ffi::Array<PrimExpr>& indice
ffi::Array<PrimExpr> output = final_indices.Map([&](PrimExpr index) {
PrimExpr result = SubstituteWithDataTypeLegalization(
- std::move(index), [&](const Var& var) { return vmap.Get(var); });
+ std::move(index), [&](const Var& var) -> ffi::Optional<PrimExpr> {
return vmap.Get(var); });
return analyzer_ptr->Simplify(result);
});
return output;
@@ -363,7 +363,7 @@ ffi::Tensor IndexMapNode::MapTensor(ffi::Tensor arr_src)
const {
}
IndexMap IndexMap::RenameVariables(
- const std::function<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map) const {
+ const ffi::TypedFunction<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map) const {
std::unordered_set<std::string> used_names;
ffi::Map<Var, Var> var_remap;
UniqueNameSupply name_supply;
@@ -461,7 +461,7 @@ std::string IndexMap2PythonLambdaExpr(const
ffi::Array<PrimVar>& initial_indices
}
ffi::String IndexMapNode::ToPythonString(
- const std::function<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map) const {
+ const ffi::TypedFunction<ffi::Optional<ffi::String>(const Var& var)>&
f_name_map) const {
auto index_map = ffi::GetRef<IndexMap>(this).RenameVariables(f_name_map);
std::string lambda_expr =
IndexMap2PythonLambdaExpr(index_map->initial_indices,
index_map->final_indices);
@@ -516,7 +516,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
ffi::Optional<sym::Analyzer> opt_analyzer) {
sym::Analyzer analyzer = opt_analyzer.has_value() ?
opt_analyzer.value() : sym::Analyzer();
auto result = forward.NonSurjectiveInverse(initial_ranges, analyzer);
- return ffi::Array<ffi::ObjectRef>{result.first, result.second};
+ return ffi::Array<ffi::ObjectRef>{result.get<0>(), result.get<1>()};
});
}
diff --git a/src/tirx/ir/layout/axis_registry.cc
b/src/tirx/ir/layout/axis_registry.cc
index df5bae9c..c614b96c 100644
--- a/src/tirx/ir/layout/axis_registry.cc
+++ b/src/tirx/ir/layout/axis_registry.cc
@@ -52,18 +52,6 @@ ffi::Optional<T> AxisAttr(const AxisNode* axis, const char*
key) {
return value.value().cast<T>();
}
-bool AxisNode::IsThreadAxis() const {
- auto thread = AxisAttr<bool>(this, "thread");
- TVM_FFI_ICHECK(thread.has_value()) << "Axis '" << _str_index << "' has no
thread classification";
- return thread.value();
-}
-
-bool AxisNode::IsMemoryAxis() const {
- auto thread = AxisAttr<bool>(this, "thread");
- TVM_FFI_ICHECK(thread.has_value()) << "Axis '" << _str_index << "' has no
thread classification";
- return !thread.value();
-}
-
ffi::Optional<ffi::String> AxisNode::GetBackend() const {
return AxisAttr<ffi::String>(this, "backend");
}
diff --git a/src/tirx/ir/stmt_functor.cc b/src/tirx/ir/stmt_functor.cc
index 8034176c..a10adb8c 100644
--- a/src/tirx/ir/stmt_functor.cc
+++ b/src/tirx/ir/stmt_functor.cc
@@ -443,8 +443,8 @@ class IRSubstituteWithDataTypeLegalization : public
DataTypeLegalizer {
}
};
-Stmt SubstituteWithDataTypeLegalization(Stmt stmt,
-
std::function<ffi::Optional<PrimExpr>(const Var&)> vmap) {
+Stmt SubstituteWithDataTypeLegalization(
+ Stmt stmt, ffi::TypedFunction<ffi::Optional<PrimExpr>(const Var&)> vmap) {
auto general_vmap = [vmap = std::move(vmap)](const Var& var) ->
ffi::Optional<Expr> {
if (auto replacement = vmap(var)) return Expr(replacement.value());
return std::nullopt;
@@ -455,7 +455,7 @@ Stmt SubstituteWithDataTypeLegalization(Stmt stmt,
}
PrimExpr SubstituteWithDataTypeLegalization(
- PrimExpr expr, std::function<ffi::Optional<PrimExpr>(const Var&)> vmap) {
+ PrimExpr expr, ffi::TypedFunction<ffi::Optional<PrimExpr>(const Var&)>
vmap) {
auto general_vmap = [vmap = std::move(vmap)](const Var& var) ->
ffi::Optional<Expr> {
if (auto replacement = vmap(var)) return Expr(replacement.value());
return std::nullopt;
diff --git a/src/tirx/ir/transform.cc b/src/tirx/ir/transform.cc
index 051d1595..3b841cac 100644
--- a/src/tirx/ir/transform.cc
+++ b/src/tirx/ir/transform.cc
@@ -64,7 +64,8 @@ class FunctionPassObj : public PassObj {
PassInfo pass_info;
/*! \brief The pass function called on each. */
- std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func;
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ pass_func;
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
@@ -96,14 +97,16 @@ class FunctionPass : public Pass {
* \param pass_info The pass info.
*/
TVM_TIRX_DLL FunctionPass(
- std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func,
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ pass_func,
PassInfo pass_info);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(FunctionPass, Pass,
FunctionPassObj);
};
FunctionPass::FunctionPass(
- std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func,
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ pass_func,
PassInfo pass_info)
: Pass(ffi::UnsafeInit{}) {
auto n = ffi::make_object<FunctionPassObj>(std::move(pass_info));
@@ -126,7 +129,7 @@ IRModule FunctionPassObj::operator()(IRModule mod, const
PassContext& pass_ctx)
// use move semantics as follows to avoid only copy.
kv.second.reset();
Function func = *std::move(opt_func);
- auto updated = pass_func(std::move(func), mod, pass_ctx);
+ auto updated = pass_func(ffi::RValueRef<Function>(std::move(func)), mod,
pass_ctx);
kv.second = Any(std::move(updated));
if (kv.second == nullptr) {
deleted_list.push_back(kv.first.as_or_throw<GlobalVar>());
@@ -144,7 +147,8 @@ IRModule FunctionPassObj::operator()(IRModule mod, const
PassContext& pass_ctx)
}
Pass CreateFunctionPass(
- std::function<ffi::Optional<Function>(Function, IRModule, PassContext)>
pass_func,
+ ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule, PassContext)>
+ pass_func,
int opt_level, ffi::String name) {
PassInfo pass_info = PassInfo(opt_level, name);
return FunctionPass(std::move(pass_func), pass_info);
@@ -155,15 +159,11 @@ TVM_FFI_STATIC_INIT_BLOCK() {
FunctionPassObj::RegisterReflection(); }
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::GlobalDef().def(
- "tirx.transform.CreateFunctionPass",
[](ffi::TypedFunction<ffi::Optional<Function>(
- ffi::RValueRef<Function>,
IRModule, PassContext)>
- pass_func,
- PassInfo pass_info) {
- auto wrapped_pass_func = [pass_func](Function func, IRModule mod,
PassContext ctx) {
- return pass_func(ffi::RValueRef<Function>(std::move(func)), mod,
ctx);
- };
- return FunctionPass(wrapped_pass_func, pass_info);
- });
+ "tirx.transform.CreateFunctionPass",
+ [](ffi::TypedFunction<ffi::Optional<Function>(ffi::RValueRef<Function>,
IRModule,
+ PassContext)>
+ pass_func,
+ PassInfo pass_info) { return FunctionPass(std::move(pass_func),
pass_info); });
}
// Pattern A (RM): auto-default repr from reflection.
diff --git a/src/tirx/ir/type.cc b/src/tirx/ir/type.cc
index e8754ad4..8839eb80 100644
--- a/src/tirx/ir/type.cc
+++ b/src/tirx/ir/type.cc
@@ -68,7 +68,7 @@ bool TensorTypeNode::IsScalar(bool alloc_or_decl) const {
layout.value().Canonicalize().as_or_throw<TileLayout>().IsTrivial()));
}
-std::optional<int64_t> TensorTypeNode::ConstantAllocationSize() const {
+ffi::Optional<int64_t> TensorTypeNode::ConstantAllocationSize() const {
int64_t result = 1;
for (const PrimExpr& extent : shape) {
const auto* size = extent.as<IntImmNode>();