// 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/ap/include/axpr/anf_expr_util.h" #include "paddle/ap/include/axpr/atomic.h" #include "paddle/ap/include/axpr/data_type_util.h" #include "paddle/ap/include/axpr/lambda_expr_builder.h" #include "paddle/ap/include/code_gen/arg_source_ctx.h" #include "paddle/ap/include/drr/drr_graph_descriptor.h" #include "paddle/ap/include/drr/drr_node_descriptor.h" #include "paddle/ap/include/drr/res_ptn_packed_ir_op_declare_data.h" #include "paddle/ap/include/drr/result_pattern_helper.h" #include "paddle/ap/include/drr/value.h" #include "paddle/ap/include/graph/graph_helper.h" #include "paddle/ap/include/ir_match/graph_match_ctx.h" #include "paddle/ap/include/ir_match/graph_matcher.h" #include "paddle/ap/include/ir_match/ir_match_ctx.h" namespace ap::code_gen { template struct MatchedResultPatternHelper { using DrrNode = drr::Node; using DrrCtx = drr::DrrCtx; using DrrNativeIrValue = drr::NativeIrValue; using DrrPackedIrValue = drr::PackedIrValue; using DrrIrValue = drr::IrValue; using DrrNativeIrOp = drr::NativeIrOp; using DrrNativeIrOpOperand = drr::NativeIrOpOperand; using DrrNativeIrOpResult = drr::NativeIrOpResult; using DrrPackedIrOp = drr::PackedIrOp; using DrrPackedIrOpOperand = drr::PackedIrOpOperand; using DrrPackedIrOpResult = drr::PackedIrOpResult; using DrrOptPackedIrOp = drr::OptPackedIrOp; using DrrOptPackedIrOpOperand = drr::OptPackedIrOpOperand; using DrrOptPackedIrOpResult = drr::OptPackedIrOpResult; using DrrIrOpImpl = std::variant; using IrMatchCtx = ir_match::IrMatchCtx; using GraphMatchCtx = ir_match::GraphMatchCtx; const GraphMatchCtx& match_ctx_; const DrrCtx& drr_ctx_; template adt::Result VisitMatchedBirInputOfRestPtnPackedIrOp( const DrrPackedIrOp& res_ptn_ir_op, const DoEachT& DoEach) const { auto CollectInput = [&](const DrrIrValue& drr_ir_value) -> adt::Result { return VisitMatchedBirValueOfResPtnIrValue(drr_ir_value, DoEach); }; ADT_RETURN_IF_ERR( VisitResPtnInputIrValueByResPtnIrOp(res_ptn_ir_op, CollectInput)); return adt::Ok{}; } template adt::Result VisitMatchedBirOutputOfRestPtnPackedIrOp( const DrrPackedIrOp& res_ptn_ir_op, const DoEachT& DoEach) const { auto DoEachDrrIrValue = [&](const DrrIrValue& drr_ir_value) -> adt::Result { return VisitMatchedBirValueOfResPtnIrValue(drr_ir_value, DoEach); }; ADT_RETURN_IF_ERR( VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, DoEachDrrIrValue)); return adt::Ok{}; } template adt::Result VisitResPtnInputIrValueByResPtnIrOp( const DrrPackedIrOp& res_ptn_ir_op, const DoEachT& DoEach) const { drr::ResultPatternHelper helper{drr_ctx_}; return helper.VisitResPtnInputIrValueByResPtnIrOp(res_ptn_ir_op, DoEach); } template adt::Result VisitMatchedBirValueOfResPtnIrValue( const DrrIrValue& res_ptn_ir_value, const DoEachT& DoEach) const { using Ok = adt::Result; const auto& opt_ir_value = SrcPtnIrValue4ResPtnIrValue(res_ptn_ir_value); ADT_CHECK(opt_ir_value.has_value()); const auto& ir_value = opt_ir_value.value(); ADT_RETURN_IF_ERR( match_ctx_->VisitBigGraphIrValueNode(ir_value.node(), DoEach)); return adt::Ok{}; } template adt::Result VisitApKernelInputIndexOrSlice( const DrrPackedIrOp& res_ptn_ir_op, const DoEachIndexT& DoEachIndex, const DoEachSliceT& DoEachSlice) const { std::size_t start = 0; using Ok = adt::Result; auto DoEachIrValue = [&](const DrrIrValue& drr_ir_value) -> Ok { ADT_LET_CONST_REF(num_ir_values, GetResPtnNumBirValues(drr_ir_value)); ADT_RETURN_IF_ERR(drr_ir_value.Match( [&](const DrrNativeIrValue&) -> Ok { ADT_RETURN_IF_ERR(DoEachIndex(start)); return adt::Ok{}; }, [&](const DrrPackedIrValue&) -> Ok { ADT_RETURN_IF_ERR(DoEachSlice(start, start + num_ir_values)); return adt::Ok{}; })); start += num_ir_values; return adt::Ok{}; }; ADT_RETURN_IF_ERR( VisitResPtnInputIrValueByResPtnIrOp(res_ptn_ir_op, DoEachIrValue)); return adt::Ok{}; } template adt::Result VisitApKernelOutputIndexOrSlice( const DrrPackedIrOp& res_ptn_ir_op, const DoEachIndexT& DoEachIndex, const DoEachSliceT& DoEachSlice) const { std::size_t start = 0; using Ok = adt::Result; auto DoEachIrValue = [&](const DrrIrValue& drr_ir_value) -> Ok { ADT_LET_CONST_REF(num_ir_values, GetResPtnNumBirValues(drr_ir_value)); ADT_RETURN_IF_ERR(drr_ir_value.Match( [&](const DrrNativeIrValue&) -> Ok { ADT_RETURN_IF_ERR(DoEachIndex(start)); return adt::Ok{}; }, [&](const DrrPackedIrValue&) -> Ok { ADT_RETURN_IF_ERR(DoEachSlice(start, start + num_ir_values)); return adt::Ok{}; })); start += num_ir_values; return adt::Ok{}; }; ADT_RETURN_IF_ERR( VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, DoEachIrValue)); return adt::Ok{}; } adt::Result GetApKernelNumOutputs( const DrrPackedIrOp& res_ptn_ir_op) const { std::size_t num_outputs = 0; auto AccNumOutputs = [&](const DrrIrValue& drr_ir_value) -> adt::Result { ADT_LET_CONST_REF(num_ir_values, GetResPtnNumBirValues(drr_ir_value)); num_outputs += num_ir_values; return adt::Ok{}; }; ADT_RETURN_IF_ERR( VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, AccNumOutputs)); return num_outputs; } template adt::Result VisitEachMatchedDrrIrValueAndOutputSlice( const std::vector& output_values, const IrOpT& res_ptn_ir_op, const DoEachT& DoEach) const { std::size_t offset = 0; auto DoEachSlice = [&](const DrrIrValue& drr_ir_value) -> adt::Result { ADT_LET_CONST_REF(num_ir_values, GetResPtnNumBirValues(drr_ir_value)); ADT_CHECK(offset + num_ir_values <= output_values.size()); std::vector slice{output_values.begin() + offset, output_values.begin() + offset + num_ir_values}; ADT_RETURN_IF_ERR(DoEach(drr_ir_value, slice)); offset += num_ir_values; return adt::Ok{}; }; return VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, DoEachSlice); } template adt::Result VisitResPtnOutputIrValueByResPtnIrOp( const IrOpT& res_ptn_ir_op, const DoEachT& DoEach) const { drr::ResultPatternHelper helper{drr_ctx_}; return helper.VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, DoEach); } adt::Result GetResPtnNumBirValues( const DrrIrValue& res_ptn_ir_value) const { const auto& opt_src_ptn_ir_value = SrcPtnIrValue4ResPtnIrValue(res_ptn_ir_value); if (!opt_src_ptn_ir_value.has_value()) { // internal ir value in result pattern. return 1U; } return match_ctx_->GetNumBigGraphIrValueNodes( opt_src_ptn_ir_value.value().node()); } std::optional SrcPtnIrValue4ResPtnIrValue( const DrrIrValue& res_ptn_ir_value) const { drr::ResultPatternHelper helper{drr_ctx_}; return helper.SrcPtnIrValue4ResPtnIrValue(res_ptn_ir_value); } using BirNativeIrValue = typename BirNode::native_value_type; adt::Result CastToBirNativeIrValue( const BirNode& bir_node) const { using RetT = adt::Result; return bir_node.Match( [&](const typename BirNode::native_value_type& bir_value) -> RetT { return bir_value; }, [&](const typename BirNode::ref_value_type& ref_value) -> RetT { return ref_value.GetOwnerNativeIrValue(); }, [&](const auto&) -> RetT { return adt::errors::TypeError{ "bir_node is not an PirNode::native_value_type or " "BirNode::ref_value_type"}; }); } }; } // namespace ap::code_gen