@@ -136,248 +136,6 @@ const IR::Node* LowerExpressions::postorder(IR::Concat* expression) {
136
136
137
137
namespace {
138
138
139
- /* *
140
- A list of assignments that all write to a "variable".
141
- This really only handles scalar variables.
142
- It is customized for the needs of FixupChecksum.
143
- */
144
- struct VariableWriters {
145
- std::set<const IR::AssignmentStatement*> writers;
146
- VariableWriters () = default ;
147
- explicit VariableWriters (const IR::AssignmentStatement* writer)
148
- { writers.emplace (writer); }
149
- VariableWriters* join (const VariableWriters* other) const {
150
- auto result = new VariableWriters ();
151
- result->writers = writers;
152
- for (auto e : other->writers )
153
- result->writers .emplace (e);
154
- return result;
155
- }
156
- /* *
157
- This function returns a non-null value only if there is exaclty one writer statement.
158
- In that case it returns the RHS of the assignment
159
- */
160
- const IR::Expression* substitution () const {
161
- if (writers.size () != 1 )
162
- return nullptr ;
163
- auto first = *writers.begin ();
164
- return first->right ;
165
- }
166
- };
167
-
168
- /* *
169
- Maintains a map from variable names to VariableWriters
170
- It is customized for the needs of FixupChecksum.
171
- */
172
- struct VariableDefinitions {
173
- std::map<cstring, const VariableWriters*> writers;
174
- VariableDefinitions (const VariableDefinitions& other) = default ;
175
- VariableDefinitions () = default ;
176
- VariableDefinitions* clone () const {
177
- return new VariableDefinitions (*this );
178
- }
179
- VariableDefinitions* join (const VariableDefinitions* other) const {
180
- auto result = clone ();
181
- for (auto e : other->writers ) {
182
- auto &prev = result->writers [e.first ];
183
- prev = prev ? prev->join (e.second ) : e.second ;
184
- }
185
- return result;
186
- }
187
- void declare (const IR::Declaration_Variable* decl) {
188
- writers.emplace (decl->getName ().name , new VariableWriters ());
189
- }
190
- const VariableWriters* getWriters (const IR::Path* path) {
191
- if (path->absolute )
192
- return nullptr ;
193
- return ::get (writers, path->name .name );
194
- }
195
- VariableDefinitions* setDefinition (const IR::Path* path,
196
- const IR::AssignmentStatement* statement) {
197
- auto w = getWriters (path);
198
- if (w == nullptr )
199
- // Path does not represent a variable
200
- return this ;
201
- auto result = clone ();
202
- result->writers [path->name .name ] = new VariableWriters (statement);
203
- return result;
204
- }
205
- };
206
-
207
- /* *
208
- Maintain def-use information.
209
- It is customized for the needs of FixupChecksum.
210
- */
211
- struct PathSubstitutions {
212
- std::map<const IR::PathExpression*, const IR::Expression*> definitions;
213
- std::set<const IR::AssignmentStatement*> haveUses;
214
- PathSubstitutions () = default ;
215
- void add (const IR::PathExpression* path, const IR::Expression* expression) {
216
- definitions.emplace (path, expression);
217
- LOG3 (" Will substitute " << dbp (path) << " with " << expression);
218
- }
219
- const IR::Expression* get (const IR::PathExpression* path) const {
220
- return ::get (definitions, path);
221
- }
222
- void foundUses (const VariableWriters* writers) {
223
- for (auto w : writers->writers )
224
- haveUses.emplace (w);
225
- }
226
- void foundUses (const IR::AssignmentStatement* statement) {
227
- haveUses.emplace (statement);
228
- }
229
- bool hasUses (const IR::AssignmentStatement* statement) const {
230
- return haveUses.find (statement) != haveUses.end ();
231
- }
232
- };
233
-
234
- /* *
235
- See the SimpleCopyProp pass below for the context in which this
236
- analysis is run. We take advantage that some more complex code
237
- patterns have already been eliminated.
238
- */
239
- class Accesses : public Inspector {
240
- PathSubstitutions* substitutions;
241
- VariableDefinitions* currentDefinitions;
242
-
243
- bool notSupported (const IR::Node* node) {
244
- ::error (" %1%: not supported in checksum update control" , node);
245
- return false ;
246
- }
247
-
248
- public:
249
- explicit Accesses (PathSubstitutions* substitutions): substitutions(substitutions) {
250
- CHECK_NULL (substitutions); setName (" Accesses" );
251
- currentDefinitions = new VariableDefinitions ();
252
- }
253
-
254
- bool preorder (const IR::Declaration_Variable* decl) override {
255
- // we assume all variable declarations are at the beginning
256
- currentDefinitions->declare (decl);
257
- return false ;
258
- }
259
-
260
- // This is only invoked for read expressions
261
- bool preorder (const IR::PathExpression* expression) override {
262
- auto writers = currentDefinitions->getWriters (expression->path );
263
- if (writers != nullptr ) {
264
- if (auto s = writers->substitution ())
265
- substitutions->add (expression, s);
266
- else
267
- substitutions->foundUses (writers);
268
- }
269
- return false ;
270
- }
271
-
272
- bool preorder (const IR::AssignmentStatement* statement) override {
273
- visit (statement->right );
274
- if (statement->left ->is <IR::PathExpression>()) {
275
- auto pe = statement->left ->to <IR::PathExpression>();
276
- currentDefinitions = currentDefinitions->setDefinition (pe->path , statement);
277
- } else {
278
- substitutions->foundUses (statement);
279
- }
280
- return false ;
281
- }
282
-
283
- bool preorder (const IR::IfStatement* statement) override {
284
- visit (statement->condition );
285
- auto defs = currentDefinitions->clone ();
286
- visit (statement->ifTrue );
287
- auto afterTrue = currentDefinitions;
288
- if (statement->ifFalse != nullptr ) {
289
- currentDefinitions = defs;
290
- visit (statement->ifFalse );
291
- currentDefinitions = afterTrue->join (currentDefinitions);
292
- } else {
293
- currentDefinitions = defs->join (afterTrue);
294
- }
295
- return false ;
296
- }
297
-
298
- bool preorder (const IR::SwitchStatement* statement) override
299
- { return notSupported (statement); }
300
-
301
- bool preorder (const IR::P4Action* action) override
302
- { return notSupported (action); }
303
-
304
- bool preorder (const IR::P4Table* table) override
305
- { return notSupported (table); }
306
-
307
- bool preorder (const IR::ReturnStatement* statement) override
308
- { return notSupported (statement); }
309
-
310
- bool preorder (const IR::ExitStatement* statement) override
311
- { return notSupported (statement); }
312
- };
313
-
314
- class Replace : public Transform {
315
- const PathSubstitutions* substitutions;
316
- public:
317
- explicit Replace (const PathSubstitutions* substitutions): substitutions(substitutions) {
318
- CHECK_NULL (substitutions); setName (" Replace" ); }
319
-
320
- const IR::Node* postorder (IR::AssignmentStatement* statement) override {
321
- if (!substitutions->hasUses (getOriginal<IR::AssignmentStatement>()))
322
- return new IR::EmptyStatement ();
323
- return statement;
324
- }
325
-
326
- const IR::Node* postorder (IR::PathExpression* expression) override {
327
- auto repl = substitutions->get (getOriginal<IR::PathExpression>());
328
- if (repl != nullptr ) {
329
- Replace rpl (substitutions);
330
- auto recurse = repl->apply (rpl);
331
- return recurse;
332
- }
333
- return expression;
334
- }
335
- };
336
-
337
- /* *
338
- This analysis is only executed on the control which performs
339
- checksum update computations.
340
-
341
- This is a simpler variant of copy propagation; it just finds
342
- patterns of the form:
343
- tmp = X;
344
- ...
345
- out = tmp;
346
-
347
- then it substitutes the definition into the use.
348
- The LocalCopyPropagation pass does not do this, because
349
- it won't consider replacing definitions where the RHS has side-effects.
350
- Since the only method call we accept in the checksum update block
351
- is a checksum unit "get" method (this is not checked here, but
352
- in the json code generator), we know that this method has no side-effects,
353
- so we can safely reorder calls to methods.
354
- Also, this is run after eliminating struct and tuple operations,
355
- so we know that all assignments operate on scalar values.
356
- */
357
- class SimpleCopyProp : public PassManager {
358
- PathSubstitutions substitutions;
359
- public:
360
- SimpleCopyProp () {
361
- setName (" SimpleCopyProp" );
362
- passes.push_back (new Accesses (&substitutions));
363
- passes.push_back (new Replace (&substitutions));
364
- }
365
- };
366
-
367
- } // namespace
368
-
369
- const IR::Node* FixupChecksum::preorder (IR::P4Control* control) {
370
- if (updateChecksumBlocks->find (control->name ) != updateChecksumBlocks->end ()) {
371
- SimpleCopyProp scp;
372
- return control->apply (scp);
373
- }
374
- return control;
375
- }
376
-
377
- // //////////////////////////////////////////////////////////////////////////////////
378
-
379
- namespace {
380
-
381
139
/* *
382
140
Detect whether a Select expression is too complicated for BMv2.
383
141
Also used to detect complex expressions that are arguments
0 commit comments