tvm
Loading...
Searching...
No Matches
stmt_functor.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
26#ifndef TVM_TIRX_STMT_FUNCTOR_H_
27#define TVM_TIRX_STMT_FUNCTOR_H_
28
29#include <tvm/ir/expr_functor.h>
31#include <tvm/ir/prim/expr.h>
32#include <tvm/tirx/function.h>
33#include <tvm/tirx/stmt.h>
34
35#include <unordered_map>
36#include <utility>
37
38namespace tvm {
39namespace tirx {
50template <typename FType>
52
53template <typename R, typename... Args>
54class StmtFunctor<R(const Stmt&, Args...)> {
55 private:
56 using TSelf = StmtFunctor<R(const Stmt&, Args...)>;
57
58 public:
60 using result_type = R;
62 StmtFunctor() : StmtFunctor(GlobalVTable()) {}
64 virtual ~StmtFunctor() = default;
66 TVM_FFI_INLINE R operator()(const Stmt& node, Args... args) {
67 return Dispatch(node, std::forward<Args>(args)...);
68 }
70 TVM_FFI_INLINE virtual R Dispatch(const Stmt& node, Args... args) {
71 TVM_FFI_ICHECK(node.defined()) << "Cannot dispatch a null statement";
72 return (*vtable_)(node, this, std::forward<Args>(args)...);
73 }
74
75 virtual R Dispatch_(const BindNode* node, Args... args) {
76 return DispatchDefault_(node, std::forward<Args>(args)...);
77 }
78 virtual R Dispatch_(const RegionStmtNode* node, Args... args) {
79 return DispatchDefault_(node, std::forward<Args>(args)...);
80 }
81 virtual R Dispatch_(const IfNode* node, Args... args) {
82 return DispatchDefault_(node, std::forward<Args>(args)...);
83 }
84 virtual R Dispatch_(const ForNode* node, Args... args) {
85 return DispatchDefault_(node, std::forward<Args>(args)...);
86 }
87 virtual R Dispatch_(const WhileNode* node, Args... args) {
88 return DispatchDefault_(node, std::forward<Args>(args)...);
89 }
90 virtual R Dispatch_(const ReturnNode* node, Args... args) {
91 return DispatchDefault_(node, std::forward<Args>(args)...);
92 }
93 virtual R Dispatch_(const BreakNode* node, Args... args) {
94 return DispatchDefault_(node, std::forward<Args>(args)...);
95 }
96 virtual R Dispatch_(const ContinueNode* node, Args... args) {
97 return DispatchDefault_(node, std::forward<Args>(args)...);
98 }
99 virtual R Dispatch_(const TensorStoreNode* node, Args... args) {
100 return DispatchDefault_(node, std::forward<Args>(args)...);
101 }
102 virtual R Dispatch_(const AssertStmtNode* node, Args... args) {
103 return DispatchDefault_(node, std::forward<Args>(args)...);
104 }
105 virtual R Dispatch_(const SeqStmtNode* node, Args... args) {
106 return DispatchDefault_(node, std::forward<Args>(args)...);
107 }
108 virtual R Dispatch_(const EvaluateNode* node, Args... args) {
109 return DispatchDefault_(node, std::forward<Args>(args)...);
110 }
112 virtual R DispatchDefault_(const ffi::Object* node, Args...) {
113 TVM_FFI_THROW(InternalError) << "Do not have a default for " << node->GetTypeKey();
114 TVM_FFI_UNREACHABLE();
115 }
116
117 protected:
119 using VTable = ObjectFunctor<R(const ffi::ObjectRef&, TSelf*, Args...)>;
121 explicit StmtFunctor(const VTable* vtable) : vtable_(vtable) {}
123 static void InitVTable(VTable* vtable) {
124 vtable->template SetDispatch<StmtNode>(
125 [](const ffi::ObjectRef& node, TSelf* self, Args... args) -> R {
126 return self->DispatchDefault_(node.get(), std::forward<Args>(args)...);
127 });
128 SetDispatch<TSelf, BindNode>(vtable);
129 SetDispatch<TSelf, RegionStmtNode>(vtable);
130 SetDispatch<TSelf, IfNode>(vtable);
131 SetDispatch<TSelf, ForNode>(vtable);
132 SetDispatch<TSelf, WhileNode>(vtable);
133 SetDispatch<TSelf, ReturnNode>(vtable);
134 SetDispatch<TSelf, BreakNode>(vtable);
135 SetDispatch<TSelf, ContinueNode>(vtable);
136 SetDispatch<TSelf, TensorStoreNode>(vtable);
137 SetDispatch<TSelf, AssertStmtNode>(vtable);
138 SetDispatch<TSelf, SeqStmtNode>(vtable);
139 SetDispatch<TSelf, EvaluateNode>(vtable);
140 }
142 template <typename Self, typename Node>
143 static void SetDispatch(VTable* vtable) {
144 vtable->template SetDispatch<Node>(
145 [](const ffi::ObjectRef& node, TSelf* self, Args... args) -> R {
146 return static_cast<Self*>(self)->Dispatch_(static_cast<const Node*>(node.get()),
147 std::forward<Args>(args)...);
148 });
149 }
150
151 private:
152 static const VTable* GlobalVTable() {
153 static const VTable table = [] {
154 VTable table;
155 InitVTable(&table);
156 table.Finalize();
157 return table;
158 }();
159 return &table;
160 }
161 const VTable* vtable_;
162};
163
177 public:
179
182
183 virtual ffi::Optional<VisitInterrupt> Visit_(const BindNode* op);
184 virtual ffi::Optional<VisitInterrupt> Visit_(const RegionStmtNode* op);
185 virtual ffi::Optional<VisitInterrupt> Visit_(const IfNode* op);
186 virtual ffi::Optional<VisitInterrupt> Visit_(const ForNode* op);
187 virtual ffi::Optional<VisitInterrupt> Visit_(const WhileNode* op);
188 virtual ffi::Optional<VisitInterrupt> Visit_(const ReturnNode* op);
189 virtual ffi::Optional<VisitInterrupt> Visit_(const BreakNode* op);
190 virtual ffi::Optional<VisitInterrupt> Visit_(const ContinueNode* op);
191 virtual ffi::Optional<VisitInterrupt> Visit_(const TensorStoreNode* op);
192 virtual ffi::Optional<VisitInterrupt> Visit_(const AssertStmtNode* op);
193 virtual ffi::Optional<VisitInterrupt> Visit_(const SeqStmtNode* op);
194 virtual ffi::Optional<VisitInterrupt> Visit_(const EvaluateNode* op);
195
196 // Preserve TIRx operand traversal where it differs from the shared defaults.
197 ffi::Optional<VisitInterrupt> Visit_(const VarNode* op) override;
198 ffi::Optional<VisitInterrupt> Visit_(const TensorLoadNode* op) override;
199 ffi::Optional<VisitInterrupt> Visit_(const OpaqueExprNode* op) override;
200 ffi::Optional<VisitInterrupt> Visit_(const TupleNode* op) override;
201 ffi::Optional<VisitInterrupt> Visit_(const TupleGetItemNode* op) override;
202 ffi::Optional<VisitInterrupt> Visit_(const CallNode* op) override;
203 ffi::Optional<VisitInterrupt> Visit_(const prim::LetNode* op) override;
204 ffi::Optional<VisitInterrupt> Visit_(const prim::RampNode* op) override;
205 ffi::Optional<VisitInterrupt> Visit_(const prim::BroadcastNode* op) override;
206 ffi::Optional<VisitInterrupt> Visit_(const prim::ShuffleNode* op) override;
207
208 protected:
209 explicit StmtExprVisitor(const VTable* vtable) : tvm::ExprVisitor(vtable) {}
210 static void InitVTable(VTable* vtable);
211};
212
222 public:
226
234 TVM_FFI_INLINE UnchangedOr<Stmt> Mutate(const Stmt& stmt,
235 InplaceMode inplace_mode = InplaceMode::kDisallow) {
236 return ffi::details::UnchangedOrUnsafe::MoveFromTVMFFIAny<Stmt>(
237 ffi::details::UnchangedOrUnsafe::MoveToTVMFFIAny(Mutate(ffi::AnyView(stmt), inplace_mode)));
238 }
239
241 TVM_FFI_INLINE UnchangedOr<SeqStmt> Mutate(const SeqStmt& stmt,
242 InplaceMode inplace_mode = InplaceMode::kDisallow) {
243 auto result = Mutate(static_cast<const Stmt&>(stmt), inplace_mode);
244 if (result.UnchangedOrSameAs(stmt)) return ffi::Unchanged();
245 return SeqStmt(std::move(result).ValueUnchecked());
246 }
247
248 TVM_FFI_INLINE UnchangedOr<ffi::Optional<SeqStmt>> Mutate(
249 const ffi::Optional<SeqStmt>& stmt, InplaceMode inplace_mode = InplaceMode::kDisallow) {
250 if (!stmt.has_value()) return ffi::Unchanged();
251 auto result = Mutate(stmt.value(), inplace_mode);
252 if (result.IsUnchanged()) return ffi::Unchanged();
253 return ffi::Optional<SeqStmt>(std::move(result).ValueUnchecked());
254 }
255
257 TVM_FFI_INLINE UnchangedOr<ffi::Optional<Stmt>> Mutate(
258 const ffi::Optional<Stmt>& stmt, InplaceMode inplace_mode = InplaceMode::kDisallow) {
259 if (!stmt.has_value()) return ffi::Unchanged();
260 auto result = Mutate(stmt.value(), inplace_mode);
261 if (result.IsUnchanged()) return ffi::Unchanged();
262 return ffi::Optional<Stmt>(std::move(result).ValueUnchecked());
263 }
264
265 virtual UnchangedOr<Stmt> Mutate_(const BindNode* op, InplaceMode inplace_mode);
266 virtual UnchangedOr<Stmt> Mutate_(const RegionStmtNode* op, InplaceMode inplace_mode);
267 virtual UnchangedOr<Stmt> Mutate_(const IfNode* op, InplaceMode inplace_mode);
268 virtual UnchangedOr<Stmt> Mutate_(const ForNode* op, InplaceMode inplace_mode);
269 virtual UnchangedOr<Stmt> Mutate_(const WhileNode* op, InplaceMode inplace_mode);
270 virtual UnchangedOr<Stmt> Mutate_(const ReturnNode* op, InplaceMode inplace_mode);
271 virtual UnchangedOr<Stmt> Mutate_(const BreakNode* op, InplaceMode inplace_mode);
272 virtual UnchangedOr<Stmt> Mutate_(const ContinueNode* op, InplaceMode inplace_mode);
273 virtual UnchangedOr<Stmt> Mutate_(const TensorStoreNode* op, InplaceMode inplace_mode);
274 virtual UnchangedOr<Stmt> Mutate_(const AssertStmtNode* op, InplaceMode inplace_mode);
275 virtual UnchangedOr<Stmt> Mutate_(const SeqStmtNode* op, InplaceMode inplace_mode);
276 virtual UnchangedOr<Stmt> Mutate_(const EvaluateNode* op, InplaceMode inplace_mode);
277
278 protected:
279 explicit StmtExprMutator(const VTable* vtable) : tvm::ExprMutator(vtable) {}
280 static void InitVTable(VTable* vtable);
281};
282
297 Stmt stmt, std::function<ffi::Optional<PrimExpr>(const Var&)> vmap);
298
309 PrimExpr expr, std::function<ffi::Optional<PrimExpr>(const Var&)> vmap);
310
321template <typename Node, typename = std::enable_if_t<std::is_base_of_v<StmtNode, Node>>>
322bool ContainsNode(const Stmt& stmt) {
323 struct Visitor : StmtExprVisitor {
324 // Early bail-out, if we already found the node. Skip expression operands.
325 ffi::Optional<VisitInterrupt> Visit(ffi::AnyView value) final {
326 if (contains_node || value.as<ExprNode>()) {
327 return std::nullopt;
328 }
329 if (value.as<Node>()) {
330 contains_node = true;
331 return std::nullopt;
332 }
333 return StmtExprVisitor::Visit(value);
334 }
335
336 bool contains_node{false};
337 };
338
339 auto visitor = ffi::make_object<Visitor>();
340 visitor->Visit(stmt);
341 return visitor->contains_node;
342}
343
344} // namespace tirx
345} // namespace tvm
346
347#endif // TVM_TIR_STMT_FUNCTOR_H_
Assert condition, if an error occurs, return the error message.
Definition stmt.h:260
Bind a variable to a value in the enclosing scope.
Definition stmt.h:135
A Break in control flow.
Definition stmt.h:605
Call corresponds to callable invocation.
Definition expr.h:935
A Continue in control flow.
Definition stmt.h:632
Evaluates an expression. This is mostly used for putting a Call node into Stmt.
Definition stmt.h:352
Structural Expr mutator with native overrides for core expressions and structural fallback for other ...
Definition expr_functor.h:431
virtual UnchangedOr< Expr > Mutate_(const OpaqueExprNode *node, InplaceMode inplace_mode)
TVM_FFI_INLINE UnchangedOr< PrimExpr > Mutate(const PrimExpr &expr, InplaceMode inplace_mode=InplaceMode::kDisallow)
Mutate a primitive expression, preserving its expression category.
Definition expr_functor.h:446
Base type of all the expressions.
Definition base_expr.h:324
Structural Expr visitor with native overrides for core expressions.
Definition expr_functor.h:336
virtual ffi::Optional< VisitInterrupt > Visit_(const OpaqueExprNode *node)
virtual ffi::Optional< VisitInterrupt > Visit(ffi::AnyView value)
Construct a visitor with the core expression hooks.
Definition object_functor.h:242
A for loop, with possible type annotations.
Definition stmt.h:457
If statement.
Definition stmt.h:387
A dynamically dispatched functor on the type of the first argument.
Definition object_functor.h:85
Base node for opaque construction-time expressions.
Definition base_expr.h:394
Typed reference/view over any Expr whose ExprNode::ty is PrimType.
Definition base_expr.h:447
A single-body statement whose semantics are defined by an operator. Operands are evaluated in the enc...
Definition stmt.h:189
A return from the current function.
Definition stmt.h:571
The container of seq statement. Represent a sequence of statements.
Definition stmt.h:75
Sequence statement.
Definition stmt.h:92
Container of all statements.
Definition stmt.h:62
Load a value from an indexed expression source.
Definition expr.h:443
Store a primitive value to an indexed destination expression.
Definition stmt.h:308
Get the index-th field out of a tuple.
Definition expr.h:405
Tuple container.
Definition expr.h:363
A local variable in the IR.
Definition expr.h:694
Managed reference to VarNode.
Definition expr.h:714
A While loop.
Definition stmt.h:533
Create a vector where all the elements are value.
Definition vector_expr.h:79
Let binding. Bind var to value then evaluate body.
Definition expr.h:727
Construct a vector with lanes elements where its i-th element equals base + i * stride....
Definition vector_expr.h:42
Shuffle instruction. vec = concat(vectors) result = (vec[indices[0]], vec[indices[1]] ....
Definition vector_expr.h:117
Mutator that recursively mutates stmts and exprs on them.
Definition stmt_functor.h:221
virtual UnchangedOr< Stmt > Mutate_(const ReturnNode *op, InplaceMode inplace_mode)
TVM_FFI_INLINE UnchangedOr< Stmt > Mutate(const Stmt &stmt, InplaceMode inplace_mode=InplaceMode::kDisallow)
Mutate a borrowed statement through the virtual generic entry.
Definition stmt_functor.h:234
static void InitVTable(VTable *vtable)
virtual UnchangedOr< Stmt > Mutate_(const ForNode *op, InplaceMode inplace_mode)
TVM_FFI_INLINE UnchangedOr< ffi::Optional< SeqStmt > > Mutate(const ffi::Optional< SeqStmt > &stmt, InplaceMode inplace_mode=InplaceMode::kDisallow)
Definition stmt_functor.h:248
StmtExprMutator(const VTable *vtable)
Definition stmt_functor.h:279
virtual UnchangedOr< Stmt > Mutate_(const RegionStmtNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const EvaluateNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const ContinueNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const WhileNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const IfNode *op, InplaceMode inplace_mode)
TVM_FFI_INLINE UnchangedOr< ffi::Optional< Stmt > > Mutate(const ffi::Optional< Stmt > &stmt, InplaceMode inplace_mode=InplaceMode::kDisallow)
Mutate an optional statement, preserving an absent function body.
Definition stmt_functor.h:257
virtual UnchangedOr< Stmt > Mutate_(const BreakNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const BindNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const TensorStoreNode *op, InplaceMode inplace_mode)
virtual UnchangedOr< Stmt > Mutate_(const AssertStmtNode *op, InplaceMode inplace_mode)
TVM_FFI_INLINE UnchangedOr< SeqStmt > Mutate(const SeqStmt &stmt, InplaceMode inplace_mode=InplaceMode::kDisallow)
Mutate a scope body without collapsing its sequence container.
Definition stmt_functor.h:241
virtual UnchangedOr< Stmt > Mutate_(const SeqStmtNode *op, InplaceMode inplace_mode)
Native visitor for TIRx statements and their expression operands.
Definition stmt_functor.h:176
ffi::Optional< VisitInterrupt > Visit_(const prim::LetNode *op) override
static void InitVTable(VTable *vtable)
virtual ffi::Optional< VisitInterrupt > Visit_(const AssertStmtNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const ReturnNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const WhileNode *op)
ffi::Optional< VisitInterrupt > Visit_(const prim::ShuffleNode *op) override
virtual ffi::Optional< VisitInterrupt > Visit_(const BindNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const TensorStoreNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const ForNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const ContinueNode *op)
ffi::Optional< VisitInterrupt > Visit_(const VarNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const OpaqueExprNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const TensorLoadNode *op) override
virtual ffi::Optional< VisitInterrupt > Visit_(const BreakNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const SeqStmtNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const IfNode *op)
virtual ffi::Optional< VisitInterrupt > Visit_(const RegionStmtNode *op)
ffi::Optional< VisitInterrupt > Visit_(const TupleNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const TupleGetItemNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const CallNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const prim::RampNode *op) override
ffi::Optional< VisitInterrupt > Visit_(const prim::BroadcastNode *op) override
virtual ffi::Optional< VisitInterrupt > Visit_(const EvaluateNode *op)
StmtExprVisitor(const VTable *vtable)
Definition stmt_functor.h:209
virtual R Dispatch_(const AssertStmtNode *node, Args... args)
Definition stmt_functor.h:102
virtual R Dispatch_(const ContinueNode *node, Args... args)
Definition stmt_functor.h:96
virtual ~StmtFunctor()=default
Destroy through the statement functor base.
virtual R Dispatch_(const IfNode *node, Args... args)
Definition stmt_functor.h:81
virtual R Dispatch_(const BindNode *node, Args... args)
Definition stmt_functor.h:75
virtual R Dispatch_(const SeqStmtNode *node, Args... args)
Definition stmt_functor.h:105
virtual R Dispatch_(const BreakNode *node, Args... args)
Definition stmt_functor.h:93
R result_type
The result type of this functor.
Definition stmt_functor.h:60
virtual R Dispatch_(const TensorStoreNode *node, Args... args)
Definition stmt_functor.h:99
virtual R Dispatch_(const ReturnNode *node, Args... args)
Definition stmt_functor.h:90
virtual R Dispatch_(const WhileNode *node, Args... args)
Definition stmt_functor.h:87
virtual R Dispatch_(const RegionStmtNode *node, Args... args)
Definition stmt_functor.h:78
static void SetDispatch(VTable *vtable)
Register an additional node hook implemented by Self.
Definition stmt_functor.h:143
StmtFunctor(const VTable *vtable)
Construct with a finalized table that outlives the functor.
Definition stmt_functor.h:121
virtual R DispatchDefault_(const ffi::Object *node, Args...)
Default behavior for statement hooks not overridden by a subclass.
Definition stmt_functor.h:112
TVM_FFI_INLINE R operator()(const Stmt &node, Args... args)
Dispatch a statement, forwarding additional arguments to its hook.
Definition stmt_functor.h:66
static void InitVTable(VTable *vtable)
Register statement hooks in a fresh mutable table.
Definition stmt_functor.h:123
virtual R Dispatch_(const ForNode *node, Args... args)
Definition stmt_functor.h:84
virtual R Dispatch_(const EvaluateNode *node, Args... args)
Definition stmt_functor.h:108
virtual TVM_FFI_INLINE R Dispatch(const Stmt &node, Args... args)
Dispatch to a node hook, including registered ancestor hooks.
Definition stmt_functor.h:70
StmtFunctor()
Construct a functor with the TIRx statement hooks.
Definition stmt_functor.h:62
Type-dispatched statement functor with a caller-selected signature.
Definition stmt_functor.h:51
Native visiting and mutation of core IR expressions.
TIR expressions.
TVM_TIRX_DLL Stmt SubstituteWithDataTypeLegalization(Stmt stmt, std::function< ffi::Optional< PrimExpr >(const Var &)> vmap)
Substitute the var specified by vmap and legalize data types after substitution.
bool ContainsNode(const Stmt &stmt)
Check if the statement contains the specified node type.
Definition stmt_functor.h:322
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition attr.h:23
Native object dispatch, visiting and mutation with structural fallback.
#define TVM_DEFINE_OBJECT_FUNCTOR_DEFAULT_CONSTRUCTOR(Class, Parent)
Define a default constructor backed by one initialized native dispatch table.
Definition object_functor.h:529
#define TVM_TIRX_DLL
Definition base.h:83
TIR Function.
TIRx statements and shared statement entry header.