Files
wehub-resource-sync 26446540fa
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

289 lines
10 KiB
C++

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef TVM_S_TIR_SCHEDULE_INSTRUCTION_H_
#define TVM_S_TIR_SCHEDULE_INSTRUCTION_H_
#include <tvm/ffi/reflection/registry.h>
#include <utility>
namespace tvm {
// Forward declaration
template <typename, typename>
class AttrRegistry;
namespace s_tir {
using namespace tvm::tirx;
// Forward declaration
class Schedule;
/*!
* \brief Type of the functor that applies the instruction to a TensorIR schedule
* \param sch The schedule to be applied on
* \param inputs The input random variables
* \param attrs Instruction attributes
* \param decision Decisions made on the instruction
* \return The functor returns an array of output random variables
*/
using FInstructionApply =
ffi::TypedFunction<ffi::Array<Any>(Schedule sch, const ffi::Array<Any>& inputs,
const ffi::Array<Any>& attrs, const Any& decision)>;
/*!
* \brief Type of the functor that converts the instruction to a statement in python syntax
* \param inputs Names of the input random variables
* \param attrs Instruction attributes
* \param decisions Decisions made on the instruction
* \param outputs Names of the output random variables
* \return A string representing the python api call
*/
using FInstructionAsPython =
ffi::TypedFunction<ffi::String(const ffi::Array<Any>& inputs, const ffi::Array<Any>& attrs,
const Any& decision, const ffi::Array<ffi::String>& outputs)>;
/*!
* \brief Type of the functor that serialize its attributes to JSON
* \param attrs The attributes to be serialized
* \return An array, serialized attributes
* \note This functor is nullable
*/
using FInstructionAttrsAsJSON = ffi::TypedFunction<ffi::ObjectRef(ffi::Array<Any> attrs)>;
/*!
* \brief Type of the functor that deserialize its attributes from JSON
* \param json_attrs The attributes to be serialized
* \return An array, deserialized attributes
* \note This functor is nullable
*/
using FInstructionAttrsFromJSON = ffi::TypedFunction<ffi::Array<Any>(ffi::ObjectRef json_attrs)>;
/*!
* \brief Kind of an instruction, e.g. Split, Reorder, etc.
* Besides the name, every kind of instruction has its own properties, including:
* 1) A boolean indicating if the instruction is pure, i.e. change nothing in the schedule state
* 2) A functor that applies the instruction to a TensorIR schedule
* 3) A functor that converts the instruction to a statement in python syntax
* 4) A functor that serialize its attributes to JSON
* 5) A functor that deserialize its attributes from JSON
*
* Unlike `tvm::OpNode`, `InstructionKindNode` doesn't support unstructured properties,
* mainly because there is no such usecase yet to add any other property.
*/
class InstructionKindNode : public ffi::Object {
public:
/*! \brief The name of a kind of instructions */
ffi::String name;
/*!
* \brief Indicates if the instruction is pure, i.e. removing it alone doesn't mutate the schedule
* state. For example, the instruction `GetSBlock` is pure because it changes
* nothing, while `ComputeInline` is not because removing it leads to a different resulting
* schedule.
*/
bool is_pure{false};
/*! \brief A functor that applies the instruction to a TensorIR schedule */
FInstructionApply f_apply_to_schedule{nullptr};
/*! \brief A functor that converts the instruction to a statement in python syntax */
FInstructionAsPython f_as_python{nullptr};
/*!
* \brief A functor that serialize its attributes to JSON
* \note If the functor is null, it means no conversion is needed
*/
FInstructionAttrsAsJSON f_attrs_as_json{nullptr};
/*!
* \brief A functor that deserialize its attributes from JSON
* \note If the functor is null, it means no conversion is needed
*/
FInstructionAttrsFromJSON f_attrs_from_json{nullptr};
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
refl::ObjectDef<InstructionKindNode>()
.def_ro("name", &InstructionKindNode::name)
.def_ro("_is_pure", &InstructionKindNode::is_pure);
}
/*! \brief Checks if the instruction kind is EnterPostproc */
bool IsPostproc() const;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.InstructionKind", InstructionKindNode, ffi::Object);
};
/*!
* \brief Managed reference to InstructionKindNode
* \sa InstructionKindNode
*/
class InstructionKind : public ffi::ObjectRef {
public:
/*!
* \brief Retrieve an InstructionKind using its name
* \param name The registered name of the InstructionKind
* \return The InstructionKind retrieved
*/
static InstructionKind Get(const ffi::String& name);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(InstructionKind, ffi::ObjectRef, InstructionKindNode);
};
/*! \brief Schedule instructions each corresponds to a schedule primitive */
class InstructionNode : public ffi::Object {
public:
/*! \brief The kind of the instruction */
InstructionKind kind;
/*!
* \brief The input random variables of the instruction, and the type of each element can be one
* of the following:
* - SBlockRV
* - LoopRV
* - ExprRV
* - double
* - int64_t
* - String
* - null pointer
*/
ffi::Array<Any> inputs;
/*!
* \brief The attributes of the instruction. Similar to attributes of an operator,
* attributes of an instruction are arbitrary constant metadata required by the instructions.
* For example, the name of the block to be retrieved in `GetSBlock`.
*/
ffi::Array<Any> attrs;
/*! \brief The output random variables of the instruction, and the type of each element can be one
* of the following:
* - SBlockRV
* - LoopRV
* - ExprRV, atomic variables only, won't be constants or composite PrimExpr
*/
ffi::Array<Any> outputs;
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
refl::ObjectDef<InstructionNode>()
.def_ro("kind", &InstructionNode::kind)
.def_ro("inputs", &InstructionNode::inputs)
.def_ro("attrs", &InstructionNode::attrs)
.def_ro("outputs", &InstructionNode::outputs);
}
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("s_tir.Instruction", InstructionNode, ffi::Object);
};
/*!
* \brief Managed reference to InstructionNode
* \sa InstructionNode
*/
class Instruction : public ffi::ObjectRef {
public:
/*!
* \brief Constructor
* \param kind The kind of the instruction
* \param inputs The input random variables of the instruction
* \param attrs The attributes of the instruction
* \param outputs The output random variables of the instruction
*/
explicit Instruction(InstructionKind kind, ffi::Array<Any> inputs, ffi::Array<Any> attrs,
ffi::Array<Any> outputs);
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(Instruction, ffi::ObjectRef, InstructionNode);
};
/*!
* \brief A helper macro to register InstructionKind, only used in `TVM_REGISTER_INST_KIND`
* \note This macro is not user-facing.
* \sa TVM_REGISTER_INST_KIND
*/
#define TVM_INST_KIND_REGISTER_VAR_DEF \
[[maybe_unused]] static ::tvm::s_tir::InstructionKindRegEntry& __make_##InstructionKind
/*!
* \brief Register an InstructionKind
* \param InstructionKindName The name of the InstructionKind
*
* Example:
*
* \code
*
* TVM_REGISTER_INST_KIND("ComputeInline")
* .set_is_pure(false)
* .set_apply_to_schedule(ApplyToSchedule)
* .set_attrs_as_json(AttrsAsJSON)
* .set_attrs_from_json(AttrsFromJSON)
* .set_as_python(AsPython);
*
* \endcode
*/
#define TVM_REGISTER_INST_KIND(InstructionKindName) \
TVM_FFI_STR_CONCAT(TVM_INST_KIND_REGISTER_VAR_DEF, __COUNTER__) = \
::tvm::s_tir::InstructionKindRegEntry::RegisterOrGet(InstructionKindName).set_name()
/*! \brief An entry in the registry of InstructionKind */
class InstructionKindRegEntry {
public:
static InstructionKindRegEntry& RegisterOrGet(const ffi::String& name);
InstructionKindRegEntry& set_name() {
get_mutable()->name = this->name;
return *this;
}
InstructionKindRegEntry& set_is_pure(bool is_pure) {
get_mutable()->is_pure = is_pure;
return *this;
}
InstructionKindRegEntry& set_apply_to_schedule(FInstructionApply f_apply_to_schedule) {
get_mutable()->f_apply_to_schedule = std::move(f_apply_to_schedule);
return *this;
}
InstructionKindRegEntry& set_as_python(FInstructionAsPython f_as_python) {
get_mutable()->f_as_python = std::move(f_as_python);
return *this;
}
InstructionKindRegEntry& set_attrs_as_json(FInstructionAttrsAsJSON f_attrs_as_json) {
get_mutable()->f_attrs_as_json = std::move(f_attrs_as_json);
return *this;
}
InstructionKindRegEntry& set_attrs_from_json(FInstructionAttrsFromJSON f_attrs_from_json) {
get_mutable()->f_attrs_from_json = std::move(f_attrs_from_json);
return *this;
}
private:
/*! \brief Private constructor, used only by AttrRegistry */
explicit InstructionKindRegEntry(uint32_t reg_index);
/*! \brief Get the mutable reference to the internal InstructionKind */
InstructionKindNode* get_mutable() const {
return const_cast<InstructionKindNode*>(inst_kind_.get());
}
/*! \brief The name of the registry entry */
ffi::String name;
/*! \brief The instruction kind */
InstructionKind inst_kind_;
template <typename, typename>
friend class ::tvm::AttrRegistry;
friend class InstructionKind;
};
} // namespace s_tir
} // namespace tvm
#endif // TVM_S_TIR_SCHEDULE_INSTRUCTION_H_