// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved. // // Licensed 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. #pragma once #include "paddle/cinn/operator_fusion/pir_graph_analyzing/loop_axis_mapping.h" #include "paddle/cinn/operator_fusion/utils.h" namespace cinn::fusion { enum InstructionType { T_Base, T_Copy, T_Combine, T_Return, T_InitPattern, T_TrivialInline, T_TmpTransform, T_TrivialLoopAlign, T_AxisTransform, }; struct FusionInstruction { using FusionInstrPtr = std::shared_ptr; virtual InstructionType type() const { return T_Base; } virtual std::string DebugStr() const { return "BaseInstr"; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } }; using FusionInstrPtr = std::shared_ptr; struct CopyInstr : public FusionInstruction { CopyInstr(const std::string& origin_name, const std::string& new_name) : origin_name_(origin_name), new_name_(new_name) {} virtual InstructionType type() const { return T_Copy; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string origin_name_; std::string new_name_; virtual std::string DebugStr() const { return "CopyInstr || " + origin_name_ + " => " + new_name_; } }; struct CombineInstr : public FusionInstruction { CombineInstr(const std::vector& names, const std::string& result) : names_(names), result_(result) {} virtual InstructionType type() const { return T_Combine; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::vector names_; std::string result_; virtual std::string DebugStr() const { std::stringstream ss; ss << "CombineInstr || "; for (auto name : names_) { ss << name << ", "; } ss << "=> " << result_; return ss.str(); } }; struct ReturnInstr : public FusionInstruction { explicit ReturnInstr(const std::string& target) : target_(target) {} virtual InstructionType type() const { return T_Return; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string target_; virtual std::string DebugStr() const { return "ReturnInstr || " + target_; } }; // struct RemovePatternInstr : public FusionInstruction {}; struct InitPatternInstr : public FusionInstruction { private: // we can't just use operation* to identify a unique op because pass change // the program. int idx_in_fusion_op = -1; std::string op_name; public: InitPatternInstr(pir::Operation* op, const std::string& result) : op_(op), result_(result) { op_name = op->name(); } void set_idx(int idx) { idx_in_fusion_op = idx; } int get_idx() const { PADDLE_ENFORCE_NE( idx_in_fusion_op, -1, ::common::errors::InvalidArgument("FusionPattern is not initialized.")); return idx_in_fusion_op; } virtual InstructionType type() const { return T_InitPattern; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } pir::Operation* op_; std::string result_; virtual std::string DebugStr() const { std::ostringstream ss; ss << "InitPatternInstr || " + op_name + " => " + result_ + " index = (" << idx_in_fusion_op << ")"; return ss.str(); } }; struct TrivialInlineInstr : public FusionInstruction { TrivialInlineInstr(const std::string& upstream, const std::string& downstream, const std::string& result) : upstream_(upstream), downstream_(downstream), result_(result) {} virtual InstructionType type() const { return T_TrivialInline; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string upstream_; std::string downstream_; std::string result_; virtual std::string DebugStr() const { return "TrivialInlineInstr || " + upstream_ + ", " + downstream_ + " => " + result_; } }; struct TmpTransformInstr : public FusionInstruction { TmpTransformInstr(const std::string& upstream, const std::string& downstream, const std::string& out_upstream, const std::string& out_downstream, const std::vector& fake_reduce_iter_idx = {}) : upstream_(upstream), downstream_(downstream), out_downstream_(out_downstream), out_upstream_(out_upstream), fake_reduce_iter_idx_(fake_reduce_iter_idx) {} InstructionType type() const override { return T_TmpTransform; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string upstream_; std::string downstream_; std::string out_upstream_; std::string out_downstream_; std::vector fake_reduce_iter_idx_; std::string DebugStr() const override { return "TmpTransformInstr || " + upstream_ + ", " + downstream_ + " => " + out_upstream_ + ", " + out_downstream_; } }; struct TrivialLoopAlignInstr : public FusionInstruction { TrivialLoopAlignInstr(const std::string& upstream, const std::string& downstream, const std::string& result, const std::vector& fake_reduce_iter_idx) : upstream_(upstream), downstream_(downstream), result_(result), fake_reduce_iter_idx_(fake_reduce_iter_idx) {} virtual InstructionType type() const { return T_TrivialLoopAlign; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string upstream_; std::string downstream_; std::string result_; std::vector fake_reduce_iter_idx_; virtual std::string DebugStr() const { return "TrivialLoopAlignInstr || " + upstream_ + ", " + downstream_ + " => " + result_; } }; struct AxisTransformInstr : public FusionInstruction { AxisTransformInstr(const std::string& source, const std::string& target, const AxisTransformRoute& axis_transform_route) : source_(source), target_(target), axis_transform_route_(axis_transform_route) {} virtual InstructionType type() const { return T_AxisTransform; } virtual FusionInstrPtr Clone() { return std::make_shared(*this); } std::string source_; std::string target_; AxisTransformRoute axis_transform_route_; virtual std::string DebugStr() const { return "AxisTransformInstr || " + source_ + " => " + target_; } }; template std::shared_ptr dynamic_cast_instr_with_err(FusionInstrPtr instr) { auto chile_instr = std::dynamic_pointer_cast(instr); PADDLE_ENFORCE_NOT_NULL( chile_instr, ::common::errors::InvalidArgument("Cast Fusion Instr Failed.")); return chile_instr; } struct FusionTracker { using FusionTrackerPtr = std::shared_ptr; FusionTracker() = default; explicit FusionTracker(const FusionTrackerPtr& other) { ExtendVector(&instructions_, other->instructions_); } FusionTracker(const FusionTrackerPtr& up, const FusionTrackerPtr& down) { ExtendVector(&instructions_, up->instructions_); ExtendVector(&instructions_, down->instructions_); } void append(FusionInstrPtr instr) { instructions_.emplace_back(instr); } FusionTrackerPtr Clone() { auto new_tracker = std::make_shared(); std::vector new_instructions; for (auto instr : instructions_) { new_tracker->append(instr->Clone()); } return new_tracker; } std::string DebugStr() const { std::stringstream ss; ss << "FusionTracker: \n"; for (auto instr : instructions_) { ss << " " << instr->DebugStr() << "\n"; } return ss.str(); } std::vector instructions_; }; using FusionTrackerPtr = std::shared_ptr; } // namespace cinn::fusion