P4C
The P4 Compiler
Loading...
Searching...
No Matches
instruction_selection.h
1
18
19#ifndef BF_P4C_MAU_INSTRUCTION_SELECTION_H_
20#define BF_P4C_MAU_INSTRUCTION_SELECTION_H_
21
22#include "backends/tofino/bf-p4c/bf-p4c-options.h"
23#include "backends/tofino/bf-p4c/common/utils.h"
24#include "backends/tofino/bf-p4c/ir/tofino_write_context.h"
25#include "backends/tofino/bf-p4c/mau/mau_visitor.h"
26#include "backends/tofino/bf-p4c/mau/reduction_or.h"
27#include "backends/tofino/bf-p4c/phv/phv_fields.h"
28
29using namespace P4;
30
36class UnimplementedRegisterMethodCalls : public MauInspector {
37 bool preorder(const IR::MAU::Primitive *prim) override;
38
39 public:
40 UnimplementedRegisterMethodCalls() {}
41};
42
47class ToFunnelShiftInstruction : public MauTransform {
48 const IR::Expression *preorder(IR::Cast *) override;
49
50 public:
51 ToFunnelShiftInstruction() {}
52};
53
57class ConvertFunnelShiftExtern : public MauTransform {
58 const IR::Expression *preorder(IR::Primitive *) override;
59
60 public:
61 ConvertFunnelShiftExtern() {}
62};
63
69class HashGenSetup : public PassManager {
71 ordered_set<const IR::Expression *> hash_dist_injections;
72 const PhvInfo &phv;
73 const BFN_Options &options;
74
75 Visitor::profile_t init_apply(const IR::Node *node) override {
76 auto rv = PassManager::init_apply(node);
77 hash_gen_injections.clear();
78 hash_dist_injections.clear();
79 return rv;
80 }
81
85 class CreateHashGenExprs : public MauInspector, TofinoWriteContext {
86 HashGenSetup &self;
87 std::vector<const IR::Expression *> per_prim_hge;
88 bool preorder(const IR::MAU::StatefulAlu *) override { return false; }
89 bool preorder(const IR::BFN::SignExtend *) override;
90 bool preorder(const IR::Concat *) override;
91 bool preorder(const IR::Expression *) override;
92 bool preorder(const IR::Constant *) override;
93 bool preorder(const IR::MAU::Primitive *) override;
94 void postorder(const IR::MAU::Primitive *) override;
95
96 void check_for_symmetric(const IR::Declaration_Instance *decl, const IR::ListExpression *le,
98 bool isBetter(const IR::Expression *dest, const IR::Expression *a, const IR::Expression *b);
99
100 public:
101 explicit CreateHashGenExprs(HashGenSetup &s) : self(s) {}
102 };
103
107 class ScanHashDists : public MauInspector {
108 HashGenSetup &self;
109 bool preorder(const IR::MAU::StatefulAlu *) override { return false; }
110 bool preorder(const IR::Expression *) override;
111
112 public:
113 explicit ScanHashDists(HashGenSetup &s) : self(s) {}
114 };
115
119 class UpdateHashDists : public MauTransform {
120 HashGenSetup &self;
121 const IR::Expression *postorder(IR::Expression *) override;
122
123 public:
124 explicit UpdateHashDists(HashGenSetup &s) : self(s) {}
125 };
126
127 public:
128 explicit HashGenSetup(const PhvInfo &p, const BFN_Options &o) : phv(p), options(o) {
129 addPasses(
130 {new CreateHashGenExprs(*this), new ScanHashDists(*this), new UpdateHashDists(*this)});
131 }
132};
133
142class Synth2PortSetup : public MauTransform {
144 std::set<UniqueAttachedId> per_flow_enables;
145 std::map<UniqueAttachedId, IR::MAU::MeterType> meter_types;
146
148
149 const IR::MAU::Action *preorder(IR::MAU::Action *) override;
150 const IR::Node *postorder(IR::MAU::Primitive *) override;
151 const IR::MAU::Action *postorder(IR::MAU::Action *) override;
152
153 void clear_action() {
154 stateful.clear();
155 per_flow_enables.clear();
156 meter_types.clear();
157 }
158
159 public:
160 explicit Synth2PortSetup(const PhvInfo &) {}
161};
162
178class DoInstructionSelection : public MauTransform, TofinoWriteContext {
179 const PhvInfo &phv;
180 IR::MAU::Action *af = nullptr;
181 class SplitInstructions;
182 int synth_arg_num = 0;
183 const IR::MAU::TableSeq *ts = nullptr;
185
186 profile_t init_apply(const IR::Node *root) override;
187 const IR::MAU::HashDist *preorder(IR::MAU::HashDist *hd) override {
188 prune();
189 return hd;
190 }
191 const IR::GlobalRef *preorder(IR::GlobalRef *) override;
192 const IR::MAU::TableSeq *postorder(IR::MAU::TableSeq *) override;
193 const IR::MAU::Action *postorder(IR::MAU::Action *) override;
194 const IR::MAU::Action *preorder(IR::MAU::Action *) override;
195 const IR::MAU::SaluAction *preorder(IR::MAU::SaluAction *a) override {
196 prune();
197 return a;
198 }
199 const IR::Expression *postorder(IR::Add *) override;
200 const IR::Expression *postorder(IR::AddSat *) override;
201 const IR::Expression *postorder(IR::Sub *) override;
202 const IR::Expression *postorder(IR::SubSat *) override;
203 const IR::Expression *postorder(IR::Neg *) override;
204 const IR::Expression *postorder(IR::Shr *) override;
205 const IR::Expression *postorder(IR::Shl *) override;
206 const IR::Expression *postorder(IR::BAnd *) override;
207 const IR::Expression *postorder(IR::BOr *) override;
208 const IR::Expression *postorder(IR::BXor *) override;
209 const IR::Expression *postorder(IR::Cmpl *) override;
210 const IR::Expression *preorder(IR::BFN::SignExtend *) override;
211 const IR::Expression *preorder(IR::Concat *) override;
212 // const IR::Expression *postorder(IR::Cast *) override;
213 const IR::Expression *postorder(IR::Operation_Relation *) override;
214 const IR::Expression *postorder(IR::Mux *) override;
215 const IR::Slice *postorder(IR::Slice *) override;
216 const IR::Expression *postorder(IR::BoolLiteral *) override;
217 const IR::Node *postorder(IR::MAU::Primitive *) override;
218 const IR::MAU::Instruction *postorder(IR::MAU::Instruction *i) override { return i; }
219
220 bool checkPHV(const IR::Expression *);
221 bool checkActionBus(const IR::Expression *e);
222 bool checkSrc1(const IR::Expression *);
223 bool checkConst(const IR::Expression *ex, long &value);
224 bool equiv(const IR::Expression *a, const IR::Expression *b);
225 IR::Member *genIntrinsicMetadata(gress_t gress, cstring header, cstring field);
226
227 void limitWidth(const IR::Expression *);
228
229 public:
230 explicit DoInstructionSelection(const PhvInfo &phv) : phv(phv) {}
231};
232
239class StatefulAttachmentSetup : public PassManager {
240 const PhvInfo &phv;
241 const IR::TempVar *saved_tempvar = nullptr;
242 const IR::MAU::HashDist *saved_hashdist = nullptr;
243 typedef std::pair<const IR::MAU::AttachedMemory *, const IR::MAU::Table *> HashDistKey;
244 typedef std::pair<const IR::MAU::StatefulCall *, const IR::MAU::Table *> StatefulCallKey;
245 ordered_set<cstring> remove_tempvars;
246 ordered_set<cstring> copy_propagated_tempvars;
248 ordered_map<cstring, const IR::MAU::HashDist *> stateful_alu_from_hash_dists;
251 typedef IR::MAU::StatefulUse use_t;
253 action_use;
254 typedef std::pair<const IR::MAU::Synth2Port *, const IR::MAU::Table *> IndexCheck;
255 struct clear_info_t {
256 const IR::MAU::AttachedMemory *attached = 0;
257 bitvec clear_value;
258 uint32_t busy_value = 0;
259 };
262
263 ordered_set<IndexCheck> addressed_by_hash;
264 ordered_set<IndexCheck> addressed_by_index;
265
266 profile_t init_apply(const IR::Node *root) override {
267 remove_tempvars.clear();
268 copy_propagated_tempvars.clear();
269 remove_instr.clear();
270 stateful_alu_from_hash_dists.clear();
271 update_hd.clear();
272 return PassManager::init_apply(root);
273 }
274 class Scan : public MauInspector, TofinoWriteContext {
275 StatefulAttachmentSetup &self;
276 bool preorder(const IR::MAU::Action *) override;
277 bool preorder(const IR::MAU::Instruction *) override;
278 bool preorder(const IR::TempVar *) override;
279 bool preorder(const IR::MAU::HashDist *) override;
280 void postorder(const IR::MAU::Instruction *) override;
281 void postorder(const IR::MAU::Primitive *) override;
282 void postorder(const IR::MAU::Table *) override;
283 void setup_index_operand(const IR::Expression *index_expr,
284 const IR::MAU::Synth2Port *synth2port, const IR::MAU::Table *tbl,
285 const IR::MAU::StatefulCall *call);
286 void simpl_concat(std::vector<const IR::Expression *> &slices, const IR::Concat *concat);
287
288 public:
289 explicit Scan(StatefulAttachmentSetup &self) : self(self) {}
290 };
291 class Update : public MauTransform {
292 StatefulAttachmentSetup &self;
293 const IR::MAU::StatefulCall *preorder(IR::MAU::StatefulCall *) override;
294 const IR::MAU::BackendAttached *preorder(IR::MAU::BackendAttached *ba) override;
295 const IR::MAU::StatefulAlu *preorder(IR::MAU::StatefulAlu *salu) override;
296 const IR::MAU::Instruction *preorder(IR::MAU::Instruction *sp) override;
297
298 public:
299 explicit Update(StatefulAttachmentSetup &self) : self(self) {
300 dontForwardChildrenBeforePreorder = true;
301 }
302 };
303
304 const IR::MAU::HashDist *find_hash_dist(const IR::Expression *expr,
305 const IR::MAU::Primitive *prim);
306 IR::MAU::HashDist *create_hash_dist(const IR::Expression *e, const IR::MAU::Primitive *prim);
307
308 public:
309 explicit StatefulAttachmentSetup(const PhvInfo &p) : phv(p) {
310 addPasses({new Scan(*this), new Update(*this)});
311 }
312};
313
314class NullifyAllStatefulCallPrim : public MauModifier {
315 bool preorder(IR::MAU::StatefulCall *sc) override;
316
317 public:
318 NullifyAllStatefulCallPrim() {}
319};
320
324class BackendCopyPropagation : public MauTransform, TofinoWriteContext {
325 const PhvInfo &phv;
326 struct FieldImpact {
327 le_bitrange dest_bits;
328 const IR::Expression *read;
329
330 public:
331 FieldImpact(le_bitrange db, const IR::Expression *r) : dest_bits(db), read(r) {}
332 const IR::Expression *getSlice(bool isSalu, le_bitrange bits);
333 };
335 bool elem_copy_propagated = false;
336 IR::Vector<IR::MAU::Primitive> *split_set = nullptr;
337
338 const IR::Node *preorder(IR::Node *n) override {
339 visitOnce();
340 return n;
341 }
342 const IR::Node *preorder(IR::MAU::Instruction *i) override;
343 const IR::MAU::StatefulCall *preorder(IR::MAU::StatefulCall *sc) override {
344 prune();
345 return sc;
346 }
347 const IR::MAU::Action *preorder(IR::MAU::Action *a) override;
348 const IR::Expression *preorder(IR::Expression *a) override;
349 void update(const IR::MAU::Instruction *instr, const IR::Expression *e);
350 const IR::Expression *propagate(const IR::MAU::Instruction *instr, const IR::Expression *e);
351 const IR::MAU::Action *postorder(IR::MAU::Action *) override;
352
353 public:
354 explicit BackendCopyPropagation(const PhvInfo &p) : phv(p) { visitDagOnce = false; }
355};
356
361class VerifyParallelWritesAndReads : public MauInspector, TofinoWriteContext {
362 public:
364
365 private:
366 const PhvInfo &phv;
367 FieldWrites writes;
368
369 bool preorder(const IR::MAU::Action *) override;
370 void postorder(const IR::MAU::Instruction *) override;
371 bool preorder(const IR::MAU::StatefulCall *) override { return false; }
372 bool preorder(const IR::MAU::BackendAttached *) override { return false; }
373
374 public:
375 explicit VerifyParallelWritesAndReads(const PhvInfo &p) : phv(p) {}
376};
377
381class EliminateAllButLastWrite : public PassManager {
382 const PhvInfo &phv;
383
384 public:
387 // Store field and all its phv bits in current action. Used for handling overlapping set
389 // Need to handle overlapping set if it's set to true.
391
392 private:
393 class Scan : public MauInspector, TofinoWriteContext {
394 EliminateAllButLastWrite &self;
395 LastInstrMap last_instr_map;
396
397 bool preorder(const IR::MAU::Action *) override;
398 bool preorder(const IR::MAU::Instruction *) override;
399 bool preorder(const IR::MAU::StatefulCall *) override { return false; }
400 bool preorder(const IR::MAU::BackendAttached *) override { return false; }
401 void postorder(const IR::MAU::Action *) override;
402
403 public:
404 explicit Scan(EliminateAllButLastWrite &self) : self(self) {}
405 };
406
407 class Update : public MauTransform, TofinoWriteContext {
408 EliminateAllButLastWrite &self;
409 const IR::MAU::Action *current_af = nullptr;
410 const IR::MAU::Action *preorder(IR::MAU::Action *) override;
411 const IR::Node *preorder(IR::MAU::Instruction *) override;
412 const IR::MAU::StatefulCall *preorder(IR::MAU::StatefulCall *sc) override {
413 prune();
414 return sc;
415 }
416 const IR::MAU::BackendAttached *preorder(IR::MAU::BackendAttached *ba) override {
417 prune();
418 return ba;
419 }
420
421 public:
422 explicit Update(EliminateAllButLastWrite &self) : self(self) {}
423 };
424
425 public:
426 explicit EliminateAllButLastWrite(const PhvInfo &p) : phv(p) {
427 addPasses({new Scan(*this), new Update(*this)});
428 }
429};
430
499class ArithCompareAdjustment : public PassManager {
500 const PhvInfo &phv;
501
502 public:
503 std::map<const PHV::Field *, int> comp_adj_field_width_map;
504 std::map<const cstring, int> comp_adj_name_width_map;
505 std::map<const IR::MAU::Action *, std::set<const PHV::Field *>> comp_adj_fields_per_action_map;
506
507 private:
508 class Scan : public MauInspector {
509 ArithCompareAdjustment &self;
510 std::map<const PHV::Field *, bitvec> comp_or_set_zero_writes;
512 std::set<const PHV::Field *> other_targets;
513
514 bool preorder(const IR::MAU::Action *) override;
515 bool preorder(const IR::MAU::Instruction *) override;
516 bool preorder(const IR::MAU::StatefulCall *) override { return false; }
517 bool preorder(const IR::MAU::BackendAttached *) override { return false; }
518 void postorder(const IR::MAU::Action *) override;
519
520 public:
521 explicit Scan(ArithCompareAdjustment &self) : self(self) {}
522 };
523
524 class Update : public Transform {
525 private:
526 ArithCompareAdjustment &self;
527 const IR::MAU::Action *current_af = nullptr;
528 std::set<const PHV::Field *> comp_adj_fields;
529
530 const IR::MAU::Action *preorder(IR::MAU::Action *) override;
531 const IR::MAU::Instruction *preorder(IR::MAU::Instruction *) override;
532 const IR::Metadata *preorder(IR::Metadata *) override;
533 const IR::ConcreteHeaderRef *preorder(IR::ConcreteHeaderRef *) override;
534 const IR::Node *preorder(IR::Member *) override;
535 const IR::Type_StructLike *adjust_type_struct(const IR::Type_StructLike *, cstring name);
536 const IR::MAU::StatefulCall *preorder(IR::MAU::StatefulCall *sc) override {
537 prune();
538 return sc;
539 }
540 const IR::MAU::BackendAttached *preorder(IR::MAU::BackendAttached *ba) override {
541 prune();
542 return ba;
543 }
544 const IR::MAU::Action *postorder(IR::MAU::Action *) override;
545
546 public:
547 explicit Update(ArithCompareAdjustment &self) : self(self) {}
548 };
549
550 bool is_compare(cstring name) {
551 return name == "gtequ" || name == "gteqs" || name == "ltu" || name == "lts" ||
552 name == "lequ" || name == "leqs" || name == "gtu" || name == "gts" || name == "eq" ||
553 name == "neq" || name == "eq64" || name == "neq64";
554 }
555
556 public:
557 explicit ArithCompareAdjustment(const PhvInfo &p) : phv(p) {
558 addPasses({new Scan(*this), new Update(*this)});
559 }
560};
561
567class MeterSetup : public PassManager {
568 // Tracks the inputs per lpf
570 // Tracks the pre-color per meter
572 // Marks an action for setting a meter type
575 const PhvInfo &phv;
576
577 class Scan : public MauInspector {
578 MeterSetup &self;
579 void find_input(const IR::MAU::Primitive *);
580 void find_pre_color(const IR::MAU::Primitive *);
581 const IR::Expression *convert_cast_to_slice(const IR::Expression *);
582 profile_t init_apply(const IR::Node *root) override;
583 bool preorder(const IR::MAU::Instruction *) override;
584 bool preorder(const IR::MAU::Primitive *) override;
585
586 public:
587 explicit Scan(MeterSetup &self) : self(self) {}
588 };
589
590 class Update : public MauModifier {
591 MeterSetup &self;
592 void update_input(IR::MAU::Meter *);
593 void update_pre_color(IR::MAU::Meter *);
594 bool preorder(IR::MAU::Meter *) override;
595 bool preorder(IR::MAU::Action *) override;
596
597 public:
598 explicit Update(MeterSetup &self) : self(self) {}
599 };
600
601 public:
602 explicit MeterSetup(const PhvInfo &p) : phv(p) {
603 addPasses({new Scan(*this), new Update(*this)});
604 }
605};
606
607class SetupAttachedAddressing : public PassManager {
608 struct AttachedActionCoord {
609 bool all_per_flow_enabled = true;
610 bool all_same_meter_type = true;
611 bool meter_type_set = false;
612 IR::MAU::MeterType meter_type = IR::MAU::MeterType::UNUSED;
613 const IR::MAU::AttachedMemory *am = nullptr;
614 };
615
616 using AttachedInfo = std::map<UniqueAttachedId, AttachedActionCoord>;
617 // coordinate the Attached Info across all inspectors
619 // Just to run the modifier on BackendAttached Objects
621
622 class InitializeAttachedInfo : public MauInspector {
623 SetupAttachedAddressing &self;
624 bool preorder(const IR::MAU::BackendAttached *) override;
625
626 public:
627 explicit InitializeAttachedInfo(SetupAttachedAddressing &self) : self(self) {}
628 };
629
630 class ScanTables : public MauInspector {
631 SetupAttachedAddressing &self;
632 bool preorder(const IR::MAU::Table *) override;
633
634 public:
635 explicit ScanTables(SetupAttachedAddressing &self) : self(self) {}
636 };
637
638 class VerifyAttached : public MauInspector {
639 SetupAttachedAddressing &self;
640 bool preorder(const IR::MAU::BackendAttached *) override;
641
642 public:
643 explicit VerifyAttached(SetupAttachedAddressing &self) : self(self) {}
644 };
645
646 class UpdateAttached : public MauModifier {
647 SetupAttachedAddressing &self;
648 void simple_attached(IR::MAU::BackendAttached *);
649 bool preorder(IR::MAU::BackendAttached *) override;
650
651 public:
652 explicit UpdateAttached(SetupAttachedAddressing &self) : self(self) {}
653 };
654
655 public:
656 SetupAttachedAddressing() {
657 addPasses({new InitializeAttachedInfo(*this), new ScanTables(*this),
658 new VerifyAttached(*this), new UpdateAttached(*this)});
659 }
660};
661
662class RemoveUnnecessaryActionArgSlice : public MauTransform {
663 const IR::Node *preorder(IR::Slice *) override;
664
665 public:
666 RemoveUnnecessaryActionArgSlice() {}
667};
668
669class GuaranteeHashDistSize : public PassManager {
671
672 Visitor::profile_t init_apply(const IR::Node *node) override {
673 auto rv = PassManager::init_apply(node);
674 hash_dist_instrs.clear();
675 return rv;
676 }
677
678 class Scan : public MauInspector {
679 GuaranteeHashDistSize &self;
680 bool contains_hash_dist = false;
681
682 bool preorder(const IR::MAU::BackendAttached *) override { return false; }
683 bool preorder(const IR::MAU::StatefulCall *) override { return false; }
684 bool preorder(const IR::MAU::Instruction *) override;
685 bool preorder(const IR::MAU::HashDist *) override;
686 void postorder(const IR::MAU::Instruction *) override;
687
688 public:
689 explicit Scan(GuaranteeHashDistSize &s) : self(s) {}
690 };
691
692 class Update : public MauTransform {
693 GuaranteeHashDistSize &self;
694
695 const IR::Node *postorder(IR::MAU::Instruction *) override;
696
697 public:
698 explicit Update(GuaranteeHashDistSize &s) : self(s) {}
699 };
700
701 public:
702 GuaranteeHashDistSize() { addPasses({new Scan(*this), new Update(*this)}); }
703};
704
705class SimplifyConditionalActionArg : public MauTransform {
706 public:
707 SimplifyConditionalActionArg() {}
708 const IR::Node *postorder(IR::Mux *prim) override;
709};
710
711class InstructionSelection : public PassManager {
712 public:
714};
715
716#endif /* BF_P4C_MAU_INSTRUCTION_SELECTION_H_ */
Definition bf-p4c-options.h:28
Definition instruction_selection.cpp:621
InstructionSelection(const BFN_Options &, PhvInfo &, const ReductionOrInfo &)
Definition instruction_selection.cpp:3246
Definition mau_visitor.h:29
Definition mau_visitor.h:45
Definition mau_visitor.h:55
Definition node.h:94
Definition vector.h:59
Definition ltbitmatrix.h:25
Definition visitor.h:437
Definition visitor.h:78
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition safe_vector.h:27
Definition phv_fields.h:1095
Definition tofino_write_context.h:24
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition hash_function.h:28
Definition reduction_or.h:47