Skip to content

Commit

Permalink
Remove unused parser declarations and unused parser type declarations…
Browse files Browse the repository at this point in the history
… that result from `RemoveRedundantParsers` pass. (p4lang#4368)

* Remove unused parser declarations and unused parser type declarations that result from `RemoveRedundantParsers` pass.
* Add unit test
* Still call RemoveAllUnusedDeclarations before RemoveRedundantParsers and add additional RemoveAllUnusedDeclarations pass to RemoveRedundantParsers.
  • Loading branch information
kfcripps authored Jan 31, 2024
1 parent ac98f4c commit 99ac793
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 1 deletion.
5 changes: 5 additions & 0 deletions frontends/p4/redundantParsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ bool FindRedundantParsers::preorder(const IR::P4Parser *parser) {
}

const IR::Node *EliminateSubparserCalls::postorder(IR::MethodCallStatement *mcs) {
// Only remove redundant parser applications in parser states. Parser applications
// made in illegal locations (such as control blocks) will be detected by and error
// will be reported in later passes (i.e. DiscoverInlining).
if (!findContext<IR::ParserState>()) return mcs;

auto mi = MethodInstance::resolve(mcs->methodCall, refMap, typeMap, true);
if (!mi->isApply()) return mcs;

Expand Down
4 changes: 3 additions & 1 deletion frontends/p4/redundantParsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
#define FRONTENDS_P4_REDUNDANTPARSERS_H_

#include "frontends/p4/typeChecking/typeChecker.h"
#include "frontends/p4/unusedDeclarations.h"
#include "ir/ir.h"

namespace P4 {
Expand Down Expand Up @@ -56,7 +57,8 @@ class RemoveRedundantParsers : public PassManager {
RemoveRedundantParsers(ReferenceMap *refMap, TypeMap *typeMap)
: PassManager{new TypeChecking(refMap, typeMap, true),
new FindRedundantParsers(redundantParsers),
new EliminateSubparserCalls(redundantParsers, refMap, typeMap)} {
new EliminateSubparserCalls(redundantParsers, refMap, typeMap),
new RemoveAllUnusedDeclarations(refMap)} {
setName("RemoveRedundantParsers");
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// The RemoveRedundantParsers pass removes applications of parsers which
// unconditionally transition to the accept state from the start state.
// For example:
// parser callee() {
// state start {
// transition accept;
// }
// }
//
// parser caller() {
// callee() subparser;
// state start {
// subparser.apply(); // <--- removed by RemoveRedundantParsers pass
// transition accept;
// }
// }
//
// After the application of 'subparser' is removed by RemoveRedundantParsers,
// subparser's unused declaration as well as its type's declaration remains.
// This test validates that these declarations get removed after the RemoveRedundantParsers
// pass. If they aren't removed, a Compiler Bug will occur in one of the inlining passes
// in some cases, and other unexpected behavior could occur elsewhere as well.

#include <core.p4>

header h_t {
bit<16> f;
}

struct headers {
h_t h1;
h_t h2;
}

// This unused parser type declaration remains after RemoveRedundantParsers.
parser RedundantParser(inout headers hdr) {
state start {
transition accept;
}
}

parser IParser2(packet_in packet, inout headers hdr) {
state start {
packet.extract(hdr.h2);
transition select(hdr.h2.f) {
default: accept;
}
}
}

parser IParser(packet_in packet, inout headers hdr) {
// This unused local parser declaration remains after RemoveRedundantParsers.
RedundantParser() redundant_parser;

state start {
packet.extract(hdr.h1);
transition select(hdr.h1.f) {
1 : s1;
default : s2;
}
}

state s1 {
// The below application of redundant_parser gets optimized out by RemoveRedundantParsers.
redundant_parser.apply(hdr);
transition accept;
}

state s2 {
IParser2.apply(packet, hdr);
transition accept;
}
}

parser Parser(packet_in p, inout headers hdr);
package top(Parser p);
top(IParser()) main;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <core.p4>

header h_t {
bit<16> f;
}

struct headers {
h_t h1;
h_t h2;
}

parser RedundantParser(inout headers hdr) {
state start {
transition accept;
}
}

parser IParser2(packet_in packet, inout headers hdr) {
state start {
packet.extract<h_t>(hdr.h2);
transition select(hdr.h2.f) {
default: accept;
}
}
}

parser IParser(packet_in packet, inout headers hdr) {
RedundantParser() redundant_parser;
@name("IParser2") IParser2() IParser2_inst;
state start {
packet.extract<h_t>(hdr.h1);
transition select(hdr.h1.f) {
16w1: s1;
default: s2;
}
}
state s1 {
redundant_parser.apply(hdr);
transition accept;
}
state s2 {
IParser2_inst.apply(packet, hdr);
transition accept;
}
}

parser Parser(packet_in p, inout headers hdr);
package top(Parser p);
top(IParser()) main;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <core.p4>

header h_t {
bit<16> f;
}

struct headers {
h_t h1;
h_t h2;
}

parser IParser(packet_in packet, inout headers hdr) {
state start {
packet.extract<h_t>(hdr.h1);
transition select(hdr.h1.f) {
16w1: s1;
default: s2;
}
}
state s1 {
transition accept;
}
state s2 {
transition IParser2_start;
}
state IParser2_start {
packet.extract<h_t>(hdr.h2);
transition select(hdr.h2.f) {
default: s2_0;
}
}
state s2_0 {
transition accept;
}
}

parser Parser(packet_in p, inout headers hdr);
package top(Parser p);
top(IParser()) main;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <core.p4>

header h_t {
bit<16> f;
}

struct headers {
h_t h1;
h_t h2;
}

parser IParser(packet_in packet, inout headers hdr) {
state start {
packet.extract<h_t>(hdr.h1);
transition select(hdr.h1.f) {
16w1: s1;
default: s2;
}
}
state s1 {
transition accept;
}
state s2 {
packet.extract<h_t>(hdr.h2);
transition accept;
}
}

parser Parser(packet_in p, inout headers hdr);
package top(Parser p);
top(IParser()) main;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include <core.p4>

header h_t {
bit<16> f;
}

struct headers {
h_t h1;
h_t h2;
}

parser RedundantParser(inout headers hdr) {
state start {
transition accept;
}
}

parser IParser2(packet_in packet, inout headers hdr) {
state start {
packet.extract(hdr.h2);
transition select(hdr.h2.f) {
default: accept;
}
}
}

parser IParser(packet_in packet, inout headers hdr) {
RedundantParser() redundant_parser;
state start {
packet.extract(hdr.h1);
transition select(hdr.h1.f) {
1: s1;
default: s2;
}
}
state s1 {
redundant_parser.apply(hdr);
transition accept;
}
state s2 {
IParser2.apply(packet, hdr);
transition accept;
}
}

parser Parser(packet_in p, inout headers hdr);
package top(Parser p);
top(IParser()) main;
Empty file.

0 comments on commit 99ac793

Please sign in to comment.