Files
2026-07-13 12:40:42 +08:00

237 lines
9.0 KiB
C++

// 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 <typename BirNode /* backend ir node*/>
struct MatchedResultPatternHelper {
using DrrNode = drr::Node;
using DrrCtx = drr::DrrCtx;
using DrrNativeIrValue = drr::NativeIrValue<DrrNode>;
using DrrPackedIrValue = drr::PackedIrValue<DrrNode>;
using DrrIrValue = drr::IrValue;
using DrrNativeIrOp = drr::NativeIrOp<DrrNode>;
using DrrNativeIrOpOperand = drr::NativeIrOpOperand<DrrNode>;
using DrrNativeIrOpResult = drr::NativeIrOpResult<DrrNode>;
using DrrPackedIrOp = drr::PackedIrOp<DrrNode>;
using DrrPackedIrOpOperand = drr::PackedIrOpOperand<DrrNode>;
using DrrPackedIrOpResult = drr::PackedIrOpResult<DrrNode>;
using DrrOptPackedIrOp = drr::OptPackedIrOp<DrrNode>;
using DrrOptPackedIrOpOperand = drr::OptPackedIrOpOperand<DrrNode>;
using DrrOptPackedIrOpResult = drr::OptPackedIrOpResult<DrrNode>;
using DrrIrOpImpl = std::variant<DrrNativeIrOp, DrrPackedIrOp>;
using IrMatchCtx = ir_match::IrMatchCtx<BirNode>;
using GraphMatchCtx = ir_match::GraphMatchCtx<BirNode>;
const GraphMatchCtx& match_ctx_;
const DrrCtx& drr_ctx_;
template <typename DoEachT>
adt::Result<adt::Ok> VisitMatchedBirInputOfRestPtnPackedIrOp(
const DrrPackedIrOp& res_ptn_ir_op, const DoEachT& DoEach) const {
auto CollectInput =
[&](const DrrIrValue& drr_ir_value) -> adt::Result<adt::Ok> {
return VisitMatchedBirValueOfResPtnIrValue(drr_ir_value, DoEach);
};
ADT_RETURN_IF_ERR(
VisitResPtnInputIrValueByResPtnIrOp(res_ptn_ir_op, CollectInput));
return adt::Ok{};
}
template <typename DoEachT>
adt::Result<adt::Ok> VisitMatchedBirOutputOfRestPtnPackedIrOp(
const DrrPackedIrOp& res_ptn_ir_op, const DoEachT& DoEach) const {
auto DoEachDrrIrValue =
[&](const DrrIrValue& drr_ir_value) -> adt::Result<adt::Ok> {
return VisitMatchedBirValueOfResPtnIrValue(drr_ir_value, DoEach);
};
ADT_RETURN_IF_ERR(
VisitResPtnOutputIrValueByResPtnIrOp(res_ptn_ir_op, DoEachDrrIrValue));
return adt::Ok{};
}
template <typename DoEachT>
adt::Result<adt::Ok> 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 <typename DoEachT>
adt::Result<adt::Ok> VisitMatchedBirValueOfResPtnIrValue(
const DrrIrValue& res_ptn_ir_value, const DoEachT& DoEach) const {
using Ok = adt::Result<adt::Ok>;
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 <typename DoEachIndexT, typename DoEachSliceT>
adt::Result<adt::Ok> VisitApKernelInputIndexOrSlice(
const DrrPackedIrOp& res_ptn_ir_op,
const DoEachIndexT& DoEachIndex,
const DoEachSliceT& DoEachSlice) const {
std::size_t start = 0;
using Ok = adt::Result<adt::Ok>;
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 <typename DoEachIndexT, typename DoEachSliceT>
adt::Result<adt::Ok> VisitApKernelOutputIndexOrSlice(
const DrrPackedIrOp& res_ptn_ir_op,
const DoEachIndexT& DoEachIndex,
const DoEachSliceT& DoEachSlice) const {
std::size_t start = 0;
using Ok = adt::Result<adt::Ok>;
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<std::size_t> GetApKernelNumOutputs(
const DrrPackedIrOp& res_ptn_ir_op) const {
std::size_t num_outputs = 0;
auto AccNumOutputs =
[&](const DrrIrValue& drr_ir_value) -> adt::Result<adt::Ok> {
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 <typename T, typename IrOpT, typename DoEachT>
adt::Result<adt::Ok> VisitEachMatchedDrrIrValueAndOutputSlice(
const std::vector<T>& 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::Ok> {
ADT_LET_CONST_REF(num_ir_values, GetResPtnNumBirValues(drr_ir_value));
ADT_CHECK(offset + num_ir_values <= output_values.size());
std::vector<T> 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 <typename IrOpT, typename DoEachT>
adt::Result<adt::Ok> 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<std::size_t> 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<DrrIrValue> 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<BirNativeIrValue> CastToBirNativeIrValue(
const BirNode& bir_node) const {
using RetT = adt::Result<BirNativeIrValue>;
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