P4C
The P4 Compiler
Loading...
Searching...
No Matches
static_entries_const_prop.h
1
19#ifndef BF_P4C_MAU_STATIC_ENTRIES_CONST_PROP_H_
20#define BF_P4C_MAU_STATIC_ENTRIES_CONST_PROP_H_
21
22#include "bf-p4c/mau/mau_visitor.h"
23
24using namespace P4;
25
26/*
27 In P4-16, user can specify constant static entries for table matches.
28 We can use these static entries to do constant propagation.
29 In example below, the assignment "hdr.b = hdr.a" introduces a header
30 validity assignment "hdr.b.$valid = hdr.a.$valid", which can be safely
31 reduced to "hdr.b.$valid = true". This reduces the instruction from
32 a two source instruction to a single source one, which is much friendly
33 for POV bits packing.
34
35 action rewrite_b() {
36 hdr.b = hdr.a;
37 hdr.a.setInvalid();
38 }
39
40 table decap {
41 key = {
42 hdr.a.isValid() : exact;
43 }
44
45 actions = {
46 rewrite_b;
47 }
48
49 const entries = {
50 { true } : rewrite_b();
51 }
52 }
53
54 The same applies for keyless table that is predicated by a gateway TODO
55
56 table decap {
57 actions = {
58 rewrite_b;
59 }
60 }
61
62 if (hdr.a.isValid()) {
63 decap.apply();
64 }
65*/
66
68 const PhvInfo &phv;
69
70 public:
71 explicit StaticEntriesConstProp(const PhvInfo &phv) : phv(phv) {}
72
73 bool equiv(const IR::MethodCallExpression *mc, const IR::MAU::Action *ac) {
74 if (mc && ac) {
75 if (auto path = mc->method->to<IR::PathExpression>()) {
76 if (path->path->name == ac->name) {
77 return true;
78 }
79 }
80 }
81 return false;
82 }
83
84 bool preorder(IR::MAU::Instruction *instr) override {
85 auto table = findContext<IR::MAU::Table>();
86 if (table->is_compiler_generated || table->entries_list == nullptr) return false;
87
88 auto action = findContext<IR::MAU::Action>();
89
90 for (unsigned i = 0; i < instr->operands.size(); i++) {
91 if (i == 0) continue;
92
93 // Must be PHV. See bug check number 2 in verify_conditional_set_without_phv()
94 if ((i == 1) && (instr->name == "conditionally-set")) {
95 continue;
96 }
97
98 auto op = phv.field(instr->operands[i]);
99 if (!op) continue;
100
101 for (unsigned j = 0; j < table->match_key.size(); j++) {
102 if (table->match_key[j]->match_type.name != "exact") continue;
103
104 auto key = phv.field(table->match_key[j]->expr);
105 if (op == key) {
106 bool can_const_prop = false;
107 const IR::Expression *match = nullptr;
108 // Check if constant values for one same action in multi-entries are unique.
109 // Don't do constant propagation if not unique or it's a default action.
110 for (auto &ent : table->entries_list->entries) {
111 if (equiv(ent->action->to<IR::MethodCallExpression>(), action) &&
112 (action->init_default == false)) {
113 if (can_const_prop == false) {
114 // Assume can constant propagtion for the first entry.
115 match = ent->keys->components.at(j);
116 can_const_prop = true;
117 } else {
118 // Need to check if more than 1 entry with the same action.
119 auto cval = ent->keys->components.at(j);
120 if (!match->equiv(*cval)) {
121 can_const_prop = false;
122 break;
123 }
124 }
125 }
126 }
127
128 if (can_const_prop) {
129 LOG4("rewrite " << instr);
130 if (auto b = match->to<IR::BoolLiteral>()) {
131 instr->operands[i] = new IR::Constant(IR::Type::Bits::get(1), b->value);
132 } else if (auto c = match->to<IR::Constant>()) {
133 instr->operands[i] = c;
134 } else {
135 LOG4("unknown static entry match type");
136 }
137 LOG4("as " << instr);
138 }
139 }
140 }
141 }
142
143 return false;
144 }
145};
146
147#endif /* BF_P4C_MAU_STATIC_ENTRIES_CONST_PROP_H_ */
Definition mau_visitor.h:45
Definition phv_fields.h:1095
Definition static_entries_const_prop.h:67
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24