17#ifndef FRONTENDS_P4_INLINING_H_
18#define FRONTENDS_P4_INLINING_H_
20#include "commonInlining.h"
21#include "frontends/common/parser_options.h"
22#include "frontends/common/resolveReferences/referenceMap.h"
23#include "frontends/p4/evaluator/evaluator.h"
24#include "frontends/p4/evaluator/substituteParameters.h"
25#include "frontends/p4/typeChecking/typeChecker.h"
26#include "frontends/p4/unusedDeclarations.h"
28#include "lib/ordered_map.h"
38 const IR::IContainer *caller;
39 const IR::IContainer *callee;
40 const IR::Declaration_Instance *instantiation;
42 std::set<const IR::MethodCallStatement *> invocations;
44 CallInfo(
const IR::IContainer *caller,
const IR::IContainer *callee,
45 const IR::Declaration_Instance *instantiation)
46 : caller(caller), callee(callee), instantiation(instantiation) {
49 CHECK_NULL(instantiation);
51 void addInvocation(
const IR::MethodCallStatement *statement) { invocations.emplace(statement); }
52 void dbprint(std::ostream &out)
const {
53 out <<
"Inline " << callee <<
" into " << caller <<
" with " << invocations.size()
59 std::map<const IR::IDeclaration *, cstring> internalName;
60 std::map<const IR::IDeclaration *, cstring> externalName;
65 BUG_CHECK(!name.isNullOrEmpty() && !extName.isNullOrEmpty(),
"Empty name");
66 LOG3(
"setNewName " << dbp(decl) <<
" to " << name);
67 if (internalName.find(decl) != internalName.end()) BUG(
"%1%: already renamed", decl);
68 internalName.emplace(decl, name);
69 externalName.emplace(decl, extName);
73 BUG_CHECK(internalName.find(decl) != internalName.end(),
"%1%: no new name", decl);
74 auto result = ::P4::get(internalName, decl);
79 BUG_CHECK(externalName.find(decl) != externalName.end(),
"%1%: no external name", decl);
80 auto result = ::P4::get(externalName, decl);
85 return internalName.find(decl) != internalName.end();
95 : paramSubst(other.paramSubst), tvs(other.tvs), renameMap(other.renameMap) {}
132 typedef std::pair<const IR::MethodCallStatement *, const IR::PathExpression *>
142 std::ostringstream oss;
143 std::get<0>(k)->dbprint(oss);
144 std::get<1>(k)->dbprint(oss);
145 return std::hash<std::string>{}(oss.str());
157 return std::get<0>(v0)->equiv(*std::get<0>(v1)) &&
158 std::get<1>(v0)->equiv(*std::get<1>(v1));
163 std::map<const IR::Declaration_Instance *, const IR::IContainer *>
declToCallee;
165 std::map<const IR::Declaration_Instance *, PerInstanceSubstitutions *>
substitutions;
167 std::map<const IR::MethodCallStatement *, const IR::Declaration_Instance *>
callToInstance;
277 std::unordered_map<const InlinedInvocationInfo, const IR::ID, key_hash, key_equal>
283 const IR::Declaration_Instance *instance)
const {
284 const IR::MethodCallStatement *call =
nullptr;
286 if (m.second == instance) {
296 std::map<const IR::IContainer *, PerCaller> callerToWork;
299 callerToWork[cci->caller].declToCallee[cci->instantiation] = cci->callee;
300 for (
auto mcs : cci->invocations)
301 callerToWork[cci->caller].callToInstance[mcs] = cci->instantiation;
303 void dbprint(std::ostream &out)
const {
304 out <<
"Inline " << callerToWork.size() <<
" call sites";
312 std::vector<CallInfo *> toInline;
313 const bool allowMultipleCalls =
true;
316 void addInstantiation(
const IR::IContainer *caller,
const IR::IContainer *callee,
317 const IR::Declaration_Instance *instantiation) {
320 CHECK_NULL(instantiation);
321 LOG3(
"Inline instantiation " << dbp(instantiation));
322 auto inst =
new CallInfo(caller, callee, instantiation);
323 inlineMap[instantiation] = inst;
326 size_t size()
const {
return inlineMap.size(); }
328 void addInvocation(
const IR::Declaration_Instance *instance,
329 const IR::MethodCallStatement *statement) {
330 CHECK_NULL(instance);
331 CHECK_NULL(statement);
332 LOG3(
"Inline invocation " << dbp(instance) <<
" at " << dbp(statement));
333 auto info = inlineMap[instance];
334 BUG_CHECK(
info,
"Could not locate instance %1% invoked by %2%", instance, statement);
335 info->addInvocation(statement);
338 void replace(
const IR::IContainer *container,
const IR::IContainer *replacement) {
339 CHECK_NULL(container);
340 CHECK_NULL(replacement);
341 LOG3(
"Replacing " << dbp(container) <<
" with " << dbp(replacement));
342 for (
auto e : toInline) {
343 if (e->callee == container) e->callee = replacement;
344 if (e->caller == container) e->caller = replacement;
358 IR::ToplevelBlock *toplevel;
361 bool allowParsers =
true;
362 bool allowControls =
true;
366 : inlineList(inlineList),
369 evaluator(evaluator),
371 CHECK_NULL(inlineList);
374 CHECK_NULL(evaluator);
375 setName(
"DiscoverInlining");
376 visitDagOnce =
false;
379 toplevel = evaluator->getToplevelBlock();
380 CHECK_NULL(toplevel);
381 return Inspector::init_apply(node);
383 void visit_all(
const IR::Block *block);
384 bool preorder(
const IR::Block *block)
override {
388 bool preorder(
const IR::ControlBlock *block)
override;
389 bool preorder(
const IR::ParserBlock *block)
override;
390 void postorder(
const IR::MethodCallStatement *statement)
override;
392 bool preorder(
const IR::P4Program *)
override {
403 bool optimizeParserInlining;
410 optimizeParserInlining(_optimizeParserInlining) {
411 setName(
"GeneralInliner");
412 visitDagOnce =
false;
415 const IR::Node *preorder(IR::MethodCallStatement *statement)
override;
420 template <
class P4Block,
class P4BlockType>
422 const P4BlockType *P4Block::*blockType);
423 const IR::Node *preorder(IR::P4Control *caller)
override;
424 const IR::Node *preorder(IR::P4Parser *caller)
override;
425 const IR::Node *preorder(IR::ParserState *state)
override;
441 setName(
"InlinePass");
451 static std::set<cstring> noPropagateAnnotations;
458 auto *evInstance = evaluator ? evaluator :
new EvaluatorPass(&refMap, typeMap);
462 {
new InlinePass(&refMap, typeMap, evInstance, policy, optimizeParserInlining),
Definition commonInlining.h:157
Must be run after an evaluator; uses the blocks to discover caller/callee relationships.
Definition inlining.h:353
Definition evaluator.h:115
Performs actual inlining work.
Definition inlining.h:399
void inline_subst(P4Block *caller, IR::IndexedVector< IR::Declaration > P4Block::*blockLocals, const P4BlockType *P4Block::*blockType)
Definition inlining.cpp:461
Definition evaluator.h:28
Definition stringify.h:33
The Declaration interface, representing objects with names.
Definition declaration.h:26
Definition commonInlining.h:178
Definition inlining.h:450
static bool isAnnotationNoPropagate(cstring name)
Is annotation name excluded from inline propagation?
Definition inlining.h:474
static void setAnnotationNoPropagate(cstring name)
Do not propagate annotation name during inlining.
Definition inlining.h:471
Definition inlining.h:309
Performs one round of inlining bottoms-up.
Definition inlining.h:430
static P4CContext & get()
Definition parser_options.cpp:539
Definition parameterSubstitution.h:30
Definition ir/pass_manager.h:40
Definition ir/pass_manager.h:145
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
void setIsV1(bool isv1)
Set boolean indicating whether map is for a P4_14 program to isV1.
Definition referenceMap.h:105
Iterates RemoveUnusedDeclarations until convergence.
Definition unusedDeclarations.h:189
Definition unusedDeclarations.h:48
Definition typeChecker.h:55
Definition typeSubstitution.h:73
Definition ordered_map.h:32
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:148
Describes information about a caller-callee pair.
Definition inlining.h:37
Definition inlining.h:154
Definition inlining.h:140
Various substitutions that must be applied for each instance.
Definition inlining.h:103
const IR::MethodCallStatement * uniqueCaller(const IR::Declaration_Instance *instance) const
Definition inlining.h:282
std::map< const IR::Declaration_Instance *, const IR::IContainer * > declToCallee
For each instance (key) the container that is intantiated.
Definition inlining.h:163
std::unordered_map< const InlinedInvocationInfo, const IR::ID, key_hash, key_equal > invocationToState
Definition inlining.h:278
std::map< const IR::MethodCallStatement *, const IR::Declaration_Instance * > callToInstance
For each invocation (key) call the instance that is invoked.
Definition inlining.h:167
std::map< const IR::Declaration_Instance *, PerInstanceSubstitutions * > substitutions
For each instance (key) we must apply a bunch of substitutions.
Definition inlining.h:165
std::pair< const IR::MethodCallStatement *, const IR::PathExpression * > InlinedInvocationInfo
Definition inlining.h:133
Summarizes all inline operations to be performed.
Definition inlining.h:101