P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
commonInlining.h
1/*
2Copyright 2018 VMware, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef FRONTENDS_P4_COMMONINLINING_H_
18#define FRONTENDS_P4_COMMONINLINING_H_
19
20#define DEBUG_INLINER 0
21
22#if DEBUG_INLINER
23#include "frontends/p4/toP4/toP4.h"
24#endif
25#include "frontends/p4/callGraph.h"
26#include "ir/ir.h"
27
33namespace P4 {
34
35template <class Callable, class CallNode>
37 // Callable can be P4Action, Function, P4Control, P4Parser
38 public:
39 const Callable *caller; // object that performs the call
40 const Callable *callee; // object that is called
41 const CallNode *call;
42
43 SimpleCallInfo(const Callable *caller, const Callable *callee, const CallNode *call)
44 : caller(caller), callee(callee), call(call) {
45 CHECK_NULL(caller);
46 CHECK_NULL(callee);
47 CHECK_NULL(call);
48 }
49 void dbprint(std::ostream &out) const {
50 out << dbp(callee) << " into " << dbp(caller) << " at " << dbp(call);
51 }
52};
53
54template <class Callable, class CallNode, class CallInfo>
56 public:
57 // Map caller -> statement -> callee
58 std::map<const Callable *, std::map<const CallNode *, const Callable *>> sites;
59 void add(CallInfo *info) {
60 CHECK_NULL(info);
61 LOG3(info);
62 sites[info->caller][info->call] = info->callee;
63 }
64 void dbprint(std::ostream &out) const {
65 for (auto t : sites) {
66 out << dbp(t.first);
67 for (auto c : t.second) {
68 out << std::endl << "\t" << dbp(c.first) << " => " << dbp(c.second);
69 }
70 }
71 }
72 bool empty() const { return sites.empty(); }
73};
74
75template <class Callable, class CallInfo, class InlineWorkList>
77 std::vector<CallInfo *> toInline; // initial data
78 std::vector<CallInfo *> inlineOrder; // sorted in inlining order
79
80 public:
81 // generate the inlining order
82 void analyze() {
83 // We only keep the call graph between objects of the same kind.
84 P4::CallGraph<const Callable *> cg("Call-graph");
85 for (auto c : toInline) cg.calls(c->caller, c->callee);
86
87 // must inline from leaves up
88 std::vector<const Callable *> order;
89 cg.sort(order);
90 for (auto c : order) {
91 // This is quadratic, but hopefully the call graph is not too large
92 for (auto ci : toInline) {
93 if (ci->caller == c) inlineOrder.push_back(ci);
94 }
95 }
96
97 std::reverse(inlineOrder.begin(), inlineOrder.end());
98 }
99
100 size_t size() const { return toInline.size(); }
101
103 InlineWorkList *next() {
104 if (inlineOrder.size() == 0) return nullptr;
105
106 std::set<const Callable *> callers;
107 auto result = new InlineWorkList();
108
109 // Find callables that can be inlined simultaneously.
110 // This traversal is in topological order starting from leaf callees.
111 // We stop at the first callable which calls one of the callables
112 // we have already selected.
113 while (!inlineOrder.empty()) {
114 auto last = inlineOrder.back();
115 if (callers.find(last->callee) != callers.end()) break;
116 inlineOrder.pop_back();
117 result->add(last);
118 callers.emplace(last->caller);
119 }
120 BUG_CHECK(!result->empty(), "Empty list of methods to inline");
121 return result;
122 }
123
124 void add(CallInfo *aci) { toInline.push_back(aci); }
125
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;
131 }
132 }
133};
134
135// Base class for inliners
136template <class InlineList, class InlineWorkList>
137class AbstractInliner : public Transform {
138 protected:
139 InlineList *list;
140 InlineWorkList *toInline;
141 AbstractInliner() : list(nullptr), toInline(nullptr) {}
142
143 public:
144 void prepare(InlineList *list, InlineWorkList *toInline) {
145 CHECK_NULL(list);
146 CHECK_NULL(toInline);
147 this->list = list;
148 this->toInline = toInline;
149 }
150 Visitor::profile_t init_apply(const IR::Node *node) {
151 LOG2("AbstractInliner " << toInline);
152 return Transform::init_apply(node);
153 }
154 virtual ~AbstractInliner() {}
155};
156
157template <class InlineList, class InlineWorkList>
158class InlineDriver : public Visitor {
159 InlineList *toInline;
161
162 public:
164 : toInline(toInline), inliner(inliner) {
165 CHECK_NULL(toInline);
166 CHECK_NULL(inliner);
167 setName((cstring("InlineDriver_") + cstring(inliner->name())).c_str());
168 }
169 const IR::Node *apply_visitor(const IR::Node *program, const char * = 0) override {
170 LOG2("InlineDriver");
171 toInline->analyze();
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;
178
179#if DEBUG_INLINER
180 // debugging code; we don't have an easy way to dump the program here,
181 // since we are not between passes
182 ToP4 top4(&std::cout, false, nullptr);
183 program->apply(top4);
184#endif
185 }
186 return program;
187 }
188};
189
190} // namespace P4
191
192#endif /* FRONTENDS_P4_COMMONINLINING_H_ */
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 toP4.h:30
Definition cstring.h:72
Definition applyOptionsPragmas.cpp:24
Describes information about a caller-callee pair.
Definition inlining.h:36