P4C
The P4 Compiler
Loading...
Searching...
No Matches
collect_parser_usedef.h
1
19#ifndef BACKENDS_TOFINO_BF_P4C_PARDE_COLLECT_PARSER_USEDEF_H_
20#define BACKENDS_TOFINO_BF_P4C_PARDE_COLLECT_PARSER_USEDEF_H_
21
22#include <optional>
23
24#include "bf-p4c/common/utils.h"
25#include "bf-p4c/parde/dump_parser.h"
26#include "bf-p4c/parde/parde_utils.h"
27#include "bf-p4c/parde/parser_info.h"
28#include "bf-p4c/phv/phv_fields.h"
29
34namespace Parser {
35
36struct Def {
37 const IR::BFN::ParserState *state = nullptr;
38 const IR::BFN::InputBufferRVal *rval = nullptr;
39
40 Def(const IR::BFN::ParserState *s, const IR::BFN::InputBufferRVal *r) : state(s), rval(r) {}
41
42 bool equiv(const Def *other) const {
43 if (this == other) return true;
44 return (state->gress == other->state->gress) && (state->name == other->state->name) &&
45 (rval->equiv(*other->rval));
46 }
47
48 std::string print() const {
49 std::stringstream ss;
50 ss << " ( " << state->name << " : " << rval->range << " )";
51 return ss.str();
52 }
53};
54
55struct Use {
56 const IR::BFN::ParserState *state = nullptr;
57 const IR::BFN::SavedRVal *save = nullptr;
58 const IR::Expression *p4Source = nullptr;
59
60 Use(const IR::BFN::ParserState *s, const IR::BFN::SavedRVal *save) : state(s), save(save) {}
61
62 bool equiv(const Use *other) const {
63 if (this == other) return true;
64 return (state->gress == other->state->gress) && (state->name == other->state->name) &&
65 (save->equiv(*other->save));
66 }
67
68 std::string print() const {
69 std::stringstream ss;
70 ss << " [ " << state->name << " : " << save->source;
71 if (p4Source) ss << " " << p4Source;
72 ss << " ]";
73 return ss.str();
74 }
75};
76
77struct UseDef {
79
80 void add_def(const PhvInfo &phv, const Use *use, const Def *def) {
81 for (auto d : use_to_defs[use])
82 if (d->equiv(def)) return;
83
84 if (auto buf = use->save->source->to<IR::BFN::InputBufferRVal>()) {
85 BUG_CHECK(buf->range.size() == def->rval->range.size(),
86 "parser def and use size mismatch");
87 } else {
88 le_bitrange bits;
89 phv.field(use->save->source, &bits);
90 BUG_CHECK(bits.size() == def->rval->range.size(), "parser def and use size mismatch");
91 }
92
93 use_to_defs[use].push_back(def);
94 }
95
96 const Use *get_use(const IR::BFN::ParserState *state, const IR::BFN::SavedRVal *save,
97 const IR::BFN::Select *select) const {
98 auto temp = new Use(state, save);
99 if (select) temp->p4Source = select->p4Source;
100 for (auto &kv : use_to_defs)
101 if (kv.first->equiv(temp)) return kv.first;
102 return temp;
103 }
104
105 const Def *get_def(const Use *use, const IR::BFN::ParserState *def_state) const {
106 for (auto def : use_to_defs.at(use)) {
107 if (def_state == def->state) return def;
108 }
109 return nullptr;
110 }
111
112 std::string print(const Use *use) const {
113 std::stringstream ss;
114 ss << "use: " << use->print() << " -- defs: ";
115 for (auto def : use_to_defs.at(use)) ss << def->print() << " ";
116 return ss.str();
117 }
118
119 std::string print() const {
120 std::stringstream ss;
121 ss << "parser def use: " << std::endl;
122 for (auto &kv : use_to_defs) ss << print(kv.first) << std::endl;
123 return ss.str();
124 }
125};
126
127} // namespace Parser
128
129struct ParserUseDef : std::map<const IR::BFN::Parser *, Parser::UseDef> {};
130
132 const PhvInfo &phv;
133
134 explicit ResolveExtractSaves(const PhvInfo &phv) : phv(phv) {}
135
137 const PhvInfo &phv;
138 const IR::Expression *expr;
139 const IR::BFN::InputBufferRVal *rv = nullptr;
140
141 FindRVal(const PhvInfo &phv, const IR::Expression *f) : phv(phv), expr(f) {}
142
143 bool preorder(const IR::BFN::Extract *extract) override {
144 le_bitrange f_bits, x_bits;
145
146 auto f = phv.field(extract->dest->field, &f_bits);
147 auto x = phv.field(expr, &x_bits);
148
149 LOG4("Searching in extract: " << extract << ", f: " << f << ", x: " << x);
150 if (f == x) {
151 if (auto rval = extract->source->to<IR::BFN::InputBufferRVal>()) {
152 auto clone = rval->clone();
153
154 // Lines up source and dest (both can be field slices)
155 // The destination field, f, is in little endian, whereas the extract source
156 // in the input buffer is in big endian.
157 clone->range.lo -= f_bits.lo;
158 clone->range.hi += f->size - f_bits.hi - 1;
159
160 clone->range.lo = clone->range.hi - x_bits.hi;
161 clone->range.hi -= x_bits.lo;
162
163 rv = clone;
164 }
165 }
166
167 return false;
168 }
169 };
170
171 bool preorder(IR::BFN::Extract *extract) override {
172 auto state = findOrigCtxt<IR::BFN::ParserState>();
173 LOG4("state: " << state->name << ", extract: " << extract);
174 if (auto save = extract->source->to<IR::BFN::SavedRVal>()) {
175 if (auto rval = save->source->to<IR::BFN::InputBufferRVal>()) {
176 extract->source = rval;
177 } else {
178 FindRVal find_rval(phv, save->source);
179 state->apply(find_rval);
180
181 if (find_rval.rv) extract->source = find_rval.rv;
182
183 LOG4("Found rval: " << find_rval.rv);
184 }
185
186 if (extract->source->is<IR::BFN::SavedRVal>())
187 LOG4("cannot resolve?");
188 else
189 LOG4("as: " << extract->source);
190 }
191
192 return false;
193 }
194};
195
237 struct ResolveExtractConst : Modifier {
239 std::string message;
240 explicit AmbiguousPropagation(const char *msg) : message(msg) {}
241 };
242
243 const CollectParserInfo &parserInfo;
244
245 explicit ResolveExtractConst(const CollectParserInfo *pi) : parserInfo{*pi} {}
246
247 const IR::BFN::ConstantRVal *find_constant(const IR::BFN::Extract *extract,
248 const IR::BFN::ParserGraph &graph,
249 const IR::BFN::ParserState *state,
250 const bool start) {
251 std::vector<const IR::BFN::Extract *> defExtracts;
252 auto source = extract->source->to<IR::BFN::SavedRVal>()->source;
253
254 for (const auto &statement : state->statements) {
255 LOG4(" statement: " << statement);
256 if (auto ext = statement->to<IR::BFN::Extract>()) {
257 LOG4(" ext: " << ext);
258 if (start && *ext == *extract) {
259 LOG4(" ext: " << ext << " and extract: " << extract
260 << " are equal, breaking the loop!");
261 break;
262 }
263 if (source->equiv(*(ext->dest->field))) {
264 LOG4("source: " << source << " and dest: " << ext->dest->field
265 << " from ext: " << ext << " in state: " << state->name
266 << " are equal!");
267 defExtracts.push_back(ext);
268 }
269 }
270 }
271
272 if (!defExtracts.empty()) {
273 auto ext = defExtracts.back();
274 if (ext->source->is<IR::BFN::ConstantRVal>())
275 return ext->source->to<IR::BFN::ConstantRVal>();
276 else
277 throw AmbiguousPropagation("source is not a constant");
278 }
279
280 const IR::BFN::ConstantRVal *foundConstant = nullptr;
281
282 if (graph.predecessors().count(state)) {
283 for (const auto &predState : graph.predecessors().at(state)) {
284 LOG4("predState: " << predState);
285 auto ret = find_constant(extract, graph, predState, false);
286 if (ret) {
287 if (foundConstant) {
288 if (!foundConstant->equiv(*ret)) {
289 throw AmbiguousPropagation("multiple possible definitions");
290 }
291 } else {
292 // foundConstant == nullptr && ret->source->is<IR::BFN::ConstantRVal>()
293 foundConstant = ret;
294 }
295 }
296 }
297 }
298
299 return foundConstant;
300 }
301
302 bool preorder(IR::BFN::Extract *extract) override {
303 if (!extract->source->is<IR::BFN::SavedRVal>()) return false;
304
305 auto state = findOrigCtxt<IR::BFN::ParserState>();
306
307 LOG4("ResolveExtractConst extract: " << extract << ", in state: " << std::endl
308 << state);
309
310 const auto &graph = parserInfo.graph(state);
311
312 try {
313 auto foundConst = find_constant(extract, graph, state, true);
314 if (foundConst) {
315 LOG4("Propagating constant: " << foundConst << " to extract: " << extract);
316 extract->source = foundConst->clone();
317 LOG4("New extract is: " << extract);
318 } else {
319 LOG4("No constant to propagate found for extract: " << extract);
320 }
321 } catch (AmbiguousPropagation &e) {
322 LOG4("Can not propagate constant to extract: "
323 << extract << " in state: " << state->name << ", because of: " << e.message
324 << "!");
325 }
326
327 return false;
328 }
329 };
330
331 public:
333 : PassManager({new ResolveExtractConst(pi), pi}) {}
334};
335
341 const PhvInfo &phv;
342
343 explicit CollectDefs(const PhvInfo &phv) : phv(phv) {}
344
345 std::map<const IR::BFN::ParserState *, ordered_set<const IR::BFN::InputBufferRVal *>>
346 state_to_rvals;
347
348 std::map<const IR::BFN::InputBufferRVal *, ordered_set<const IR::Expression *>>
349 rval_to_lvals;
350
351 // Maps each state to a set of lvalues that are extracted in it from
352 // a input packet buffer
353 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>>
354 state_to_inp_buff_exts;
355
356 // Maps each state to a set of lvalues that are extracted in it from
357 // a constant
358 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>> state_to_const_exts;
359
360 // Maps each state to a set of lvalues that are extracted in it from
361 // somewhere else (possibly SavedRVal)
362 std::map<const IR::BFN::ParserState *, ordered_set<const PHV::Field *>> state_to_other_exts;
363
364 Visitor::profile_t init_apply(const IR::Node *root) override {
365 state_to_rvals.clear();
366 rval_to_lvals.clear();
367 state_to_inp_buff_exts.clear();
368 state_to_const_exts.clear();
369 state_to_other_exts.clear();
370 return ParserInspector::init_apply(root);
371 }
372
373 // TODO what if extract gets dead code eliminated?
374 // TODO this won't work if the extract is out of order
375 bool preorder(const IR::BFN::Extract *extract) override {
376 auto state = findContext<IR::BFN::ParserState>();
377 le_bitrange bits;
378 auto f = phv.field(extract->dest->field, &bits);
379
380 if (auto rval = extract->source->to<IR::BFN::InputBufferRVal>()) {
381 state_to_rvals[state].insert(rval);
382 rval_to_lvals[rval].insert(extract->dest->field);
383 state_to_inp_buff_exts[state].insert(f);
384
385 LOG4(state->name << " " << rval << " -> " << extract->dest->field);
386 } else if (extract->source->is<IR::BFN::ConstantRVal>()) {
387 state_to_const_exts[state].insert(f);
388 LOG4(state->name << " constant -> " << extract->dest->field);
389 } else {
390 state_to_other_exts[state].insert(f);
391 LOG4(state->name << " other -> " << extract->dest->field);
392 }
393
394 return false;
395 }
396 };
397
399 const PhvInfo &phv;
400 const CollectParserInfo &parser_info;
401 const CollectDefs &defs;
402
403 ParserUseDef &parser_use_def;
404
405 MapToUse(const PhvInfo &phv, const CollectParserInfo &pi, const CollectDefs &d,
406 ParserUseDef &parser_use_def)
407 : phv(phv), parser_info(pi), defs(d), parser_use_def(parser_use_def) {}
408
409 Visitor::profile_t init_apply(const IR::Node *root) override {
410 parser_use_def.clear();
411 return ParserInspector::init_apply(root);
412 }
413
414 // Checks if on each path to given state the value for expression saved
415 // is defined (this means that for a given state it needs to be defined
416 // in itself or each of its possible predecessors)
417 bool is_source_extracted_on_each_path_to_state(const IR::BFN::ParserGraph &graph,
418 const IR::BFN::ParserState *state,
419 const PHV::Field *saved) {
420 // The state sets the value to a value from input buffer
421 // => the value is defined after this point
422 if ((defs.state_to_inp_buff_exts.count(state) &&
423 defs.state_to_inp_buff_exts.at(state).count(saved)) ||
424 (defs.state_to_other_exts.count(state) &&
425 defs.state_to_other_exts.at(state).count(saved))) {
426 LOG6("State " << state->name << " extracts " << saved->name
427 << " from input buffer or other field");
428 return true;
429 // The state sets the value to a constant
430 // => the value is not defined after this point
431 } else if (defs.state_to_const_exts.count(state) &&
432 defs.state_to_const_exts.at(state).count(saved)) {
433 LOG6("State " << state->name << " extracts " << saved->name << " from a constant");
434 return false;
435 // This state does not change the value
436 // => check all of its predecessors
437 } else {
438 if (!graph.predecessors().count(state)) {
439 // FIXME (MichalKekely): This should return false! Since we
440 // have not found any extract on this path yet and we cannot go
441 // any further back in the graph.
442 // However, currently this breaks egress metadata and extra parse
443 // states that are generated by the compiler (for example for mirrored
444 // packets some of the metadata are not "extracted").
445 LOG6("State " << state->name << " is the start state/entry point");
446 return true;
447 }
448 LOG6("State " << state->name << " does not extract " << saved->name
449 << ", checking predecessors");
450 for (auto const pred : graph.predecessors().at(state)) {
451 if (!is_source_extracted_on_each_path_to_state(graph, pred, saved)) {
452 LOG6("State's " << state->name << " predecessor " << pred->name
453 << " does not have " << saved->name
454 << " defined on all paths");
455 return false;
456 }
457 }
458 LOG6("State " << state->name << " has " << saved->name << " defined on all paths");
459 return true;
460 }
461 }
462
463 void add_def(ordered_set<Parser::Def *> &rv, const IR::BFN::ParserState *state,
464 const IR::BFN::InputBufferRVal *rval) {
465 if (rval->range.lo >= 0) {
466 auto def = new Parser::Def(state, rval);
467 rv.insert(def);
468 }
469 }
470
471 std::vector<std::pair<const IR::BFN::ParserState *, const IR::BFN::InputBufferRVal *>>
472 defer_defs_to_children(const IR::BFN::InputBufferRVal *rval,
473 const IR::BFN::ParserGraph &graph,
474 const IR::BFN::ParserState *use_state,
475 const IR::BFN::ParserState *def_state, const PHV::Field *field,
476 const PHV::Field *saved, const le_bitrange &field_bits,
477 const le_bitrange &saved_bits) {
478 if (def_state == use_state) return {};
479
480 // Adjust the rval
481 auto def_rval = rval->clone();
482 if (saved_bits.size() != field_bits.size()) {
483 auto nw_f_bits = field_bits.toOrder<Endian::Network>(field->size);
484 auto nw_s_bits = saved_bits.toOrder<Endian::Network>(saved->size);
485
486 auto full_rval = rval->clone();
487 full_rval->range.lo -= nw_f_bits.lo;
488 full_rval->range.hi += field->size - nw_f_bits.hi + 1;
489
490 def_rval = full_rval->clone();
491 def_rval->range.lo += nw_s_bits.lo;
492 def_rval->range.hi -= saved->size - nw_s_bits.hi + 1;
493 }
494
495 // Check whether we can defer to the children
496 bool def_deferred = false;
497 bool def_invalid = false;
498 std::vector<std::pair<const IR::BFN::ParserState *, const IR::BFN::InputBufferRVal *>>
499 new_defs;
500 for (const auto *trans : def_state->transitions) {
501 if (trans->loop) {
502 def_invalid = true;
503 break;
504 }
505
506 if (!trans->next) continue;
507 if (!graph.is_reachable(trans->next, use_state)) continue;
508
509 auto *shifted_rval = def_rval->apply(ShiftPacketRVal(trans->shift * 8, true))
510 ->to<IR::BFN::InputBufferRVal>();
511 def_deferred = true;
512 def_invalid |= shifted_rval->range.lo < 0;
513 new_defs.push_back(std::make_pair(trans->next, shifted_rval));
514 }
515
516 if (def_deferred && !def_invalid) return new_defs;
517
518 return {};
519 }
520
521 // defs have absolute offsets from current state
522 ordered_set<Parser::Def *> find_defs(const IR::BFN::InputBufferRVal *rval,
523 const IR::BFN::ParserGraph &graph,
524 const IR::BFN::ParserState *state) {
526
527 if (rval->range.lo < 0) { // def is in an earlier state
528 if (graph.predecessors().count(state)) {
529 for (auto pred : graph.predecessors().at(state)) {
530 for (auto t : graph.transitions(pred, state)) {
531 auto shift = t->shift;
532
533 auto shifted_rval = rval->apply(ShiftPacketRVal(-(shift * 8), true));
534 auto defs = find_defs(shifted_rval->to<IR::BFN::InputBufferRVal>(),
535 graph, pred);
536
537 for (auto def : defs) rv.insert(def);
538 }
539 }
540 }
541
542 return rv;
543 } else if (rval->range.lo >= 0) { // def is in this state
544 add_def(rv, state, rval);
545 }
546
547 return rv;
548 }
549
550 // multiple defs in earlier states with no absolute offsets from current state
551 ordered_set<Parser::Def *> find_defs(const IR::Expression *saved,
552 const IR::BFN::ParserGraph &graph,
553 const IR::BFN::ParserState *state) {
555
556 for (auto &kv : defs.state_to_rvals) {
557 auto def_state = kv.first;
558
559 if (def_state == state || graph.is_ancestor(def_state, state)) {
560 for (auto rval : kv.second) {
561 for (auto lval : defs.rval_to_lvals.at(rval)) {
562 le_bitrange s_bits, f_bits;
563 auto f = phv.field(lval, &f_bits);
564 auto s = phv.field(saved, &s_bits);
565
566 if (f == s) {
567 auto child_rvals = defer_defs_to_children(
568 rval, graph, state, def_state, f, s, f_bits, s_bits);
569
570 if (child_rvals.size()) {
571 for (auto &[def_state, rval] : child_rvals)
572 add_def(rv, def_state, rval);
573 } else {
574 if (s_bits.size() == f_bits.size()) {
575 add_def(rv, def_state, rval);
576 } else {
577 auto nw_f_bits = f_bits.toOrder<Endian::Network>(f->size);
578 auto nw_s_bits = s_bits.toOrder<Endian::Network>(s->size);
579
580 auto full_rval = rval->clone();
581 full_rval->range.lo -= nw_f_bits.lo;
582 full_rval->range.hi += f->size - nw_f_bits.hi + 1;
583
584 auto slice_rval = full_rval->clone();
585 slice_rval->range.lo += nw_s_bits.lo;
586 slice_rval->range.hi -= s->size - nw_s_bits.hi + 1;
587
588 add_def(rv, def_state, slice_rval);
589 }
590 }
591 }
592 }
593 }
594 }
595 }
596
597 return rv;
598 }
599
600 bool preorder(const IR::BFN::SavedRVal *save) override {
601 auto parser = findOrigCtxt<IR::BFN::Parser>();
602 auto state = findOrigCtxt<IR::BFN::ParserState>();
603 auto select = findOrigCtxt<IR::BFN::Select>();
604
605 auto &graph = parser_info.graph(parser);
606
607 auto use = parser_use_def[parser].get_use(state, save, select);
608
610
611 if (auto buf = save->source->to<IR::BFN::InputBufferRVal>())
612 defs = find_defs(buf, graph, state);
613 else
614 defs = find_defs(save->source, graph, state);
615
616 for (auto def : defs) parser_use_def[parser].add_def(phv, use, def);
617
618 if (!select) return false;
619
620 le_bitrange bits;
621 auto f = phv.field(save->source, &bits);
622 // Check if the value used in select is defined on each path to this state
623 // (defined in this case means that it is assigned a value from a input packet
624 // buffer, which is not rewritten by any other value since Tofino only
625 // supports loading a value from packet input buffer to match register)
626 if (!save->source->is<IR::BFN::InputBufferRVal>() &&
627 !is_source_extracted_on_each_path_to_state(graph, state, f)) {
628 ::fatal_error(
629 "Value used in select statement needs to be set "
630 "from input packet (not a constant) for every possible path "
631 "through the parse graph. This does not hold true for: %1%",
632 use->print());
633 }
634
635 if (!parser_use_def[parser].use_to_defs.count(use))
636 ::fatal_error("Use of uninitialized parser value in a select statement %1%. ",
637 use->print());
638
639 LOG4(parser_use_def[parser].print(use));
640
641 return false;
642 }
643
644 bool preorder(const IR::BFN::Parser *parser) override {
645 parser_use_def[parser] = {};
646
647 std::stringstream ss;
648 ss << "MapToUse parser:" << std::endl;
649 parser->dbprint(ss);
650 ss << std::endl << std::endl;
651 LOG4(ss.str());
652
653 return true;
654 }
655 };
656
657 void end_apply() override {
658 for (auto &kv : parser_use_def) {
659 LOG3(kv.first->gress << " parser:");
660 LOG3(parser_use_def[kv.first].print());
661 }
662 }
663
664 explicit CollectParserUseDef(const PhvInfo &phv, const CollectParserInfo &parser_info) {
665 auto collect_defs = new CollectDefs(phv);
666 addPasses({
667 collect_defs,
668 new MapToUse(phv, parser_info, *collect_defs, parser_use_def),
669 });
670 }
671
672 ParserUseDef parser_use_def;
673};
674
676 const CollectParserInfo &parser_info;
677 const ParserUseDef &parser_use_def;
678
680 : parser_info(pi), parser_use_def(ud) {}
681
682 const IR::BFN::InputBufferRVal *get_absolute_def(const IR::BFN::SavedRVal *save) {
683 auto parser = findOrigCtxt<IR::BFN::Parser>();
684 auto state = findOrigCtxt<IR::BFN::ParserState>();
685 auto select = findOrigCtxt<IR::BFN::Select>();
686
687 auto use = parser_use_def.at(parser).get_use(state, save, select);
688
689 if (parser_use_def.at(parser).use_to_defs.count(use) == 0) {
690 LOG4("No defs for use: " << use->print());
691 return nullptr;
692 }
693
694 auto defs = parser_use_def.at(parser).use_to_defs.at(use);
695
696 LOG4("defs.size(): " << defs.size()
697 << ", usedef: " << parser_use_def.at(parser).print(use));
698
699 if (defs.size() == 1) {
700 auto def = *defs.begin();
701 auto shifts = parser_info.get_all_shift_amounts(def->state, state);
702
703 LOG4("shifts->size(): " << shifts->size());
704 // if has single def of absolute offset, propagate to use
705 if (shifts->size() == 1) {
706 auto rval = def->rval->clone();
707
708 if (rval->is<IR::BFN::PacketRVal>()) {
709 auto shift = *shifts->begin();
710 rval->range = rval->range.shiftedByBits(-shift);
711 }
712
713 return rval;
714 }
715 }
716
717 return nullptr;
718 }
719
720 bool preorder(IR::BFN::SavedRVal *save) override {
721 if (save->source->is<IR::BFN::InputBufferRVal>()) return false;
722
723 auto orig = getOriginal<IR::BFN::SavedRVal>();
724
725 if (auto def = get_absolute_def(orig)) {
726 LOG4("propagate " << def << " to " << save->source);
727 save->source = def;
728 }
729
730 return false;
731 }
732};
733
735 bool preorder(const IR::BFN::Extract *extract) override {
736 if (extract->source->is<IR::BFN::SavedRVal>()) {
737 auto state = findContext<IR::BFN::ParserState>();
738
739 ::fatal_error(
740 "Unable to resolve extraction source."
741 " This is likely due to the source having no absolute offset from the"
742 " state %1%. %2%",
743 state->name, extract);
744 }
745
746 return false;
747 }
748};
749
750 // end of group ParserCopyProp
751
759 explicit ParserCopyProp(const PhvInfo &phv) {
760 auto *parserInfo = new CollectParserInfo;
761 auto *collectUseDef = new CollectParserUseDef(phv, *parserInfo);
762 auto *copyPropDef = new CopyPropParserDef(*parserInfo, collectUseDef->parser_use_def);
763
764 addPasses({LOGGING(4) ? new DumpParser("before_parser_copy_prop") : nullptr,
765 new ResolveExtractSaves(phv), parserInfo, new PropagateExtractConst(parserInfo),
766 collectUseDef, copyPropDef, new ResolveExtractSaves(phv),
768 LOGGING(4) ? new DumpParser("after_parser_copy_prop") : nullptr});
769 }
770};
771
772#endif /* BACKENDS_TOFINO_BF_P4C_PARDE_COLLECT_PARSER_USEDEF_H_ */
Definition node.h:95
Definition visitor.h:400
Definition visitor.h:372
Definition ir/pass_manager.h:40
Definition ir/pass_manager.h:145
Definition visitor.h:78
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
int size
Total size of Field in bits.
Definition phv_fields.h:194
cstring name
Definition phv_fields.h:161
Definition phv_fields.h:1095
Run ResolveExtractConst pass until every IR::BFN::ConstantRVal which can be propagated is propagated ...
Definition collect_parser_usedef.h:200
Definition collect_parser_usedef.h:734
Definition collect_parser_usedef.h:339
Definition collect_parser_usedef.h:675
Definition collect_parser_usedef.h:129
Definition collect_parser_usedef.h:131
bool is_reachable(const State *src, const State *dst) const
Definition parser_info.h:335
const std::set< int > * get_all_shift_amounts(const State *dst) const
Definition parser_info.h:791
bool is_ancestor(const State *src, const State *dst) const
Is "src" an ancestor of "dst"?
Definition parser_info.h:257
Dumps the entire parser graphs (can be used before and also after parser lowering).
Definition dump_parser.h:288
Definition parser_info.h:186
Definition parde_visitor.h:66
Definition parde_visitor.h:78
Definition collect_parser_usedef.h:340
Definition collect_parser_usedef.h:398
ClosedRange< Unit, DestOrder > toOrder(int spaceSize) const
Definition lib/bitrange.h:636
int lo
Definition lib/bitrange.h:694
ssize_t size() const
Definition lib/bitrange.h:539
int hi
Definition lib/bitrange.h:700
Definition collect_parser_usedef.h:36
Definition collect_parser_usedef.h:77
Definition collect_parser_usedef.h:55
Definition collect_parser_usedef.h:758
Definition collect_parser_usedef.h:136
Definition parde_utils.h:84