P4C
The P4 Compiler
Loading...
Searching...
No Matches
action_synthesis_policy.h
1
19#ifndef BF_P4C_MIDEND_ACTION_SYNTHESIS_POLICY_H_
20#define BF_P4C_MIDEND_ACTION_SYNTHESIS_POLICY_H_
21
22#include "backends/tofino/bf-p4c/ir/tofino_write_context.h"
23#include "backends/tofino/bf-p4c/midend/register_read_write.h"
24#include "midend/actionSynthesis.h"
25
26namespace BFN {
27
45 P4::ReferenceMap *refMap;
46 P4::TypeMap *typeMap;
47 // set of controls where actions are not synthesized
48 const std::set<cstring> *skip;
49
50 bool convert(const Visitor::Context *, const IR::P4Control *control) override {
51 if (control->is<IR::BFN::TnaDeparser>()) {
52 return false;
53 }
54 for (auto c : *skip)
55 if (control->name == c) return false;
56 return true;
57 }
58
59 static const IR::Type_Extern *externType(const IR::Type *type) {
60 if (auto *spec = type->to<IR::Type_SpecializedCanonical>()) type = spec->baseType;
61 return type->to<IR::Type_Extern>();
62 }
63
64 class FindPathsWritten : public Inspector, TofinoWriteContext {
65 std::set<cstring> &writes;
66 bool preorder(const IR::PathExpression *pe) {
67 if (isWrite()) writes.insert(pe->toString());
68 return false;
69 }
70 bool preorder(const IR::Member *m) {
71 if (isWrite()) writes.insert(m->toString());
72 return false;
73 }
74 bool preorder(const IR::AssignmentStatement *assign) {
75 // special case -- ignore writing the result of a 'hash.get' call to a var,
76 // as we can use that directly in the same action (hash is computed in ixbar hash)
77 if (auto *mc = assign->right->to<IR::MethodCallExpression>()) {
78 if (auto *m = mc->method->to<IR::Member>()) {
79 if (auto *et = externType(m->expr->type)) {
80 if (et->name == "Hash" && m->member == "get") return false;
81 }
82 }
83 }
84 return true;
85 }
86
87 public:
88 explicit FindPathsWritten(std::set<cstring> &w) : writes(w) {}
89 };
90
91 class DependsOnPaths : public Inspector {
93 std::set<cstring> &paths;
94 bool rv = false;
95 bool preorder(const IR::PathExpression *pe) {
96 if (paths.count(pe->toString())) rv = true;
97 return !rv;
98 }
99 bool preorder(const IR::Member *m) {
100 if (paths.count(m->toString())) rv = true;
101 return !rv;
102 }
103 bool preorder(const IR::Node *) { return !rv; }
104 void postorder(const IR::MethodCallExpression *mc) {
105 auto *mi = P4::MethodInstance::resolve(mc, self.refMap, self.typeMap, true);
106 if (auto *em = mi ? mi->to<P4::ExternMethod>() : nullptr) {
107 for (auto *n : em->mayCall()) {
108 if (auto *fn = n->to<IR::Function>()) {
109 visit(fn->body, "body");
110 }
111 }
112 }
113 }
114
115 public:
116 explicit operator bool() { return rv; }
117 DependsOnPaths(ActionSynthesisPolicy &self, const IR::Node *n, std::set<cstring> &p)
118 : self(self), paths(p), rv(false) {
119 n->apply(*this);
120 }
121 };
122
123 class ReferencesExtern : public Inspector {
124 bool rv = false;
125 bool preorder(const IR::PathExpression *pe) {
126 if (rv) return false;
127 auto *et = externType(pe->type);
128 if (et && et->name != "Hash") {
129 rv = true;
130 }
131 return !rv;
132 }
133 bool preorder(const IR::Node *) { return !rv; }
134
135 public:
136 explicit operator bool() { return rv; }
137 explicit ReferencesExtern(const IR::Node *n) { n->apply(*this); }
138 };
139
145 bool isRegisterWriteAfterRead(const IR::BlockStatement *blk, const IR::StatOrDecl *stmt_decl) {
146 auto *blk_stmt = blk->components.back()->to<IR::Statement>();
147 if (!blk_stmt) return false;
149 auto *read_mce = read_rv.first;
150 if (!read_mce) return false;
151
152 auto *stmt = stmt_decl->to<IR::Statement>();
153 if (!stmt) return false;
155 auto *write_mce = write_rv.first;
156 if (!write_mce) return false;
157
158 auto *read_inst = P4::MethodInstance::resolve(read_mce, refMap, typeMap);
159 // Check also object becuase of plain functions
160 if (!read_inst || !read_inst->object) return false;
161 auto *read_decl = read_inst->object->to<IR::Declaration_Instance>();
162 if (!read_decl) return false;
163
164 auto *read_member = read_mce->method->to<IR::Member>();
165 if (!read_member) return false;
166 auto *read_extern_type = externType(read_member->expr->type);
167 if (!read_extern_type) return false;
168 if (read_extern_type->name != "Register" || read_member->member != "read") return false;
169
170 auto *write_inst = P4::MethodInstance::resolve(write_mce, refMap, typeMap);
171 // Check also object becuase of plain functions
172 if (!write_inst || !write_inst->object) return false;
173 auto *write_decl = write_inst->object->to<IR::Declaration_Instance>();
174 if (!write_decl) return false;
175
176 auto *write_member = write_mce->method->to<IR::Member>();
177 if (!write_member) return false;
178 auto *write_extern_type = externType(write_member->expr->type);
179 if (!write_extern_type) return false;
180 if (write_extern_type->name != "Register" || write_member->member != "write") return false;
181
182 if (read_decl->declid != write_decl->declid) return false;
183
184 return true;
185 }
186
187 bool can_combine(const Visitor::Context *, const IR::BlockStatement *blk,
188 const IR::StatOrDecl *stmt) override {
189 if (isRegisterWriteAfterRead(blk, stmt)) return true;
190 std::set<cstring> writes;
191 if (ReferencesExtern(blk) && ReferencesExtern(stmt)) return false;
192 blk->apply(FindPathsWritten(writes));
193 return !DependsOnPaths(*this, stmt, writes);
194 }
195
196 public:
197 ActionSynthesisPolicy(const std::set<cstring> *skip, P4::ReferenceMap *refMap,
198 P4::TypeMap *typeMap)
199 : refMap(refMap), typeMap(typeMap), skip(skip) {
200 CHECK_NULL(skip);
201 }
202};
203
204} // namespace BFN
205
206#endif /* BF_P4C_MIDEND_ACTION_SYNTHESIS_POLICY_H_ */
Definition actionSynthesis.h:30
virtual bool can_combine(const Visitor::Context *, const IR::BlockStatement *, const IR::StatOrDecl *)
Definition actionSynthesis.h:49
virtual bool convert(const Visitor::Context *ctxt, const IR::P4Control *control)=0
Definition methodInstance.h:168
Definition node.h:94
Definition visitor.h:400
static MethodInstance * resolve(const IR::MethodCallExpression *mce, const DeclarationLookup *refMap, TypeMap *typeMap, bool useExpressionType=false, const Visitor::Context *ctxt=nullptr, bool incomplete=false)
Definition methodInstance.cpp:27
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition typeMap.h:41
Definition tofino_write_context.h:24
bool isWrite(bool root_value=false)
Definition ir/tofino_write_context.cpp:23
static std::pair< const IR::MethodCallExpression *, const IR::Expression * > extractRegisterReadWrite(const IR::Statement *reg_stmt)
Definition midend/register_read_write.cpp:92
The namespace encapsulating Barefoot/Intel-specific stuff.
Definition add_t2na_meta.cpp:21
T * to() noexcept
Definition rtti.h:226
Definition visitor.h:47