17#ifndef FRONTENDS_P4_INLINING_H_ 
   18#define FRONTENDS_P4_INLINING_H_ 
   20#include "commonInlining.h" 
   21#include "frontends/common/resolveReferences/referenceMap.h" 
   22#include "frontends/p4/evaluator/evaluator.h" 
   23#include "frontends/p4/evaluator/substituteParameters.h" 
   24#include "frontends/p4/typeChecking/typeChecker.h" 
   25#include "frontends/p4/unusedDeclarations.h" 
   27#include "lib/ordered_map.h" 
   37    const IR::IContainer *caller;
 
   38    const IR::IContainer *callee;
 
   39    const IR::Declaration_Instance *instantiation;  
 
   41    std::set<const IR::MethodCallStatement *> invocations;  
 
   43    CallInfo(
const IR::IContainer *caller, 
const IR::IContainer *callee,
 
   44             const IR::Declaration_Instance *instantiation)
 
   45        : caller(caller), callee(callee), instantiation(instantiation) {
 
   48        CHECK_NULL(instantiation);
 
   50    void addInvocation(
const IR::MethodCallStatement *statement) { invocations.emplace(statement); }
 
   51    void dbprint(std::ostream &out)
 const {
 
   52        out << 
"Inline " << callee << 
" into " << caller << 
" with " << invocations.size()
 
 
   58    std::map<const IR::IDeclaration *, cstring> internalName;
 
   59    std::map<const IR::IDeclaration *, cstring> externalName;
 
   64        BUG_CHECK(!name.isNullOrEmpty() && !extName.isNullOrEmpty(), 
"Empty name");
 
   65        LOG3(
"setNewName " << dbp(decl) << 
" to " << name);
 
   66        if (internalName.find(decl) != internalName.end()) BUG(
"%1%: already renamed", decl);
 
   67        internalName.emplace(decl, name);
 
   68        externalName.emplace(decl, extName);
 
   72        BUG_CHECK(internalName.find(decl) != internalName.end(), 
"%1%: no new name", decl);
 
   73        auto result = ::get(internalName, decl);
 
   78        BUG_CHECK(externalName.find(decl) != externalName.end(), 
"%1%: no external name", decl);
 
   79        auto result = ::get(externalName, decl);
 
   84        return internalName.find(decl) != internalName.end();
 
 
   94        : paramSubst(other.paramSubst), tvs(other.tvs), renameMap(other.renameMap) {}
 
 
  131        typedef std::pair<const IR::MethodCallStatement *, const IR::PathExpression *>
 
  141                std::ostringstream oss;
 
  142                std::get<0>(k)->dbprint(oss);
 
  143                std::get<1>(k)->dbprint(oss);
 
  144                return std::hash<std::string>{}(oss.str());
 
 
  156                return std::get<0>(v0)->equiv(*std::get<0>(v1)) &&
 
  157                       std::get<1>(v0)->equiv(*std::get<1>(v1));
 
 
  162        std::map<const IR::Declaration_Instance *, const IR::IContainer *> 
declToCallee;
 
  164        std::map<const IR::Declaration_Instance *, PerInstanceSubstitutions *> 
substitutions;
 
  166        std::map<const IR::MethodCallStatement *, const IR::Declaration_Instance *> 
callToInstance;
 
  276        std::unordered_map<const InlinedInvocationInfo, const IR::ID, key_hash, key_equal>
 
  282            const IR::Declaration_Instance *instance)
 const {
 
  283            const IR::MethodCallStatement *call = 
nullptr;
 
  285                if (m.second == instance) {
 
 
 
  295    std::map<const IR::IContainer *, PerCaller> callerToWork;
 
  298        callerToWork[cci->caller].declToCallee[cci->instantiation] = cci->callee;
 
  299        for (
auto mcs : cci->invocations)
 
  300            callerToWork[cci->caller].callToInstance[mcs] = cci->instantiation;
 
  302    void dbprint(std::ostream &out)
 const {
 
  303        out << 
"Inline " << callerToWork.size() << 
" call sites";
 
 
  311    std::vector<CallInfo *> toInline;  
 
  312    const bool allowMultipleCalls = 
true;
 
  315    void addInstantiation(
const IR::IContainer *caller, 
const IR::IContainer *callee,
 
  316                          const IR::Declaration_Instance *instantiation) {
 
  319        CHECK_NULL(instantiation);
 
  320        LOG3(
"Inline instantiation " << dbp(instantiation));
 
  321        auto inst = 
new CallInfo(caller, callee, instantiation);
 
  322        inlineMap[instantiation] = inst;
 
  325    size_t size()
 const { 
return inlineMap.size(); }
 
  327    void addInvocation(
const IR::Declaration_Instance *instance,
 
  328                       const IR::MethodCallStatement *statement) {
 
  329        CHECK_NULL(instance);
 
  330        CHECK_NULL(statement);
 
  331        LOG3(
"Inline invocation " << dbp(instance) << 
" at " << dbp(statement));
 
  332        auto info = inlineMap[instance];
 
  333        BUG_CHECK(info, 
"Could not locate instance %1% invoked by %2%", instance, statement);
 
  334        info->addInvocation(statement);
 
  337    void replace(
const IR::IContainer *container, 
const IR::IContainer *replacement) {
 
  338        CHECK_NULL(container);
 
  339        CHECK_NULL(replacement);
 
  340        LOG3(
"Replacing " << dbp(container) << 
" with " << dbp(replacement));
 
  341        for (
auto e : toInline) {
 
  342            if (e->callee == container) e->callee = replacement;
 
  343            if (e->caller == container) e->caller = replacement;
 
 
  357    IR::ToplevelBlock *toplevel;
 
  360    bool allowParsers = 
true;
 
  361    bool allowControls = 
true;
 
  365        : inlineList(inlineList),
 
  368          evaluator(evaluator),
 
  370        CHECK_NULL(inlineList);
 
  373        CHECK_NULL(evaluator);
 
  374        setName(
"DiscoverInlining");
 
  375        visitDagOnce = 
false;
 
  378        toplevel = evaluator->getToplevelBlock();
 
  379        CHECK_NULL(toplevel);
 
  380        return Inspector::init_apply(node);
 
  382    void visit_all(
const IR::Block *block);
 
  383    bool preorder(
const IR::Block *block)
 override {
 
  387    bool preorder(
const IR::ControlBlock *block) 
override;
 
  388    bool preorder(
const IR::ParserBlock *block) 
override;
 
  389    void postorder(
const IR::MethodCallStatement *statement) 
override;
 
  391    bool preorder(
const IR::P4Program *)
 override {
 
 
  402    bool optimizeParserInlining;
 
  409          optimizeParserInlining(_optimizeParserInlining) {
 
  410        setName(
"GeneralInliner");
 
  411        visitDagOnce = 
false;
 
  414    const IR::Node *preorder(IR::MethodCallStatement *statement) 
override;
 
  419    template <
class P4Block, 
class P4BlockType>
 
  421                      const P4BlockType *P4Block::*blockType);
 
  422    const IR::Node *preorder(IR::P4Control *caller) 
override;
 
  423    const IR::Node *preorder(IR::P4Parser *caller) 
override;
 
  424    const IR::Node *preorder(IR::ParserState *state) 
override;
 
 
  440        setName(
"InlinePass");
 
 
  450    static std::set<cstring> noPropagateAnnotations;
 
 
Definition stringify.h:31
 
The Declaration interface, representing objects with names.
Definition declaration.h:26
 
Definition commonInlining.h:157
 
Must be run after an evaluator; uses the blocks to discover caller/callee relationships.
Definition inlining.h:352
 
Definition evaluator.h:114
 
Performs actual inlining work.
Definition inlining.h:398
 
void inline_subst(P4Block *caller, IR::IndexedVector< IR::Declaration > P4Block::*blockLocals, const P4BlockType *P4Block::*blockType)
Definition inlining.cpp:461
 
Definition evaluator.h:27
 
Definition commonInlining.h:178
 
Definition inlining.h:449
 
static bool isAnnotationNoPropagate(cstring name)
Is annotation name excluded from inline propagation?
Definition inlining.h:466
 
static void setAnnotationNoPropagate(cstring name)
Do not propagate annotation name during inlining.
Definition inlining.h:463
 
Definition inlining.h:308
 
Performs one round of inlining bottoms-up.
Definition inlining.h:429
 
Definition parameterSubstitution.h:30
 
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
 
Iterates RemoveUnusedDeclarations until convergence.
Definition unusedDeclarations.h:146
 
Definition unusedDeclarations.h:28
 
Definition typeChecker.h:55
 
Definition typeSubstitution.h:73
 
Definition pass_manager.h:38
 
Definition pass_manager.h:143
 
Definition ordered_map.h:30
 
Definition applyOptionsPragmas.cpp:24
 
Describes information about a caller-callee pair.
Definition inlining.h:36
 
Definition inlining.h:153
 
Definition inlining.h:139
 
Various substitutions that must be applied for each instance.
Definition inlining.h:102
 
const IR::MethodCallStatement * uniqueCaller(const IR::Declaration_Instance *instance) const
Definition inlining.h:281
 
std::map< const IR::Declaration_Instance *, const IR::IContainer * > declToCallee
For each instance (key) the container that is intantiated.
Definition inlining.h:162
 
std::unordered_map< const InlinedInvocationInfo, const IR::ID, key_hash, key_equal > invocationToState
Definition inlining.h:277
 
std::map< const IR::MethodCallStatement *, const IR::Declaration_Instance * > callToInstance
For each invocation (key) call the instance that is invoked.
Definition inlining.h:166
 
std::map< const IR::Declaration_Instance *, PerInstanceSubstitutions * > substitutions
For each instance (key) we must apply a bunch of substitutions.
Definition inlining.h:164
 
std::pair< const IR::MethodCallStatement *, const IR::PathExpression * > InlinedInvocationInfo
Definition inlining.h:132
 
Summarizes all inline operations to be performed.
Definition inlining.h:100