Program Listing for File expr_functor.h#
↰ Return to documentation for file (tvm/ir/expr_functor.h)
/*
* 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.
*/
#ifndef TVM_IR_EXPR_FUNCTOR_H_
#define TVM_IR_EXPR_FUNCTOR_H_
#include <tvm/ir/expr.h>
#include <tvm/ir/object_functor.h>
#include <tvm/ir/op.h>
#include <tvm/ir/prim/expr.h>
#include <tvm/ir/prim/vector_expr.h>
namespace tvm {
template <typename FType>
class ExprFunctor;
template <typename R, typename... Args>
class ExprFunctor<R(const Expr&, Args...)> {
private:
using TSelf = ExprFunctor<R(const Expr&, Args...)>;
public:
using result_type = R;
ExprFunctor() : ExprFunctor(GlobalVTable()) {}
TVM_FFI_INLINE R operator()(const Expr& node, Args... args) {
return Dispatch(node, std::forward<Args>(args)...);
}
TVM_FFI_INLINE virtual R Dispatch(const Expr& node, Args... args) {
TVM_FFI_ICHECK(node.defined()) << "Cannot dispatch a null expression";
try {
return (*vtable_)(node, this, std::forward<Args>(args)...);
} catch (ffi::Error& error) {
ffi::detail::UpdateVisitErrorContext(error, node);
throw;
}
}
virtual R Dispatch_(const LambdaExprObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const OpaqueExprObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const TupleObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const TupleGetItemObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const TensorRegionObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const TensorLoadObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const VarObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const GlobalVarObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const CallObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const GenericConstObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const DataTypeImmObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const IntImmObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const FloatImmObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const OpObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const StringImmObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::CastObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::AddObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::LShiftObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::RShiftObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::BitwiseAndObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::BitwiseOrObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::BitwiseXorObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::BitwiseNotObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::SubObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::MulObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::DivObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::ModObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::FloorDivObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::FloorModObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::MinObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::MaxObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::EQObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::NEObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::LTObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::LEObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::GTObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::GEObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::AndObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::OrObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::NotObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::SelectObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::LetObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::RampObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::BroadcastObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R Dispatch_(const prim::ShuffleObj* node, Args... args) {
return DispatchDefault_(node, std::forward<Args>(args)...);
}
virtual R DispatchDefault_(const ffi::Object* node, Args... args) {
TVM_FFI_THROW(InternalError) << "Do not have a default for " << node->GetTypeKey();
TVM_FFI_UNREACHABLE();
}
protected:
using VTable = ObjectFunctor<R(const ffi::ObjectRef&, TSelf*, Args...)>;
explicit ExprFunctor(const VTable* vtable) : vtable_(vtable) {}
static void InitVTable(VTable* vtable) {
SetDispatch<TSelf, LambdaExprObj>(vtable);
SetDispatch<TSelf, OpaqueExprObj>(vtable);
SetDispatch<TSelf, TupleObj>(vtable);
SetDispatch<TSelf, TupleGetItemObj>(vtable);
SetDispatch<TSelf, TensorLoadObj>(vtable);
SetDispatch<TSelf, TensorRegionObj>(vtable);
SetDispatch<TSelf, VarObj>(vtable);
SetDispatch<TSelf, GlobalVarObj>(vtable);
SetDispatch<TSelf, CallObj>(vtable);
SetDispatch<TSelf, GenericConstObj>(vtable);
SetDispatch<TSelf, DataTypeImmObj>(vtable);
SetDispatch<TSelf, IntImmObj>(vtable);
SetDispatch<TSelf, FloatImmObj>(vtable);
SetDispatch<TSelf, OpObj>(vtable);
SetDispatch<TSelf, StringImmObj>(vtable);
SetDispatch<TSelf, prim::CastObj>(vtable);
SetDispatch<TSelf, prim::AddObj>(vtable);
SetDispatch<TSelf, prim::LShiftObj>(vtable);
SetDispatch<TSelf, prim::RShiftObj>(vtable);
SetDispatch<TSelf, prim::BitwiseAndObj>(vtable);
SetDispatch<TSelf, prim::BitwiseOrObj>(vtable);
SetDispatch<TSelf, prim::BitwiseXorObj>(vtable);
SetDispatch<TSelf, prim::BitwiseNotObj>(vtable);
SetDispatch<TSelf, prim::SubObj>(vtable);
SetDispatch<TSelf, prim::MulObj>(vtable);
SetDispatch<TSelf, prim::DivObj>(vtable);
SetDispatch<TSelf, prim::ModObj>(vtable);
SetDispatch<TSelf, prim::FloorDivObj>(vtable);
SetDispatch<TSelf, prim::FloorModObj>(vtable);
SetDispatch<TSelf, prim::MinObj>(vtable);
SetDispatch<TSelf, prim::MaxObj>(vtable);
SetDispatch<TSelf, prim::EQObj>(vtable);
SetDispatch<TSelf, prim::NEObj>(vtable);
SetDispatch<TSelf, prim::LTObj>(vtable);
SetDispatch<TSelf, prim::LEObj>(vtable);
SetDispatch<TSelf, prim::GTObj>(vtable);
SetDispatch<TSelf, prim::GEObj>(vtable);
SetDispatch<TSelf, prim::AndObj>(vtable);
SetDispatch<TSelf, prim::OrObj>(vtable);
SetDispatch<TSelf, prim::NotObj>(vtable);
SetDispatch<TSelf, prim::SelectObj>(vtable);
SetDispatch<TSelf, prim::LetObj>(vtable);
SetDispatch<TSelf, prim::RampObj>(vtable);
SetDispatch<TSelf, prim::BroadcastObj>(vtable);
SetDispatch<TSelf, prim::ShuffleObj>(vtable);
}
template <typename Self, typename Node>
static void SetDispatch(VTable* vtable) {
vtable->template SetDispatch<Node>(
[](const ffi::ObjectRef& node, TSelf* self, Args... args) -> R {
return static_cast<Self*>(self)->Dispatch_(static_cast<const Node*>(node.get()),
std::forward<Args>(args)...);
});
}
private:
static const VTable* GlobalVTable() {
static const VTable table = [] {
VTable table;
InitVTable(&table);
table.Finalize();
return table;
}();
return &table;
}
const VTable* vtable_;
};
class TVM_TIRX_DLL ExprVisitor : public ObjectVisitor {
public:
TVM_DEFINE_OBJECT_FUNCTOR_DEFAULT_CONSTRUCTOR(ExprVisitor, ObjectVisitor)
using ObjectVisitor::Visit;
// Override existing hooks directly. Extra types need a fresh inherited table.
// Hooks borrow the node and return None or an owning interrupt, and throw on failure.
virtual ffi::Optional<VisitInterrupt> Visit_(const OpaqueExprObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const TupleObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const TupleGetItemObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const TensorLoadObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const TensorRegionObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const VarObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const GlobalVarObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const CallObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const GenericConstObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const DataTypeImmObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const IntImmObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const FloatImmObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const OpObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const StringImmObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::CastObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::AddObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::LShiftObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::RShiftObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::BitwiseAndObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::BitwiseOrObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::BitwiseXorObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::BitwiseNotObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::SubObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::MulObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::DivObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::ModObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::FloorDivObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::FloorModObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::MinObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::MaxObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::EQObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::NEObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::LTObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::LEObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::GTObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::GEObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::AndObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::OrObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::NotObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::SelectObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::LetObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::RampObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::BroadcastObj* node);
virtual ffi::Optional<VisitInterrupt> Visit_(const prim::ShuffleObj* node);
protected:
explicit ExprVisitor(const VTable* vtable) : ObjectVisitor(vtable) {}
static void InitVTable(VTable* vtable);
};
class TVM_TIRX_DLL ExprMutator : public ObjectMutator {
public:
TVM_DEFINE_OBJECT_FUNCTOR_DEFAULT_CONSTRUCTOR(ExprMutator, ObjectMutator)
using ObjectMutator::Mutate;
TVM_FFI_INLINE UnchangedOr<PrimExpr> Mutate(const PrimExpr& expr,
InplaceMode inplace_mode = InplaceMode::kDisallow) {
return ffi::detail::UnchangedOrUnsafe::MoveFromTVMFFIAny<PrimExpr>(
ffi::detail::UnchangedOrUnsafe::MoveToTVMFFIAny(Mutate(ffi::AnyView(expr), inplace_mode)));
}
TVM_FFI_INLINE UnchangedOr<Expr> Mutate(const Expr& expr,
InplaceMode inplace_mode = InplaceMode::kDisallow) {
return ffi::detail::UnchangedOrUnsafe::MoveFromTVMFFIAny<Expr>(
ffi::detail::UnchangedOrUnsafe::MoveToTVMFFIAny(Mutate(ffi::AnyView(expr), inplace_mode)));
}
// A downstream class overrides any existing hook without rebuilding the table.
// Extra node types use a fresh inherited table and SetDispatch<Self, ExtraObj>.
// Hooks borrow the node and return Unchanged or an owning replacement in its expression
// category, throwing on failure. Narrower field types are checked separately. Forward
// inplace_mode on every child edge.
virtual UnchangedOr<Expr> Mutate_(const OpaqueExprObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const TupleObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const TupleGetItemObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const TensorLoadObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const TensorRegionObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const VarObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const GlobalVarObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const CallObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const GenericConstObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const DataTypeImmObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const IntImmObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const FloatImmObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const OpObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<Expr> Mutate_(const StringImmObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::CastObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::AddObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::LShiftObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::RShiftObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::BitwiseAndObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::BitwiseOrObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::BitwiseXorObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::BitwiseNotObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::SubObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::MulObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::DivObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::ModObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::FloorDivObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::FloorModObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::MinObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::MaxObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::EQObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::NEObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::LTObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::LEObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::GTObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::GEObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::AndObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::OrObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::NotObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::SelectObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::LetObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::RampObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::BroadcastObj* node, InplaceMode inplace_mode);
virtual UnchangedOr<PrimExpr> Mutate_(const prim::ShuffleObj* node, InplaceMode inplace_mode);
protected:
static UnchangedOr<Expr> ReinferMutatedCallType(UnchangedOr<Expr> mutated,
const CallObj* original,
InplaceMode inplace_mode);
explicit ExprMutator(const VTable* vtable) : ObjectMutator(vtable) {}
static void InitVTable(VTable* vtable);
};
} // namespace tvm
#endif // TVM_IR_EXPR_FUNCTOR_H_