// 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