17#ifndef FRONTENDS_P4_COMMONINLINING_H_
18#define FRONTENDS_P4_COMMONINLINING_H_
20#include "frontends/common/resolveReferences/resolveReferences.h"
21#define DEBUG_INLINER 0
24#include "frontends/p4/toP4/toP4.h"
26#include "frontends/p4/callGraph.h"
38template <
class CallableT,
class CallNodeT,
class CallExpressionT = IR::MethodCallExpression>
42 using Callable = CallableT;
43 using CallNode = CallNodeT;
44 using CallExpression = CallExpressionT;
46 const Callable *caller;
47 const Callable *callee;
49 const CallExpression *callExpr;
51 SimpleCallInfo(
const Callable *caller,
const Callable *callee,
const CallNode *call,
52 const CallExpression *expr)
53 : caller(caller), callee(callee), call(call), callExpr(expr) {
59 void dbprint(std::ostream &out)
const {
60 out << dbp(callee) <<
" into " << dbp(caller) <<
" at " << dbp(call) <<
" via "
65template <
class CallInfo>
68 using ReplacementMap = std::map<
69 const typename CallInfo::CallNode *,
70 std::pair<const typename CallInfo::Callable *, const typename CallInfo::CallExpression *>>;
72 std::map<const typename CallInfo::Callable *, ReplacementMap> sites;
78 void dbprint(std::ostream &out)
const {
79 for (
auto t : sites) {
81 for (
auto c : t.second) {
83 <<
"\t" << dbp(c.first) <<
" => " << dbp(c.second.first) <<
" via "
84 << dbp(c.second.second);
88 bool empty()
const {
return sites.empty(); }
91template <
class Callable,
class CallInfo,
class InlineWorkList>
93 std::vector<CallInfo *> toInline;
94 std::vector<CallInfo *> inlineOrder;
101 for (
auto c : toInline) cg.calls(c->caller, c->callee);
104 std::vector<const Callable *> order;
106 for (
auto c : order) {
108 for (
auto ci : toInline) {
109 if (ci->caller == c) inlineOrder.push_back(ci);
113 std::reverse(inlineOrder.begin(), inlineOrder.end());
116 size_t size()
const {
return toInline.size(); }
124 if (inlineOrder.size() == 0)
return nullptr;
126 std::set<const Callable *> callers;
127 auto result =
new InlineWorkList();
133 while (!inlineOrder.empty()) {
134 auto last = inlineOrder.back();
135 if (callers.find(last->callee) != callers.end())
break;
136 inlineOrder.pop_back();
138 callers.emplace(last->caller);
140 BUG_CHECK(!result->empty(),
"Empty list of methods to inline");
144 void add(
CallInfo *aci) { toInline.push_back(aci); }
146 void replace(
const Callable *container,
const Callable *replacement) {
147 LOG2(
"Substituting " << container <<
" with " << replacement);
148 for (
auto e : inlineOrder) {
149 if (e->callee == container) e->callee = replacement;
150 if (e->caller == container) e->caller = replacement;
156template <
class InlineList,
class InlineWorkList>
157class AbstractInliner :
public Transform,
public ResolutionContext {
160 InlineWorkList *toInline;
161 AbstractInliner() : list(
nullptr), toInline(
nullptr) {}
164 void prepare(
InlineList *list, InlineWorkList *toInline) {
166 CHECK_NULL(toInline);
168 this->toInline = toInline;
171 LOG2(
"AbstractInliner " << toInline);
172 return Transform::init_apply(node);
174 virtual ~AbstractInliner() {}
177template <
class InlineList,
class InlineWorkList>
178class InlineDriver :
public Visitor {
184 : toInline(toInline), inliner(inliner) {
185 CHECK_NULL(toInline);
187 setName((
"InlineDriver_"_cs +
cstring(inliner->name())).c_str());
189 const IR::Node *apply_visitor(
const IR::Node *program,
const char * = 0)
override {
190 LOG2(
"InlineDriver");
192 LOG3(
"InlineList size " << toInline->size());
193 while (
auto todo = toInline->next()) {
194 LOG2(
"Processing " << todo);
195 inliner->prepare(toInline, todo);
196 program = program->apply(*inliner);
202 ToP4 top4(&std::cout,
false,
nullptr);
203 program->apply(top4);
Definition commonInlining.h:157
Definition callGraph.h:41
Definition stringify.h:33
Definition inlining.h:309
Definition commonInlining.h:92
InlineWorkList * next()
Get next batch of objects to inline.
Definition commonInlining.h:123
Definition commonInlining.h:66
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void info(const int kind, const char *format, const T *node, Args &&...args)
Report info messages of type kind. Requires that the node argument have source info.
Definition lib/error.h:155
unsigned errorCount()
Definition lib/error.h:34
Describes information about a caller-callee pair.
Definition inlining.h:37