P4C
The P4 Compiler
Loading...
Searching...
No Matches
header_mutex.h
1
19#ifndef BACKENDS_TOFINO_BF_P4C_PHV_ANALYSIS_HEADER_MUTEX_H_
20#define BACKENDS_TOFINO_BF_P4C_PHV_ANALYSIS_HEADER_MUTEX_H_
21
22#include "bf-p4c/ir/gateway_control_flow.h"
23#include "bf-p4c/mau/mau_visitor.h"
24#include "bf-p4c/parde/parser_dominator_builder.h"
25#include "bf-p4c/parde/parser_info.h"
26#include "bf-p4c/phv/analysis/build_mutex.h"
27#include "ir/ir.h"
28#include "ir/visitor.h"
29
30enum HeaderState : uintmax_t {
31 UNKNOWN = 0,
32 INACTIVE = 1,
33 // ACTIVE has to be larger than INACTIVE because later we want to sort header name and header
34 // state pairs by header state value so that INACTIVE headers are ordered first.
35 ACTIVE = 2
36};
37const uint state_size = 2;
38const std::map<HeaderState, cstring> header_state_to_cstring = {
39 {UNKNOWN, "UNKNOWN"_cs}, {INACTIVE, "INACTIVE"_cs}, {ACTIVE, "ACTIVE"_cs}};
40
48struct HeaderInfo {
49 ordered_set<cstring> parser_headers;
50 ordered_set<cstring> mau_headers;
51 ordered_set<cstring> all_headers;
52 bitvec headers_always_encountered;
53 ordered_map<cstring, bitvec> headers_always_encountered_before;
54 ordered_map<cstring, bitvec> headers_always_encountered_after;
55 ordered_map<cstring, bitvec> headers_always_not_encountered_if_header_not_encountered;
56 ordered_map<const IR::MAU::Table *,
58 headers_live_during_action;
59 SymBitMatrix mutually_exclusive_headers;
60
61 size_t get_header_index(cstring header_name);
62 cstring get_header_name(size_t header_index);
63 void print_mutually_exclusive_headers();
64 void pretty_print_bitvec(bitvec bv);
65 void print_header_encounter_info();
66 void print_headers_live_during_action();
67 void clear();
68};
69
79 HeaderInfo &header_info;
80 bitvec headers_encountered;
81 SymBitMatrix mutually_inclusive_headers;
82
84 static bool ignore_field(const PHV::Field *field) {
85 return !field || field->pov || field->metadata;
86 }
87
88 void mark(const PHV::Field *field);
89
90 profile_t init_apply(const IR::Node *root) override;
91 bool preorder(const IR::MAU::TableSeq *) override { return false; }
92 bool preorder(const IR::BFN::Deparser *) override { return false; }
93 void flow_merge(Visitor &other_) override;
94 void flow_copy(::ControlFlowVisitor &other_) override;
95 void end_apply() override;
96
97 public:
98 AddParserHeadersToHeaderMutexMatrix(PhvInfo &phv, const bitvec &neverOverlay,
99 const PragmaNoOverlay &pragma, HeaderInfo &header_info)
100 : BuildMutex(phv, neverOverlay, pragma, ignore_field), header_info(header_info) {}
101 AddParserHeadersToHeaderMutexMatrix *clone() const override {
102 return new AddParserHeadersToHeaderMutexMatrix(*this);
103 }
104};
105
110 protected:
111 PhvInfo &phv;
112 cstring header_name(const IR::Member *member);
113 const PHV::Field *get_phv_field(const IR::Expression *expression);
114
115 public:
116 explicit HeaderNameMauInspector(PhvInfo &phv) : phv(phv) {}
117};
118
125 HeaderInfo &header_info;
126 bool &mau_contains_pov_read_write;
127 bool &mau_handles_parser_error;
128
129 ordered_set<const PHV::Field *> parser_err_fields;
130
131 profile_t init_apply(const IR::Node *root) override;
136 bool is_original_parser_err_field(const PHV::Field *field);
140 const PHV::Field *get_assigned_field();
146 bool is_parser_err(const PHV::Field *field);
152 bool preorder(const IR::Expression *expression) override;
156 void end_apply() override;
157
158 public:
159 FindPovAndParserErrorInMau(PhvInfo &phv, HeaderInfo &headers, bool &mau_contains_pov_read_write,
160 bool &mau_handles_parser_error)
162 header_info(headers),
163 mau_contains_pov_read_write(mau_contains_pov_read_write),
164 mau_handles_parser_error(mau_handles_parser_error) {}
165};
166
172 HeaderInfo &header_info;
173
174 void add_mau_headers_to_mutual_exclusive_headers();
175 profile_t init_apply(const IR::Node *root) override;
176
177 public:
178 explicit AddMauHeadersToHeaderMutexMatrix(HeaderInfo &header_info) : header_info(header_info) {}
179};
180
189 PhvInfo &phv;
190 HeaderInfo &header_info;
191
192 bool have_mutually_exclusive_fields(cstring header1, cstring header2);
193 void remove_header_mutexes_if_all_fields_not_mutex();
194 profile_t init_apply(const IR::Node *root) override;
195
196 public:
198 : phv(phv), header_info(header_info) {}
199};
200
208 PhvInfo &phv;
209 HeaderInfo &header_info;
210
212 state_to_headers;
214 header_to_states;
215
216 static bool ignore_field(const PHV::Field *field) {
217 return !field || field->pov || field->metadata;
218 }
219 bitvec get_headers_extracted_in_states(std::set<const IR::BFN::ParserState *> states);
220 bitvec get_surely_not_extracted(std::set<const IR::BFN::ParserState *> not_visited_states);
221 bitvec get_always_extracted();
222 SymBitMatrix get_flipped_bit_matrix(SymBitMatrix matrix);
223
224 profile_t init_apply(const IR::Node *root) override;
225 bool preorder(const IR::BFN::Extract *extract) override;
226
227 void build_header_encounter_maps();
228 void end_apply() override;
229
230 public:
232 : phv(phv), header_info(header_info) {}
233};
234
241 HeaderInfo &header_info;
242
243 bool has_const_entries(const IR::MAU::Table *table);
244 bool preorder(const IR::Member *member) override;
245
246 void end_apply() override;
247
248 public:
249 FindConstEntryTables(PhvInfo &phv, HeaderInfo &header_info)
250 : HeaderNameMauInspector(phv), header_info(header_info) {}
251};
252
259 PhvInfo &phv;
260
265
266 bool preorder(const IR::MAU::Table *table);
267 bool preorder(const IR::Expression *expression);
268
269 ordered_set<const IR::MAU::Table *> get_tables(bitvec tables_bv);
270 ordered_set<const PHV::Field *> get_fields(bitvec fields_bv);
271
272 bitvec get_all_tables_after(const IR::MAU::Table *table);
273 bitvec get_all_fields_referenced_after(const IR::MAU::Table *table);
274
275 ordered_set<const IR::MAU::Table *> get_next_tables(const IR::MAU::Table *table);
276 void build_next_table_bitvecs();
277 void print_next_table_bitvecs();
278 void print_fields_referenced();
279 void end_apply() override;
280
281 public:
282 bool is_deparsed_or_referenced_later(const IR::MAU::Table *table, const PHV::Field *field);
283
284 explicit FieldLevelOptimisation(PhvInfo &phv) : phv(phv) {}
285};
286
295 public TofinoWriteContext {
296 PhvInfo &phv;
297 HeaderInfo &header_info;
298 bool &mau_handles_parser_error;
299 const PragmaMutuallyExclusive &pa_mutex;
301 FieldLevelOptimisation &field_level_optimisation;
302
303 /* Data structure indicating which headers are active at a given point in MAU. Each header in
304 * the program is represented by 2 bits in the vector and is stored in the same order than in
305 * header_info.all_headers
306 */
307 bitvec active_headers;
308 ordered_map<cstring, bitvec> extracted_headers;
309 ordered_map<cstring, bitvec> not_extracted_headers;
310 SymBitMatrix parser_mutex_headers;
311 SymBitMatrix mutex_headers_modified;
312 cstring visiting_gateway_row_tag;
313 std::map<cstring, std::set<const IR::Expression *>> visiting_gateway_rows;
314 const IR::MAU::Table *visiting = nullptr;
315 cstring gress;
316
317 const PHV::Field *get_phv_field(const IR::Expression *expression);
318 HeaderState get_header_state(size_t header_index);
319 HeaderState get_header_state(cstring header_name);
320 void print_active_headers();
321 std::string get_active_headers();
322 void set_header_state(size_t header_index, HeaderState value);
323 void set_header_state(cstring header_name, HeaderState value);
324
325 bool preorder(const IR::BFN::Parser *parser) override {
326 gress = toString(parser->gress);
327 return false;
328 }
329
330 void pre_visit_table_next(const IR::MAU::Table *tbl, cstring tag) override;
331
332 ExcludeMAUNotMutexHeaders *clone() const override {
333 return new ExcludeMAUNotMutexHeaders(*this);
334 }
335
336 bool is_header(const PHV::Field *field) { return field && field->header() && !field->metadata; }
337 bool is_set(const IR::MAU::Primitive *primitive);
338 bool is_set_header_pov(const IR::MAU::Primitive *primitive);
339 bool is_set_header_valid(const IR::MAU::Primitive *primitive);
340 bool is_set_header_invalid(const IR::MAU::Primitive *primitive);
341 bool is_set_header_pov_to_other_header_pov(const IR::MAU::Primitive *primitive);
342 void init_active_headers();
343 void init_extracted_headers();
344 void init_not_extracted_headers();
345 profile_t init_apply(const IR::Node *root) override;
346
347 bool is_header_pov_lhs_constant_rhs_operation_relation(const IR::Operation_Relation *op_rel);
348 std::optional<std::pair<cstring, HeaderState>> get_header_to_state_pair_from_operation_relation(
349 const IR::Operation_Relation *op_rel);
350 std::optional<std::pair<const IR::Expression *, cstring>> get_gateway_row();
351 std::vector<std::pair<cstring, HeaderState>>
352 get_all_header_to_state_pairs_from_gateway_row_expression(const IR::Expression *gre);
353 bool preorder(const IR::Expression *) override;
354
355 void clear_row(cstring header, ordered_map<cstring, bitvec> &bit_matrix);
356 void clear_column(cstring header, ordered_map<cstring, bitvec> &bit_matrix);
357 void process_set_invalid(cstring header);
358 void record_modified_where(int i, int j);
359 ordered_set<std::pair<cstring, cstring>> process_set_valid(cstring header,
360 HeaderState state = ACTIVE);
361 void process_is_invalid(cstring header);
362 void process_is_valid(cstring header);
363
364 ordered_set<std::pair<cstring, cstring>> process_set_header_povs(const IR::MAU::Action *action);
365 std::string get_active_headers_change_table(
366 bitvec begin, bitvec mid, bitvec end, bool const_entries,
367 ordered_set<std::pair<cstring, cstring>> mutexes_removed);
368 bool preorder(const IR::MAU::Action *action) override;
369
370 void bitwise_and_bit_matrices(ordered_map<cstring, bitvec> &bit_matrix,
371 const ordered_map<cstring, bitvec> &other_bit_matrix);
372 void merge_active_headers(bitvec other_active_headers);
373 void flow_merge(Visitor &other_) override;
374 void flow_copy(::ControlFlowVisitor &other_) override;
375
376 bool can_preserve_field_mutex(
377 const PHV::Field *field1, const PHV::Field *field2,
378 const ordered_set<const IR::MAU::Table *> tables_affecting_header_mutex);
379 void end_apply() override;
380
381 public:
383 PhvInfo &phv, HeaderInfo &header_info, bool &mau_handles_parser_error,
384 const PragmaMutuallyExclusive &pa_mutex,
385 ordered_map<std::pair<int, int>, ordered_set<const IR::MAU::Table *>> &modified_where,
386 FieldLevelOptimisation &field_level_optimisation)
387 : phv(phv),
388 header_info(header_info),
389 mau_handles_parser_error(mau_handles_parser_error),
390 pa_mutex(pa_mutex),
391 modified_where(modified_where),
392 field_level_optimisation(field_level_optimisation) {}
393};
394
400class HeaderMutex : public PassManager {
401 private:
402 HeaderInfo header_info;
403 bool mau_contains_pov_read_write;
404 bool mau_handles_parser_error;
405
406 FieldLevelOptimisation field_level_optimisation;
408
409 public:
410 HeaderMutex(PhvInfo &phv, const bitvec &never_overlay, const PHV::Pragmas &pragmas)
411 : field_level_optimisation(phv) {
412 addPasses({new AddParserHeadersToHeaderMutexMatrix(phv, never_overlay,
413 pragmas.pa_no_overlay(), header_info),
414 new FindPovAndParserErrorInMau(phv, header_info, mau_contains_pov_read_write,
415 mau_handles_parser_error),
416 new AddMauHeadersToHeaderMutexMatrix(header_info),
417 new RemoveHeaderMutexesIfAllFieldsNotMutex(phv, header_info),
418 new PassIf(
419 [this]() {
420 // If there are no field mutexes to remove, the following
421 // passes would be redundant as they would do nothing.
422 return mau_contains_pov_read_write &&
423 !header_info.mutually_exclusive_headers.empty();
424 },
425 {new FindParserHeaderEncounterInfo(phv, header_info),
426 new FindConstEntryTables(phv, header_info), &field_level_optimisation,
427 new ExcludeMAUNotMutexHeaders(phv, header_info, mau_handles_parser_error,
428 pragmas.pa_mutually_exclusive(),
429 modified_where, field_level_optimisation)})});
430 }
431};
432
433#endif /* BACKENDS_TOFINO_BF_P4C_PHV_ANALYSIS_HEADER_MUTEX_H_ */
Add the headers added in MAU (not parsed) found by FindPovAndParserErrorInMau into the header mutual ...
Definition header_mutex.h:171
Collect every header encountered in the parser and insert them into HeaderInfo. Addtionally,...
Definition header_mutex.h:78
Definition gateway_control_flow.h:41
Definition build_mutex.h:63
Walk through MAU in control flow order and find header level mutually exclusivity in the parser that ...
Definition header_mutex.h:295
Using transitive closure of table flow graph, determine which PHV fields are referenced after a given...
Definition header_mutex.h:258
bool is_deparsed_or_referenced_later(const IR::MAU::Table *table, const PHV::Field *field)
If a PHV field is referenced after a given table or it is deparsed, return true.
Definition header_mutex.cpp:695
Find all tables which have a $valid or $stkvalid table key. If that table has const entries,...
Definition header_mutex.h:240
Find if any header $valid bits are read/written to and if parser errors are handled in MAU....
Definition header_mutex.h:124
After identifying which headers in the P4 program are mutually exclusive in the parser,...
Definition header_mutex.h:400
MauInspector that can get the header name of the PHV field being visited in the member.
Definition header_mutex.h:109
cstring header_name(const IR::Member *member)
From an IR::Member that is a header POV bit, get that header's name.
Definition header_mutex.cpp:181
Definition mau_visitor.h:29
Definition visitor.h:463
Definition node.h:95
Definition visitor.h:400
Definition ir/pass_manager.h:172
Definition ir/pass_manager.h:40
Definition symbitmatrix.h:27
Definition visitor.h:78
Definition visitor.h:75
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
bool pov
True if this Field is a validity bit.
Definition phv_fields.h:253
cstring header() const
Definition phv_fields.h:285
bool metadata
True if this Field is metadata.
Definition phv_fields.h:209
Definition phv_pragmas.h:46
Definition phv_fields.h:1095
Definition pa_mutually_exclusive.h:37
Definition pa_no_overlay.h:33
Many PHV field mutexes have already been removed due to other constraints prior to this pass....
Definition header_mutex.h:188
Definition tofino_write_context.h:24
Based on dominators and post-dominators of parser states, determines which other headers have also su...
Definition header_mutex.h:207
Builds parser graphs and determines the dominators and post-dominators of all parser states....
Definition parser_dominator_builder.h:43
Data structure containing information about which headers are present in the parser and MAU,...
Definition header_mutex.h:48