17#ifndef FRONTENDS_P4_COMMONINLINING_H_
18#define FRONTENDS_P4_COMMONINLINING_H_
20#define DEBUG_INLINER 0
23#include "frontends/p4/toP4/toP4.h"
25#include "frontends/p4/callGraph.h"
35template <
class Callable,
class CallNode>
39 const Callable *caller;
40 const Callable *callee;
43 SimpleCallInfo(
const Callable *caller,
const Callable *callee,
const CallNode *call)
44 : caller(caller), callee(callee), call(call) {
49 void dbprint(std::ostream &out)
const {
50 out << dbp(callee) <<
" into " << dbp(caller) <<
" at " << dbp(call);
54template <
class Callable,
class CallNode,
class CallInfo>
58 std::map<const Callable *, std::map<const CallNode *, const Callable *>> sites;
62 sites[info->caller][info->call] = info->callee;
64 void dbprint(std::ostream &out)
const {
65 for (
auto t : sites) {
67 for (
auto c : t.second) {
68 out << std::endl <<
"\t" << dbp(c.first) <<
" => " << dbp(c.second);
72 bool empty()
const {
return sites.empty(); }
75template <
class Callable,
class CallInfo,
class InlineWorkList>
77 std::vector<CallInfo *> toInline;
78 std::vector<CallInfo *> inlineOrder;
85 for (
auto c : toInline) cg.calls(c->caller, c->callee);
88 std::vector<const Callable *> order;
90 for (
auto c : order) {
92 for (
auto ci : toInline) {
93 if (ci->caller == c) inlineOrder.push_back(ci);
97 std::reverse(inlineOrder.begin(), inlineOrder.end());
100 size_t size()
const {
return toInline.size(); }
104 if (inlineOrder.size() == 0)
return nullptr;
106 std::set<const Callable *> callers;
107 auto result =
new InlineWorkList();
113 while (!inlineOrder.empty()) {
114 auto last = inlineOrder.back();
115 if (callers.find(last->callee) != callers.end())
break;
116 inlineOrder.pop_back();
118 callers.emplace(last->caller);
120 BUG_CHECK(!result->empty(),
"Empty list of methods to inline");
124 void add(
CallInfo *aci) { toInline.push_back(aci); }
126 void replace(
const Callable *container,
const Callable *replacement) {
127 LOG2(
"Substituting " << container <<
" with " << replacement);
128 for (
auto e : inlineOrder) {
129 if (e->callee == container) e->callee = replacement;
130 if (e->caller == container) e->caller = replacement;
136template <
class InlineList,
class InlineWorkList>
140 InlineWorkList *toInline;
144 void prepare(
InlineList *list, InlineWorkList *toInline) {
146 CHECK_NULL(toInline);
148 this->toInline = toInline;
150 Visitor::profile_t init_apply(
const IR::Node *node) {
151 LOG2(
"AbstractInliner " << toInline);
152 return Transform::init_apply(node);
157template <
class InlineList,
class InlineWorkList>
164 : toInline(toInline), inliner(inliner) {
165 CHECK_NULL(toInline);
167 setName((
cstring(
"InlineDriver_") +
cstring(inliner->name())).c_str());
169 const IR::Node *apply_visitor(
const IR::Node *program,
const char * = 0)
override {
170 LOG2(
"InlineDriver");
172 LOG3(
"InlineList size " << toInline->size());
173 while (
auto todo = toInline->next()) {
174 LOG2(
"Processing " << todo);
175 inliner->prepare(toInline, todo);
176 program = program->apply(*inliner);
177 if (::errorCount() > 0)
break;
182 ToP4 top4(&std::cout,
false,
nullptr);
183 program->apply(top4);
Definition source_file.h:38
Definition commonInlining.h:137
Definition callGraph.h:41
Definition commonInlining.h:158
Definition inlining.h:308
Definition commonInlining.h:36
Definition commonInlining.h:76
InlineWorkList * next()
Get next batch of objects to inline.
Definition commonInlining.h:103
Definition commonInlining.h:55
Definition applyOptionsPragmas.cpp:24
Describes information about a caller-callee pair.
Definition inlining.h:36