Skip to content

Commit 9deae97

Browse files
committed
Extend CopyStructures to optionally copy tuples
Signed-off-by: Chris Dodd <[email protected]>
1 parent 745318f commit 9deae97

File tree

12 files changed

+177
-13
lines changed

12 files changed

+177
-13
lines changed

backends/p4test/midend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,10 @@ MidEnd::MidEnd(P4TestOptions &options, std::ostream *outStream) {
106106
new P4::HandleNoMatch(),
107107
new P4::SimplifyParsers(),
108108
new P4::StrengthReduction(&typeMap),
109-
new P4::EliminateTuples(&typeMap),
109+
options.keepTuples ? nullptr : new P4::EliminateTuples(&typeMap),
110110
new P4::FlattenLogMsg(&typeMap),
111111
new P4::SimplifyComparisons(&typeMap),
112-
new P4::CopyStructures(&typeMap, false),
112+
new P4::CopyStructures(&typeMap, false, false, options.keepTuples),
113113
new P4::NestedStructs(&typeMap),
114114
new P4::StrengthReduction(&typeMap),
115115
new P4::SimplifySelectList(&typeMap),

backends/p4test/p4test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ P4TestOptions::P4TestOptions() {
8686
return true;
8787
},
8888
"use passes that use general switch instead of action_run");
89+
registerOption(
90+
"--keepTuples", nullptr, [this](const char *) { return keepTuples = true; },
91+
"keep tuple type, but flatten assignments of them");
8992
}
9093

9194
class P4TestPragmas : public P4::P4COptionPragmaParser {

backends/p4test/p4test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class P4TestOptions : public CompilerOptions {
2727
bool validateOnly = false;
2828
bool loadIRFromJson = false;
2929
bool preferSwitch = false;
30+
bool keepTuples = false; // keep tuples but flatten assignments of them
3031
P4TestOptions();
3132
};
3233

backends/p4tools/common/compiler/midend.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ void MidEnd::addDefaultPasses() {
121121
new P4::SimplifyComparisons(&typeMap),
122122
// Expand header and struct assignments into sequences of field assignments.
123123
new PassRepeated({
124-
new P4::CopyStructures(&typeMap, false, true, nullptr),
124+
new P4::CopyStructures(&typeMap, false, true, false, nullptr),
125125
}),
126126
new P4::RemoveParserControlFlow(&typeMap),
127127
// Flatten nested list expressions.

midend/copyStructures.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
#include "copyStructures.h"
1818

1919
#include "frontends/p4/alias.h"
20+
#include "ir/irutils.h"
2021

2122
namespace P4 {
2223

@@ -66,7 +67,8 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
6667
const auto *ltype = typeMap->getType(statement->left, true);
6768

6869
// If the left type is not a struct like or a header stack, return.
69-
if (!(ltype->is<IR::Type_StructLike>() || ltype->is<IR::Type_Array>())) {
70+
if (!ltype->is<IR::Type_StructLike>() && !ltype->is<IR::Type_Array>() &&
71+
!ltype->is<IR::Type_Tuple>()) {
7072
return statement;
7173
}
7274
/*
@@ -153,6 +155,15 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
153155
new IR::ArrayIndex(stack->elementType, statement->right, new IR::Constant(i));
154156
retval.push_back(new IR::AssignmentStatement(srcInfo, left, right));
155157
}
158+
} else if (auto *tup = ltype->to<IR::Type_Tuple>()) {
159+
if (!copyTuples) return statement;
160+
int idx = 0;
161+
for (auto *el : tup->components) {
162+
const auto *left = new IR::ArrayIndex(el, statement->left, new IR::Constant(idx));
163+
const auto *right = new IR::ArrayIndex(el, statement->right, new IR::Constant(idx));
164+
retval.push_back(new IR::AssignmentStatement(srcInfo, left, right));
165+
++idx;
166+
}
156167
} else {
157168
if (ltype->is<IR::Type_Header>() || ltype->is<IR::Type_Array>()) {
158169
// Leave headers as they are -- copy_header will also copy the valid bit
@@ -168,7 +179,7 @@ const IR::Node *DoCopyStructures::postorder(IR::AssignmentStatement *statement)
168179
retval.push_back(new IR::AssignmentStatement(statement->srcInfo, left, right));
169180
}
170181
}
171-
return new IR::BlockStatement(statement->srcInfo, std::move(retval));
182+
return IR::inlineBlock(*this, std::move(retval));
172183
}
173184

174185
} // namespace P4

midend/copyStructures.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ namespace P4 {
4444
*
4545
* Further, struct initialization is converted to assignment on struct fields
4646
*
47-
* Note, header assignments are not converted in this pass.
47+
* header assignments and tuple assignments are optionally converted in this pass, based
48+
* on constructor argument
4849
*
4950
* @pre none
5051
* @post
@@ -62,13 +63,22 @@ class DoCopyStructures : public Transform {
6263

6364
/// Do not only copy normal structures but also perform copy assignments for headers.
6465
bool copyHeaders;
66+
/// Also split up assignments of tuples
67+
bool copyTuples;
6568

6669
public:
67-
explicit DoCopyStructures(TypeMap *typeMap, bool errorOnMethodCall, bool copyHeaders = false)
68-
: typeMap(typeMap), errorOnMethodCall(errorOnMethodCall), copyHeaders(copyHeaders) {
70+
explicit DoCopyStructures(TypeMap *typeMap, bool errorOnMethodCall, bool copyHeaders = false,
71+
bool copyTuples = true)
72+
: typeMap(typeMap),
73+
errorOnMethodCall(errorOnMethodCall),
74+
copyHeaders(copyHeaders),
75+
copyTuples(copyTuples) {
6976
CHECK_NULL(typeMap);
7077
setName("DoCopyStructures");
7178
}
79+
// FIXME -- this should be a preorder so we can deal with nested structs directly,
80+
// but that fails because we depend on the typeMap which will be out of date after
81+
// expanding outer copies. So we need to repeat this pass in a loop
7282
const IR::Node *postorder(IR::AssignmentStatement *statement) override;
7383
};
7484

@@ -117,14 +127,13 @@ class RemoveAliases : public Transform {
117127
class CopyStructures : public PassRepeated {
118128
public:
119129
explicit CopyStructures(TypeMap *typeMap, bool errorOnMethodCall = true,
120-
bool copyHeaders = false, TypeChecking *typeChecking = nullptr) {
130+
bool copyHeaders = false, bool copyTuples = false,
131+
TypeChecking *typeChecking = nullptr) {
121132
CHECK_NULL(typeMap);
122133
setName("CopyStructures");
123134
if (typeChecking == nullptr) typeChecking = new TypeChecking(nullptr, typeMap);
124-
passes.emplace_back(typeChecking);
125-
passes.emplace_back(new RemoveAliases(typeMap));
126-
passes.emplace_back(typeChecking);
127-
passes.emplace_back(new DoCopyStructures(typeMap, errorOnMethodCall, copyHeaders));
135+
addPasses({typeChecking, new RemoveAliases(typeMap), typeChecking,
136+
new DoCopyStructures(typeMap, errorOnMethodCall, copyHeaders, copyTuples)});
128137
}
129138
};
130139

testdata/p4_16_samples/tuple5a.p4

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <core.p4>
2+
@command_line("--keepTuples")
3+
control generic<M>(inout M m);
4+
package top<M>(generic<M> c);
5+
6+
struct t1 {
7+
tuple<bit<8>, bit<16>> a;
8+
bit<32> b;
9+
}
10+
11+
struct t2 {
12+
tuple<bit<32>, t1> x;
13+
tuple<t1, bit<32>> y;
14+
}
15+
16+
control c(inout t2 t) {
17+
apply {
18+
t1 tmp = t.x[1];
19+
t.x[0] += t.y[0].b;
20+
t.x[1].a[0] = t.y[1][7:0];
21+
t.x[1].a[1] = t.y[1][tmp.a[0]+:16];
22+
t.y[0] = tmp;
23+
}
24+
}
25+
26+
top(c()) main;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <core.p4>
2+
3+
@command_line("--keepTuples") control generic<M>(inout M m);
4+
package top<M>(generic<M> c);
5+
struct t1 {
6+
tuple<bit<8>, bit<16>> a;
7+
bit<32> b;
8+
}
9+
10+
struct t2 {
11+
tuple<bit<32>, t1> x;
12+
tuple<t1, bit<32>> y;
13+
}
14+
15+
control c(inout t2 t) {
16+
apply {
17+
t1 tmp = t.x[1];
18+
t.x[0] += t.y[0].b;
19+
t.x[1].a[0] = t.y[1][7:0];
20+
t.x[1].a[1] = t.y[1][tmp.a[0]+:16];
21+
t.y[0] = tmp;
22+
}
23+
}
24+
25+
top<t2>(c()) main;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <core.p4>
2+
3+
@command_line("--keepTuples") control generic<M>(inout M m);
4+
package top<M>(generic<M> c);
5+
struct t1 {
6+
tuple<bit<8>, bit<16>> a;
7+
bit<32> b;
8+
}
9+
10+
struct t2 {
11+
tuple<bit<32>, t1> x;
12+
tuple<t1, bit<32>> y;
13+
}
14+
15+
control c(inout t2 t) {
16+
@name("c.tmp") t1 tmp_0;
17+
apply {
18+
tmp_0 = t.x[1];
19+
t.x[0] = t.x[0] + t.y[0].b;
20+
t.x[1].a[0] = t.y[1][7:0];
21+
t.x[1].a[1] = t.y[1][tmp_0.a[0]+:16];
22+
t.y[0] = tmp_0;
23+
}
24+
}
25+
26+
top<t2>(c()) main;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <core.p4>
2+
3+
@command_line("--keepTuples") control generic<M>(inout M m);
4+
package top<M>(generic<M> c);
5+
struct t1 {
6+
tuple<bit<8>, bit<16>> a;
7+
bit<32> b;
8+
}
9+
10+
struct t2 {
11+
tuple<bit<32>, t1> x;
12+
tuple<t1, bit<32>> y;
13+
}
14+
15+
control c(inout t2 t) {
16+
tuple<bit<8>, bit<16>> tmp_0_a;
17+
@hidden action tuple5a18() {
18+
tmp_0_a[0] = t.x[1].a[0];
19+
tmp_0_a[1] = t.x[1].a[1];
20+
t.x[0] = t.x[0] + t.y[0].b;
21+
t.x[1].a[0] = t.y[1][7:0];
22+
t.x[1].a[1] = t.y[1][tmp_0_a[0]+:16];
23+
t.y[0].a[0] = tmp_0_a[0];
24+
t.y[0].a[1] = tmp_0_a[1];
25+
t.y[0].b = t.x[1].b;
26+
}
27+
@hidden table tbl_tuple5a18 {
28+
actions = {
29+
tuple5a18();
30+
}
31+
const default_action = tuple5a18();
32+
}
33+
apply {
34+
tbl_tuple5a18.apply();
35+
}
36+
}
37+
38+
top<t2>(c()) main;

0 commit comments

Comments
 (0)