P4C
The P4 Compiler
Loading...
Searching...
No Matches
field_defuse.h
1
19#ifndef _FIELD_DEFUSE_H_
20#define _FIELD_DEFUSE_H_
21
22#include <iostream>
23
24#include "backends/tofino/bf-p4c/ir/control_flow_visitor.h"
25#include "backends/tofino/bf-p4c/ir/tofino_write_context.h"
26#include "backends/tofino/bf-p4c/phv/phv_fields.h"
27#include "ir/ir.h"
28#include "lib/ltbitmatrix.h"
29#include "lib/ordered_set.h"
30#include "lib/symbitmatrix.h"
31
32using namespace P4;
33
43class ImplicitParserInit : public IR::Expression {
44 private:
45 IR::Expression *clone() const override {
46 auto *new_expr = new ImplicitParserInit(*this);
47 return new_expr;
48 }
49
50 public:
51 explicit ImplicitParserInit(const PHV::Field *f) : field(f) {}
52 const PHV::Field *field;
53 void dbprint(std::ostream &out) const override {
54 out << "ImplicitParserInit of " << field->id << ":" << field->name;
55 }
56
57 DECLARE_TYPEINFO(ImplicitParserInit);
58};
59
62class WriteParserError : public IR::Expression {
63 private:
64 IR::Expression *clone() const override {
65 auto *new_expr = new WriteParserError(*this);
66 return new_expr;
67 }
68
69 public:
70 explicit WriteParserError(const PHV::Field *f) : field(f) {}
71 const PHV::Field *field;
72 void dbprint(std::ostream &out) const override { out << "write parser error to " << field; }
73
74 DECLARE_TYPEINFO(WriteParserError);
75};
76
78 public:
82 typedef std::pair<const IR::BFN::Unit *, const IR::Expression *> locpair;
84
85 enum VisitMode { VisitJustReads, VisitJustWrites, VisitAll };
86
87 VisitMode mode = VisitAll;
88
93 static const std::unordered_set<cstring> write_by_parser;
94
95 private:
96 const PhvInfo &phv;
97 SymBitMatrix &conflict;
98
101 ordered_map<locpair, bool> &ixbar_refs;
102
104 ordered_map<int, LocPairSet> &located_uses, &located_defs;
105
108
110 LocPairSet &parser_zero_inits;
111
112 // All fields that rely on parser zero initialization.
113 ordered_set<const PHV::Field *> &uninitialized_fields;
114
115 // All fields used as alias destinations.
116 ordered_set<const PHV::Field *> alias_destinations;
117 static const LocPairSet emptyset;
118
120 struct info {
121 const PHV::Field *field = nullptr;
122 LocPairSet def, use;
123 ordered_map<locpair, ordered_set<le_bitrange>> def_covered_ranges_map;
124 // The reason to have a set of bit range is that there is a case that new def's range only
125 // shadows a segment of a previous range, e.g., [3,5] shadows [0,7]. In this case, the
126 // unshadowed range will be cut into two ranges. In addition, as shown in
127 // bf-p4c/test/gtest/field_defuse.cpp test case FieldDefUseTest.ComplexSliceTest3, a def may
128 // be duplicated since a def may go through multiple branchs and each branch may have
129 // different covered def bit range.
130 };
132 std::vector<info> defuse;
133 class ClearBeforeEgress;
134 class CollectAliasDestinations;
135
136 profile_t init_apply(const IR::Node *root) override;
137 void end_apply(const IR::Node *root) override;
138 void end_apply() override;
139 void collect_uninitalized();
140 void check_conflicts(const info &read, int when);
141 void read(const PHV::Field *, std::optional<le_bitrange>, const IR::BFN::Unit *,
142 const IR::Expression *, bool);
143 void read(const IR::HeaderRef *, const IR::BFN::Unit *, const IR::Expression *, bool);
144 void write(const PHV::Field *, std::optional<le_bitrange>, const IR::BFN::Unit *,
145 const IR::Expression *, bool);
146 void write(const IR::HeaderRef *, const IR::BFN::Unit *, const IR::Expression *, bool);
147 info &field(const PHV::Field *);
148 info &field(int id) { return field(phv.field(id)); }
149 void access_field(const PHV::Field *);
150 bool preorder(const IR::BFN::Pipe *p) override;
151 bool preorder(const IR::BFN::Parser *p) override;
152 void postorder(const IR::BFN::Parser *p) override;
153 bool preorder(const IR::BFN::ParserState *ps) override;
154 void postorder(const IR::BFN::ParserState *ps) override;
155 bool preorder(const IR::BFN::LoweredParser *p) override;
156 bool preorder(const IR::MAU::Table *t) override;
157 void postorder(const IR::MAU::Table *t) override;
158 bool preorder(const IR::MAU::Primitive *prim) override;
159 bool preorder(const IR::MAU::Action *p) override;
160 bool preorder(const IR::MAU::StatefulAlu *prim) override;
161 bool preorder(const IR::Expression *e) override;
162 bool preorder(const IR::BFN::AbstractDeparser *d) override;
163 void postorder(const IR::BFN::AbstractDeparser *d) override;
164 FieldDefUse *clone() const override { return new FieldDefUse(*this); }
165 void flow_merge(Visitor &) override;
166 void flow_copy(::ControlFlowVisitor &) override;
167 FieldDefUse(const FieldDefUse &) = default;
168 FieldDefUse(FieldDefUse &&) = default;
169 void shadow_previous_ranges(FieldDefUse::info &, le_bitrange &);
170 friend std::ostream &operator<<(std::ostream &, const FieldDefUse::info &);
171 friend void dump(const FieldDefUse::info &);
172 friend std::ostream &operator<<(std::ostream &, const FieldDefUse &);
173 std::ostream &dotgraph(std::ostream &) const;
174
175 public:
176 explicit FieldDefUse(const PhvInfo &p)
177 : phv(p),
178 conflict(*new SymBitMatrix),
179 uses(*new std::remove_reference<decltype(uses)>::type),
180 defs(*new std::remove_reference<decltype(defs)>::type),
181 ixbar_refs(*new std::remove_reference<decltype(ixbar_refs)>::type),
182 located_uses(*new std::remove_reference<decltype(located_uses)>::type),
183 located_defs(*new std::remove_reference<decltype(located_defs)>::type),
184 output_deps(*new std::remove_reference<decltype(output_deps)>::type),
185 parser_zero_inits(*new std::remove_reference<decltype(parser_zero_inits)>::type),
186 uninitialized_fields(*new std::remove_reference<decltype(uninitialized_fields)>::type) {
187 joinFlows = true;
188 visitDagOnce = false;
189 BackwardsCompatibleBroken = true;
190 }
191
192 // TODO: unused?
193 // const SymBitMatrix &conflicts() { return conflict; }
194
195 const LocPairSet &getDefs(locpair use) const {
196 return defs.count(use) ? defs.at(use) : emptyset;
197 }
198 const LocPairSet &getDefs(const IR::BFN::Unit *u, const IR::Expression *e) const {
199 return getDefs(locpair(u, e));
200 }
201 const LocPairSet &getDefs(const Visitor *v, const IR::Expression *e) const {
202 return getDefs(locpair(v->findOrigCtxt<IR::BFN::Unit>(), e));
203 }
204
206 const LocPairSet getAllDefsAndUses(int fid) const {
207 LocPairSet defsnuses;
208 if (located_defs.count(fid)) defsnuses |= located_defs.at(fid);
209 if (located_uses.count(fid)) defsnuses |= located_uses.at(fid);
210 return defsnuses;
211 }
212
215 if (!f) return {};
216 return getAllDefsAndUses(f->id);
217 }
218
220 const LocPairSet &getAllDefs(int fid) const {
221 return located_defs.count(fid) ? located_defs.at(fid) : emptyset;
222 }
223
224 const ordered_map<int, LocPairSet> &getAllDefs() const { return located_defs; }
225
226 LocPairSet getParserDefs(const PHV::Field *f, std::optional<le_bitrange> bits) const;
227 LocPairSet getParserDefs(const PHV::FieldSlice &fs) const {
228 return getParserDefs(fs.field(), fs.range());
229 }
230
231 const LocPairSet &getUses(locpair def) const {
232 return uses.count(def) ? uses.at(def) : emptyset;
233 }
234 const LocPairSet &getUses(const IR::BFN::Unit *u, const IR::Expression *e) const {
235 return getUses(locpair(u, e));
236 }
237 const LocPairSet &getUses(const Visitor *v, const IR::Expression *e) const {
238 return getUses(locpair(v->findOrigCtxt<IR::BFN::Unit>(), e));
239 }
241 const LocPairSet &getAllUses(int fid) const {
242 return located_uses.count(fid) ? located_uses.at(fid) : emptyset;
243 }
244 const ordered_map<int, LocPairSet> &getAllUses() const { return located_uses; }
245
247 const LocPairSet &getOutputDeps(locpair def) const {
248 return output_deps.count(def) ? output_deps.at(def) : emptyset;
249 }
250 const LocPairSet &getOutputDeps(const IR::BFN::Unit *u, const IR::Expression *e) const {
251 return getOutputDeps(locpair(u, e));
252 }
253 const LocPairSet &getOutputDeps(const Visitor *v, const IR::Expression *e) const {
254 return getOutputDeps(locpair(v->findOrigCtxt<IR::BFN::Unit>(), e));
255 }
256
257 const ordered_set<const PHV::Field *> &getUninitializedFields() const {
258 return uninitialized_fields;
259 }
260
261 bool hasNonDarkContext(locpair info) const {
262 if (ixbar_refs.count(info)) {
263 LOG4("\t ixbar_refs:" << ixbar_refs.size());
264 }
265
266 if (!ixbar_refs.count(info)) {
267 LOG5("\t\t ixbar_refs for expression " << info.second << " not found for unit "
268 << info.first
269 << ", but assuming it is non-dark");
270 return true;
271 }
272
273 return ixbar_refs.at(info);
274 }
275
276 bool hasUninitializedRead(int fid) const {
277 for (const auto &def : getAllDefs(fid)) {
278 auto *expr = def.second;
279 if (dynamic_cast<const ImplicitParserInit *>(expr) != nullptr)
280 if (getUses(def).size() > 0) return true;
281 }
282 return false;
283 }
284
286 bool isUsedInParser(const PHV::Field *f) const;
287 bool hasUseAt(const PHV::Field *f, const IR::BFN::Unit *u) const;
288 bool hasDefAt(const PHV::Field *f, const IR::BFN::Unit *u) const;
289 bool hasDefInParser(const PHV::Field *f, std::optional<le_bitrange> bits) const;
290 bool hasDefInParser(const PHV::FieldSlice &fs) const {
291 return hasDefInParser(fs.field(), fs.range());
292 }
293};
294
295 // end of group parde
296
297#endif /* _FIELD_DEFUSE_H_ */
Definition visitor.h:463
Definition node.h:94
Definition visitor.h:400
Definition symbitmatrix.h:27
Definition visitor.h:75
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
int id
Unique field ID.
Definition phv_fields.h:164
cstring name
Definition phv_fields.h:161
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
const le_bitrange & range() const override
Definition phv_fields.h:980
Definition phv_fields.h:1095
Definition tofino_write_context.h:24
static const std::unordered_set< cstring > write_by_parser
Definition field_defuse.h:30
const LocPairSet getAllDefsAndUses(const PHV::Field *f) const
Definition field_defuse.h:214
bool isUsedInParser(const PHV::Field *f) const
Definition common/field_defuse.cpp:614
std::pair< const IR::BFN::Unit *, const IR::Expression * > locpair
Definition field_defuse.h:82
const LocPairSet & getOutputDeps(locpair def) const
Definition field_defuse.h:247
const LocPairSet getAllDefsAndUses(int fid) const
Definition field_defuse.h:206
const LocPairSet & getAllUses(int fid) const
Definition field_defuse.h:241
const LocPairSet & getAllDefs(int fid) const
Definition field_defuse.h:220
Definition field_defuse.h:77
Definition field_defuse.h:43
Definition field_defuse.h:62
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void info(const int kind, const char *format, const T *node, Args &&...args)
Report info messages of type kind. Requires that the node argument have source info.
Definition lib/error.h:148
STL namespace.