Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove apply() calls to redundant parsers #3356

Merged
merged 4 commits into from
Jun 25, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Remove apply() calls to redundant parsers
A parser with an unconditional accept in its start state is
effectively a redundant/dummy parser and can be eliminated when it is
called as a subparser. This removes the apply() calls to these
subparsers, which also removes the generation of the setInvalid() call
in resetHeaders.
  • Loading branch information
bleibig committed Jun 16, 2022
commit 7a2fa10d34fe62f04d62372a249a0a34528b09d6
1 change: 1 addition & 0 deletions frontends/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ set (P4_FRONTEND_SRCS
p4/parserCallGraph.cpp
p4/parserControlFlow.cpp
p4/reassociation.cpp
p4/redundantParsers.cpp
mihaibudiu marked this conversation as resolved.
Show resolved Hide resolved
p4/removeParameters.cpp
p4/removeReturns.cpp
p4/reservedWords.cpp
Expand Down
2 changes: 2 additions & 0 deletions frontends/p4/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ limitations under the License.
#include "parseAnnotations.h"
#include "parserControlFlow.h"
#include "reassociation.h"
#include "redundantParsers.h"
#include "removeParameters.h"
#include "removeReturns.h"
#include "resetHeaders.h"
Expand Down Expand Up @@ -219,6 +220,7 @@ const IR::P4Program *FrontEnd::run(const CompilerOptions &options, const IR::P4P
new MoveConstructors(&refMap),
new RemoveAllUnusedDeclarations(&refMap),
new ClearTypeMap(&typeMap),
new RemoveRedundantParsers(&typeMap),
evaluator,
new Inline(&refMap, &typeMap, evaluator, options.optimizeParserInlining),
new InlineActions(&refMap, &typeMap),
Expand Down
58 changes: 58 additions & 0 deletions frontends/p4/redundantParsers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright 2013-present Barefoot Networks, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you really wait 9 years to subit this patch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "redundantParsers.h"

namespace P4 {
bool FindRedundantParsers::preorder(const IR::P4Parser *parser) {
for (const IR::ParserState *state : parser->states) {
if (state->name != IR::ParserState::start) {
continue;
}
const auto *pathExpr = state->selectExpression->to<IR::PathExpression>();
if (!pathExpr ||
pathExpr->path->name != IR::ParserState::accept ||
!state->components.empty()) {
continue;
}
LOG4("Found redundant parser " << parser->name);
redundantParsers.insert(parser->type->name);
}
return false;
}

const IR::Node *EliminateSubparserCalls::postorder(IR::MethodCallStatement *mcs) {
auto method = mcs->methodCall->method;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a helper class called MethodInstance which can help with this.
It will return an ApplyMethod object for a parser invocation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using that, but I was hitting some assertion failures. Maybe there are still some issues with MethodInstance, I can look into that.

auto *member = method->to<IR::Member>();
if (!member || member->member != IR::IApply::applyMethodName) {
return mcs;
}
auto type = typeMap->getType(member->expr);
if (!type) {
return mcs;
}
auto parser = type->to<IR::Type_Parser>();
if (!parser) {
return mcs;
}
if (redundantParsers.count(parser->name)) {
LOG4("Removing apply call to redundant parser " << parser->getName()
<< ": " << *mcs);
return nullptr;
}
return mcs;
}
}
63 changes: 63 additions & 0 deletions frontends/p4/redundantParsers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
Copyright 2013-present Barefoot Networks, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not 2022?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef _P4_REDUNDANT_PARSERS_H
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the same format for the macro as in other frontend files; otherwise cpplint will be upset.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

#define _P4_REDUNDANT_PARSERS_H

#include "ir/ir.h"
#include "typeMap.h"

namespace P4 {

/** Find parsers that have an unconditional "accept" in their start
* state, and put them in redundantParsers.
*/
class FindRedundantParsers : public Inspector {
std::set<cstring> &redundantParsers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why string and not IR::P4Parser?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using IR::P4Parser *, it didn't quite work because the pointers discovered in RemoveRedundantParsers did not match those found earlier, despite having the same name. Is there supposed to be a single instance of every declaration in the IR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a transform you should use getOriginal(), there are lots of examples in the code

bool preorder(const IR::P4Parser *parser) override;
public:
FindRedundantParsers(std::set<cstring> &redundantParsers)
: redundantParsers(redundantParsers) { }
};

/** Find .apply() calls on parsers that are on redundantParsers, and
* eliminate them.
*/
class EliminateSubparserCalls : public Transform {
const std::set<cstring> &redundantParsers;
TypeMap *typeMap;
const IR::Node *postorder(IR::MethodCallStatement *methodCallStmt) override;
public:
EliminateSubparserCalls(const std::set<cstring> &redundantParsers, TypeMap *typeMap)
: redundantParsers(redundantParsers), typeMap(typeMap)
{ }
};

class RemoveRedundantParsers : public PassManager {
std::set<cstring> redundantParsers;
public:
RemoveRedundantParsers(TypeMap *typeMap)
: PassManager {
new FindRedundantParsers(redundantParsers),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want the 'type' field to be correct then you have to insert a call to typeChecking here. But it's probably simpler in that case to pass the computed typeMap annd use MethodInstance with a typeMap argument.

new EliminateSubparserCalls(redundantParsers, typeMap)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The typeMap will always be empty the way you inserted this pass.
Don't you need to invoke the typechecker first?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do you will need a handle to the referenceMap too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to run before ClearTypeMap. Though from my testing, even before the type map was not empty when this pass was run.

} {
setName("RemoveRedundantParsers");
}
};

}

#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cpplint will want this to be followed by a comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done