Skip to content

Commit 153bfb9

Browse files
author
Mathew Suresh Zachariah
committed
Updates to RemoveParameters
Signed-off-by: Mathew Suresh Zachariah <mazachar@pensando.io>
1 parent c9f7234 commit 153bfb9

12 files changed

+311
-34
lines changed

backends/tofino/bf-p4c/midend/remove_action_params.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ namespace BFN {
3535
*/
3636
class DoRemoveActionParametersTofino : public P4::DoRemoveActionParameters {
3737
public:
38-
explicit DoRemoveActionParametersTofino(P4::ActionInvocation *inv)
39-
: P4::DoRemoveActionParameters(inv) {}
38+
explicit DoRemoveActionParametersTofino(P4::ActionInvocation *inv, P4::TypeMap *typeMap)
39+
: P4::DoRemoveActionParameters(inv, typeMap) {}
4040

4141
/**
4242
* Check if there is a mark_to_drop action and don't replace parameters.
@@ -187,7 +187,7 @@ class RemoveActionParameters : public PassManager {
187187
if (!tc) tc = new P4::TypeChecking(refMap, typeMap);
188188
passes.emplace_back(tc);
189189
passes.emplace_back(new P4::FindActionParameters(typeMap, ai));
190-
passes.emplace_back(new DoRemoveActionParametersTofino(ai));
190+
passes.emplace_back(new DoRemoveActionParametersTofino(ai, typeMap));
191191
passes.emplace_back(new P4::ClearTypeMap(typeMap));
192192
}
193193
};

frontends/p4/functionsInlining.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,7 @@ const IR::Node *FunctionsInliner::preorder(IR::MethodCallExpression *expr) {
155155
auto it = pendingReplacements.find(orig);
156156
if (it != pendingReplacements.end()) {
157157
LOG2("Performing pending replacement of " << dbp(expr) << " with " << dbp(it->second));
158-
auto result = it->second;
159-
pendingReplacements.erase(it);
160-
return result;
158+
return it->second;
161159
}
162160

163161
return expr;

frontends/p4/functionsInlining.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class FunctionsInliner : public AbstractInliner<FunctionsInlineList, FunctionsIn
7676
class isLocalExpression; // functor to test actual arguments scope use
7777

7878
public:
79-
FunctionsInliner() { visitDagOnce = false; }
79+
FunctionsInliner() = default;
8080
Visitor::profile_t init_apply(const IR::Node *node) override;
8181
void end_apply(const IR::Node *node) override;
8282
const IR::Node *preorder(IR::Function *function) override;

frontends/p4/removeParameters.cpp

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,47 @@ limitations under the License.
1919
#include "frontends/common/resolveReferences/resolveReferences.h"
2020
#include "frontends/p4/methodInstance.h"
2121
#include "frontends/p4/moveDeclarations.h"
22+
#include "frontends/p4/sideEffects.h"
2223
#include "frontends/p4/tableApply.h"
2324
#include "frontends/p4/typeChecking/typeChecker.h"
2425

2526
namespace P4 {
2627

2728
namespace {
29+
30+
// Extract side-effecting array index expressions into temporaries
31+
// to ensure they are evaluated exactly once for inout copy-in/copy-out.
32+
class ExtractArrayIndices : public Transform {
33+
TypeMap *typeMap;
34+
MinimalNameGenerator &nameGen;
35+
IR::IndexedVector<IR::Declaration> &tempDecls;
36+
IR::IndexedVector<IR::StatOrDecl> &tempAssigns;
37+
38+
public:
39+
ExtractArrayIndices(TypeMap *typeMap, MinimalNameGenerator &nameGen,
40+
IR::IndexedVector<IR::Declaration> &tempDecls,
41+
IR::IndexedVector<IR::StatOrDecl> &tempAssigns)
42+
: typeMap(typeMap), nameGen(nameGen), tempDecls(tempDecls), tempAssigns(tempAssigns) {
43+
setName("ExtractArrayIndices");
44+
}
45+
const IR::Node *preorder(IR::ArrayIndex *aindex) override {
46+
visit(aindex->left);
47+
if (SideEffects::check(aindex->right, called_by, typeMap)) {
48+
if (auto indexType = typeMap->getType(aindex->right, true)) {
49+
auto tmp = nameGen.newName("tmp_idx");
50+
auto decl = new IR::Declaration_Variable(aindex->right->srcInfo, tmp, indexType);
51+
tempDecls.push_back(decl);
52+
auto assign = new IR::AssignmentStatement(
53+
aindex->right->srcInfo, new IR::PathExpression(tmp), aindex->right);
54+
tempAssigns.push_back(assign);
55+
aindex->right = new IR::PathExpression(aindex->right->srcInfo, new IR::Path(tmp));
56+
}
57+
}
58+
prune();
59+
return aindex;
60+
}
61+
};
62+
2863
// Remove arguments from any embedded MethodCallExpression
2964
class RemoveMethodCallArguments : public Transform {
3065
int argumentsToRemove; // -1 => all
@@ -117,6 +152,8 @@ const IR::Node *DoRemoveActionParameters::postorder(IR::P4Action *action) {
117152
ParameterSubstitution substitution;
118153
substitution.populate(action->parameters, args);
119154

155+
MinimalNameGenerator nameGen(action);
156+
120157
bool removeAll = invocations->removeAllParameters(getOriginal<IR::P4Action>());
121158
for (auto p : action->parameters->parameters) {
122159
if (p->direction == IR::Direction::None && !removeAll) {
@@ -133,16 +170,35 @@ const IR::Node *DoRemoveActionParameters::postorder(IR::P4Action *action) {
133170
continue;
134171
}
135172

136-
if (p->direction == IR::Direction::In || p->direction == IR::Direction::InOut ||
137-
p->direction == IR::Direction::None) {
173+
if (p->direction == IR::Direction::InOut) {
174+
// For inout parameters, extract side-effecting array indices
175+
// into temporaries to evaluate them once and avoid DAG sharing.
176+
IR::IndexedVector<IR::Declaration> tempDecls;
177+
IR::IndexedVector<IR::StatOrDecl> tempAssigns;
178+
ExtractArrayIndices eai(typeMap, nameGen, tempDecls, tempAssigns);
179+
eai.setCalledBy(this);
180+
auto argExpr = arg->expression->apply(eai)->to<IR::Expression>();
181+
for (auto *d : tempDecls) result->push_back(d);
182+
body.append(tempAssigns);
183+
138184
auto left = new IR::PathExpression(p->name);
139-
auto assign = new IR::AssignmentStatement(arg->srcInfo, left, arg->expression);
185+
auto assign = new IR::AssignmentStatement(arg->srcInfo, left, argExpr);
140186
body.push_back(assign);
141-
}
142-
if (p->direction == IR::Direction::Out || p->direction == IR::Direction::InOut) {
187+
143188
auto right = new IR::PathExpression(p->name);
144-
auto assign = new IR::AssignmentStatement(arg->srcInfo, arg->expression, right);
145-
postamble.push_back(assign);
189+
auto assign2 = new IR::AssignmentStatement(arg->srcInfo, argExpr->clone(), right);
190+
postamble.push_back(assign2);
191+
} else {
192+
if (p->direction == IR::Direction::In || p->direction == IR::Direction::None) {
193+
auto left = new IR::PathExpression(p->name);
194+
auto assign = new IR::AssignmentStatement(arg->srcInfo, left, arg->expression);
195+
body.push_back(assign);
196+
}
197+
if (p->direction == IR::Direction::Out) {
198+
auto right = new IR::PathExpression(p->name);
199+
auto assign = new IR::AssignmentStatement(arg->srcInfo, arg->expression, right);
200+
postamble.push_back(assign);
201+
}
146202
}
147203
}
148204
}
@@ -198,7 +254,7 @@ RemoveActionParameters::RemoveActionParameters(TypeMap *typeMap, TypeChecking *t
198254
if (!typeChecking) typeChecking = new TypeChecking(nullptr, typeMap);
199255
passes.emplace_back(typeChecking);
200256
passes.emplace_back(new FindActionParameters(typeMap, ai));
201-
passes.emplace_back(new DoRemoveActionParameters(ai));
257+
passes.emplace_back(new DoRemoveActionParameters(ai, typeMap));
202258
passes.emplace_back(new ClearTypeMap(typeMap));
203259
}
204260

frontends/p4/removeParameters.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,13 @@ class FindActionParameters : public Inspector, public ResolutionContext {
114114
*/
115115
class DoRemoveActionParameters : public Transform {
116116
ActionInvocation *invocations;
117+
TypeMap *typeMap;
117118

118119
public:
119-
explicit DoRemoveActionParameters(ActionInvocation *invocations) : invocations(invocations) {
120+
DoRemoveActionParameters(ActionInvocation *invocations, TypeMap *typeMap)
121+
: invocations(invocations), typeMap(typeMap) {
120122
CHECK_NULL(invocations);
123+
CHECK_NULL(typeMap);
121124
setName("DoRemoveActionParameters");
122125
}
123126

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <core.p4>
2+
3+
bit<3> max(in bit<3> val, in bit<3> bound) {
4+
return val < bound ? val : bound;
5+
}
6+
7+
header inner_t {
8+
bit<8> f2;
9+
}
10+
11+
header outer_t {
12+
bit<8> f1;
13+
}
14+
15+
struct mid_t {
16+
inner_t[1] inner_arr;
17+
}
18+
19+
struct Headers {
20+
outer_t[1] outer_arr;
21+
mid_t[1] mid_arr;
22+
}
23+
24+
control proto(inout Headers h);
25+
package top(proto _c);
26+
27+
// Test: expr[i1].f1[i2].f2 — chained array indices with function calls and field accesses
28+
control ingress(inout Headers h) {
29+
action a(inout bit<8> val) {
30+
val = 8w1;
31+
}
32+
table t {
33+
actions = { a(h.mid_arr[max(3w0, 3w0)].inner_arr[max(3w0, 3w0)].f2); }
34+
}
35+
apply { t.apply(); }
36+
}
37+
38+
top(ingress()) main;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <core.p4>
2+
3+
bit<3> max(in bit<3> val, in bit<3> bound) {
4+
return (val < bound ? val : bound);
5+
}
6+
header inner_t {
7+
bit<8> f2;
8+
}
9+
10+
header outer_t {
11+
bit<8> f1;
12+
}
13+
14+
struct mid_t {
15+
inner_t[1] inner_arr;
16+
}
17+
18+
struct Headers {
19+
outer_t[1] outer_arr;
20+
mid_t[1] mid_arr;
21+
}
22+
23+
control proto(inout Headers h);
24+
package top(proto _c);
25+
control ingress(inout Headers h) {
26+
action a(inout bit<8> val) {
27+
val = 8w1;
28+
}
29+
table t {
30+
actions = {
31+
a(h.mid_arr[max(3w0, 3w0)].inner_arr[max(3w0, 3w0)].f2);
32+
@defaultonly NoAction();
33+
}
34+
default_action = NoAction();
35+
}
36+
apply {
37+
t.apply();
38+
}
39+
}
40+
41+
top(ingress()) main;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <core.p4>
2+
3+
header inner_t {
4+
bit<8> f2;
5+
}
6+
7+
header outer_t {
8+
bit<8> f1;
9+
}
10+
11+
struct mid_t {
12+
inner_t[1] inner_arr;
13+
}
14+
15+
struct Headers {
16+
outer_t[1] outer_arr;
17+
mid_t[1] mid_arr;
18+
}
19+
20+
control proto(inout Headers h);
21+
package top(proto _c);
22+
control ingress(inout Headers h) {
23+
@name("ingress.val") bit<8> val;
24+
@name("ingress.tmp_idx") bit<3> tmp_idx_1;
25+
@name("ingress.tmp_idx_0") bit<3> tmp_idx_2;
26+
@name("ingress.val_0") bit<3> val_3;
27+
@name("ingress.bound_0") bit<3> bound;
28+
@name("ingress.retval") bit<3> retval;
29+
@name("ingress.tmp") bit<3> tmp;
30+
@name("ingress.inlinedRetval") bit<3> inlinedRetval_1;
31+
@name("ingress.val_2") bit<3> val_4;
32+
@name("ingress.bound_1") bit<3> bound_2;
33+
@name("ingress.retval") bit<3> retval_1;
34+
@name("ingress.tmp") bit<3> tmp_1;
35+
@name("ingress.inlinedRetval_0") bit<3> inlinedRetval_2;
36+
@noWarn("unused") @name(".NoAction") action NoAction_1() {
37+
}
38+
@name("ingress.a") action a() {
39+
val_3 = 3w0;
40+
bound = 3w0;
41+
if (val_3 < bound) {
42+
tmp = val_3;
43+
} else {
44+
tmp = bound;
45+
}
46+
retval = tmp;
47+
inlinedRetval_1 = retval;
48+
tmp_idx_1 = inlinedRetval_1;
49+
val_4 = 3w0;
50+
bound_2 = 3w0;
51+
if (val_4 < bound_2) {
52+
tmp_1 = val_4;
53+
} else {
54+
tmp_1 = bound_2;
55+
}
56+
retval_1 = tmp_1;
57+
inlinedRetval_2 = retval_1;
58+
tmp_idx_2 = inlinedRetval_2;
59+
val = 8w1;
60+
h.mid_arr[tmp_idx_1].inner_arr[tmp_idx_2].f2 = val;
61+
}
62+
@name("ingress.t") table t_0 {
63+
actions = {
64+
a();
65+
@defaultonly NoAction_1();
66+
}
67+
default_action = NoAction_1();
68+
}
69+
apply {
70+
t_0.apply();
71+
}
72+
}
73+
74+
top(ingress()) main;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include <core.p4>
2+
3+
header inner_t {
4+
bit<8> f2;
5+
}
6+
7+
header outer_t {
8+
bit<8> f1;
9+
}
10+
11+
struct mid_t {
12+
inner_t[1] inner_arr;
13+
}
14+
15+
struct Headers {
16+
outer_t[1] outer_arr;
17+
mid_t[1] mid_arr;
18+
}
19+
20+
control proto(inout Headers h);
21+
package top(proto _c);
22+
control ingress(inout Headers h) {
23+
@noWarn("unused") @name(".NoAction") action NoAction_1() {
24+
}
25+
@name("ingress.a") action a() {
26+
h.mid_arr[3w0].inner_arr[3w0].f2 = 8w1;
27+
}
28+
@name("ingress.t") table t_0 {
29+
actions = {
30+
a();
31+
@defaultonly NoAction_1();
32+
}
33+
default_action = NoAction_1();
34+
}
35+
apply {
36+
t_0.apply();
37+
}
38+
}
39+
40+
top(ingress()) main;

0 commit comments

Comments
 (0)