8#ifndef FRONTENDS_P4_COMMONINLINING_H_
9#define FRONTENDS_P4_COMMONINLINING_H_
11#include "frontends/common/resolveReferences/resolveReferences.h"
12#define DEBUG_INLINER 0
15#include "frontends/p4/toP4/toP4.h"
17#include "frontends/p4/callGraph.h"
29template <
class CallableT,
class CallNodeT,
class CallExpressionT = IR::MethodCallExpression>
33 using Callable = CallableT;
34 using CallNode = CallNodeT;
35 using CallExpression = CallExpressionT;
37 const Callable *caller;
38 const Callable *callee;
40 const CallExpression *callExpr;
42 SimpleCallInfo(
const Callable *caller,
const Callable *callee,
const CallNode *call,
43 const CallExpression *expr)
44 : caller(caller), callee(callee), call(call), callExpr(expr) {
50 void dbprint(std::ostream &out)
const {
51 out << dbp(callee) <<
" into " << dbp(caller) <<
" at " << dbp(call) <<
" via "
56template <
class CallInfo>
59 using ReplacementMap = std::map<
60 const typename CallInfo::CallNode *,
61 std::pair<const typename CallInfo::Callable *, const typename CallInfo::CallExpression *>>;
63 std::map<const typename CallInfo::Callable *, ReplacementMap> sites;
69 void dbprint(std::ostream &out)
const {
70 for (
auto t : sites) {
72 for (
auto c : t.second) {
74 <<
"\t" << dbp(c.first) <<
" => " << dbp(c.second.first) <<
" via "
75 << dbp(c.second.second);
79 bool empty()
const {
return sites.empty(); }
82template <
class Callable,
class CallInfo,
class InlineWorkList>
84 std::vector<CallInfo *> toInline;
85 std::vector<CallInfo *> inlineOrder;
92 for (
auto c : toInline) cg.calls(c->caller, c->callee);
95 std::vector<const Callable *> order;
97 for (
auto c : order) {
99 for (
auto ci : toInline) {
100 if (ci->caller == c) inlineOrder.push_back(ci);
104 std::reverse(inlineOrder.begin(), inlineOrder.end());
107 size_t size()
const {
return toInline.size(); }
115 if (inlineOrder.size() == 0)
return nullptr;
117 std::set<const Callable *> callers;
118 auto result =
new InlineWorkList();
124 while (!inlineOrder.empty()) {
125 auto last = inlineOrder.back();
126 if (callers.find(last->callee) != callers.end())
break;
127 inlineOrder.pop_back();
129 callers.emplace(last->caller);
131 BUG_CHECK(!result->empty(),
"Empty list of methods to inline");
135 void add(
CallInfo *aci) { toInline.push_back(aci); }
137 void replace(
const Callable *container,
const Callable *replacement) {
138 LOG2(
"Substituting " << container <<
" with " << replacement);
139 for (
auto e : inlineOrder) {
140 if (e->callee == container) e->callee = replacement;
141 if (e->caller == container) e->caller = replacement;
147template <
class InlineList,
class InlineWorkList>
148class AbstractInliner :
public Transform,
public ResolutionContext {
151 InlineWorkList *toInline;
152 AbstractInliner() : list(
nullptr), toInline(
nullptr) {}
155 void prepare(
InlineList *list, InlineWorkList *toInline) {
157 CHECK_NULL(toInline);
159 this->toInline = toInline;
162 LOG2(
"AbstractInliner " << toInline);
163 return Transform::init_apply(node);
165 virtual ~AbstractInliner() {}
168template <
class InlineList,
class InlineWorkList>
169class InlineDriver :
public Visitor {
175 : toInline(toInline), inliner(inliner) {
176 CHECK_NULL(toInline);
178 setName((
"InlineDriver_"_cs +
cstring(inliner->name())).c_str());
180 const IR::Node *apply_visitor(
const IR::Node *program,
const char * = 0)
override {
181 LOG2(
"InlineDriver");
183 LOG3(
"InlineList size " << toInline->size());
184 while (
auto todo = toInline->next()) {
185 LOG2(
"Processing " << todo);
186 inliner->prepare(toInline, todo);
187 program = program->apply(*inliner);
193 ToP4 top4(&std::cout,
false,
nullptr);
194 program->apply(top4);
Definition commonInlining.h:148
Definition callGraph.h:41
Definition stringify.h:33
Definition inlining.h:300
Definition commonInlining.h:83
InlineWorkList * next()
Get next batch of objects to inline.
Definition commonInlining.h:114
Definition commonInlining.h:57
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
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:167
unsigned errorCount()
Definition lib/error.h:34
Describes information about a caller-callee pair.
Definition inlining.h:28